Initial revision
authorDavid Henkel-Wallace <gumby@cygnus>
Thu, 21 Mar 1991 21:11:25 +0000 (21:11 +0000)
committerDavid Henkel-Wallace <gumby@cygnus>
Thu, 21 Mar 1991 21:11:25 +0000 (21:11 +0000)
22 files changed:
bfd/COPYING [new file with mode: 0644]
bfd/ChangeLog [new file with mode: 0644]
bfd/Makefile [new file with mode: 0755]
bfd/TODO [new file with mode: 0644]
bfd/aout.c [new file with mode: 0755]
bfd/archive.c [new file with mode: 0644]
bfd/archures.c [new file with mode: 0644]
bfd/archures.h [new file with mode: 0755]
bfd/bfd.c [new file with mode: 0644]
bfd/cache.c [new file with mode: 0644]
bfd/coff-code.h [new file with mode: 0755]
bfd/coff-i960.c [new file with mode: 0644]
bfd/libaout.h [new file with mode: 0644]
bfd/libbfd.c [new file with mode: 0644]
bfd/libbfd.h [new file with mode: 0644]
bfd/libcoff.h [new file with mode: 0644]
bfd/misc.c [new file with mode: 0755]
bfd/misc.h [new file with mode: 0755]
bfd/opncls.c [new file with mode: 0644]
bfd/srec.c [new file with mode: 0644]
bfd/sunos.c [new file with mode: 0644]
bfd/targets.c [new file with mode: 0644]

diff --git a/bfd/COPYING b/bfd/COPYING
new file mode 100644 (file)
index 0000000..9a17037
--- /dev/null
@@ -0,0 +1,249 @@
+
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 1, 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
new file mode 100644 (file)
index 0000000..e9d10f6
--- /dev/null
@@ -0,0 +1,314 @@
+Tue Mar  5 01:47:57 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * coff-code.h (bfd_coff_swap_sym, bfd_coff_swap_aux,
+       bfd_coff_swap_lineno):  Export the routines that byte-swap COFF
+       symbol tables if necessary when reading them in, so gdb can use
+       them.  Add "bfd_coff_" to the names so they won't conflict with
+       names in calling programs.  FIXME-soon:  if coff-code.h is
+       included in two BFD modules, this will cause duplicate
+       definitions; the routines should be exported to a separate,
+       common, module (probably along with a mess of other ones).
+
+Sat Mar  2 12:11:26 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       Improve modtime support.
+
+       * bfd.h:  Add boolean mtime_set, and declare bfd_get_mtime.
+       Remove #define for bfd_get_mtime.  Remove gratuitous comment.
+       * bfd.c (bfd_get_mtime):  New fn, caches mtime, gets if not cached.
+       BUG:  archive members still do not get correct mod times.
+
+       Improve floating point support for core files.
+
+       * sunos.c (struct core):  Change void *fpa_dummy to double fp_stuff.
+       (sunos4_core_file_p):  Create a second registers section in the
+       core file, called ".reg2", for the float registers.
+
+Thu Feb 14 15:49:06 1991  Gumby Vinayak Wallace  (gumby at cygint.cygnus.com)
+
+       * many changes to improve archive handling; found a logic flaw in
+         bfd_check_format which only just happened to work by cooncidence.
+
+Thu Feb 14 07:53:16 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+       * bfd.c (bfd_perform_relocation): fixed to use output_offsets
+       correctly.
+       
+       * bfd.h: changed type of udata in asymbol to void *, like it
+       should be. Added bfd_reloc_dangerous enum member.
+
+       * coff-code.h: Fixed it so that internally generated symbols get
+       their values relocated correctly in all cases. Removed calls to
+       xmalloc.
+
+       * icoff.c: Not understanding the destination symbol of a reloc is
+       not a failure any more, just 'dangerous'. This allows linking of
+       b.out and coff images.
+
+       * sunos.c: Cleaned up the way that ZMAGIC section sizes are
+       calculated.
+
+
+Tue Feb 12 13:25:46 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+       * sunos.c (translate_to_native_sym_flags): fixed
+       sym_pointer->n_value so that symbols on the way out get their
+       section relative values calculated correctly.
+
+       * coff-code.h (mangle_symbols): fixed problem where tags were not
+       being relocated for structs, enums, unions. Also various lints.
+
+Mon Feb 11 19:52:26 1991  Gumby Vinayak Wallace  (gumby at cygint.cygnus.com)
+
+       * archive.c (get_elt_at_filepos): system_call_error returned
+         incorrectly.
+
+Sun Feb 10 23:18:40 1991  Gumby Vinayak Wallace  (gumby at cygint.cygnus.com)
+
+       * Resolve the use of no_error and system_call_error.
+         The bfd library itself now will never set bfd_error to
+         no_error.
+
+         The code still needs to be combed to make sure all the error
+         codes are correct.  I suspect they are not always set correctly.
+
+       * The names of all the messages have _ prepended because the sun
+         bundled compiler can't distinguish from a macro which takes an
+         argument and the same identifier in a non-macro context.
+
+       * The reason for the above being that entry points which used to
+         be trampoline functions are now just macros which expand to a
+         direct call through the bfd's xfer vector.
+
+       * (../include/intel-coff.h) F_AR32WR: fix this constant.  Why
+         must gas have its own version of everything (the gas version
+         had the correct value)
+
+Tue Feb  5 11:46:53 1991  Steve Chamberlain  (steve at cygint.cygnus.com)
+
+       * b.out.c: Added patches supplied by chrisb@mipon2.intel.com to
+       properly support i960 architecture and output correct reloc stuff.
+
+       * bfd.h: added prototype for bfd_printable_arch_mach, added
+       BFD_FAIL
+
+       * coff-code.h: Applied patches from chrisb to support i960
+       architecture, zero relocs and swap them correcly and conditionally
+       compiled the timestamp.
+
+       * sunos.c: Made the default section alignment 2^3 so that doubles
+       are done properly. Fixed the same reloc bug that was in b.out.c
+
+       * sysdep.h: Now compiles on a Posix box
+
+Wed Jan 30 21:36:26 1991  John Gilmore  (gnu at cygint.cygnus.com)
+
+       * icoff.c:  Fix comment on big-endian version.
+       * coff-code.h:  Make HAS_RELOC really work (it's backwards from
+       F_RELFLG).  Set F_AR32WR in output files if little endian
+       architecture.
+
+Tue Jan 29 20:56:10 PST 1991 steve@cygnus.com
+       
+       * archures.c fixed =/== typo
+       
+       * sunos.c added architecture stuff for output. Fixed
+       bug where files where vma(data) != size(text) 
+       were processed wrong.
+
+       * coff-code.h added a lint cast
+
+       * (../include/a.out.sun4.h) fixed it so zmagic
+       worked
+
+Mon Jan 28 19:15:29 PST 1991 steve@cygnus.com
+
+       * archive.c removed loads of includes, and fixed bug where string
+       table didn't have a null at the end.
+
+       * bfd.c fixed includes, added symbols argument to 
+       canonicalize_reloc entry point.
+
+       * libbfd.c fixed includes and added some lint patches.
+       
+       * targets.c added both sorts of intel coff.
+
+       * b.out.c fixed included, changed was the canonical
+       relocs were done.
+
+       * icoff.c added support for callj and big and little
+       enidian tables.
+
+       * opncls.c added chmod+xing for files with EXEC_P set.
+
+       * sunos.c fixed includes. Changed default section
+       alignement to words. Fixed relocation stuff to work with
+       new scheme
+
+       * bfd.h various new types added, prototype for new
+       reloc calls, changed bfd->iostream to a void *
+       to including files don't need stdio.h.
+
+       * libcoff.h added conversion table to tie relocs to
+       canonical symbols
+               
+       * sysdep.h created
+
+       * coff-code.h fixed includes. Added code to support
+       big and little endian formats. Various lints. Better
+       processing of symbols. Changed reloc stuff to new
+       order
+
+       * libbfd.h fixed includes
+
+
+Mon Jan 21 11:53:51 PST 1991 steve@cygnus.com
+       
+       * bfd.h changed name of alignment entry in sec_struct to
+       alignment_power, because of conflicting uses within bfd.
+       Now it should be obvious that it's a 2**n alignment
+       specifier. Removed start_pad, end_alignment, block, minsize,
+       output_file_alignment, subsection_alignment and original_vma fields.
+       Added align_power() macro. Fixed bfd_section_alignment
+       acessor macros. Added bfd_symbol_same_target macro.
+
+       * b.out.c (b_out_write_object_contents) fixed to use
+       new alignment member. Fixed (callj_callback) to use section
+       relative symbols properly.
+
+       * sunos.c (sunos4_object_p) fixed to use new alignment_power.
+       Fixed (translate_from_native_sym_flags) to correctly make       
+       symbols section relative.
+
+       * bfd.c (bfd_errmsg) fixed various enum cast problems. 
+       (bfd_make_section) took out initialization of obsolete members.
+       (bfd_print_symbol_vandf) added
+
+       * opncls.c (bfd_create) created.
+
+       * coff-code.h (coff_new_section_hook) took away refs
+       to obsolete members. (make_a_section_from_file) added
+       conversion between alignment types. (coff_symbol_from)
+       added. (coff_count_linenumbers) only counts linenumbers
+       if symbol is of coff-type. (coff_mangle_symbols) only
+       heavily mangles symbols if symbol is coff-type.
+       (coff_write_symbols) various lints. (coff_write_object_contents)
+       various lints and modification for alignment conversion.
+       (coff_slurp_relocs) fixed for use with new asection shape.
+
+Sat Jan 19 16:10:42 PST 1991 steve@cygnus.com
+
+       * archive.c lots of lint
+
+       * b.out.c added callj relocation support, upgrated reloc howto.
+       Fixed so that asymbol and reloc records are output 
+       correctly.
+
+       * bfd.c lots of lint, support for new bfd entry point
+       bfd_print_symbol.
+
+       * bfd.h changed definition of asymbol to contain pointer to
+       owning bfd, removed target dependencies.
+
+       * cache.c took out print statements, put in BFD_ASSERT calls.
+
+       * coff-code.h various lints, corrected linenumber output
+       functionality. Added support for new style asymbols and
+       bfd_print_symbol. Fixed so that asymbol and
+       reloc records are handled correctly. Added timestamp.
+
+       * icoff.c Added support for new howto shape.
+       
+       * liba.out.h Added support for new asymbol shape
+
+       * libbfd.c various lints
+
+       * libbfd.h various lints
+
+       * libcoff.h added support for new asymbol shape.
+
+       * sunos.c  various lints. Added support for new asymbol shape
+       and bfd_print_symbol.
+
+Wed Jan 16 21:38:09 PST 1991 steve@cygnus.com
+
+       * b.out.c removed prototype of sunos4_ennativate_symtab, lots of
+       pointer lint. Added support for callj relocation. Fixed bug where
+       the last 32 bytes of the text section were overwritten by data. Fixed bug
+       where archives of b.out didn't work due bfd_slurp_extended_name_table
+       returning false.
+
+       * sunos.c added support for n_other field. Braced the howto table so
+       that it won't be affected by any lengthing of the howto struct typedef.
+       Various lints
+
+       * bfd.h added support for n_other field, added special_function         
+       reloc type, modified bfd_perform_relocation prototype. Added bfd_h_get_x
+       macros.
+
+       * bfd.c upgraded bfd_perform_relocation, various lints.
+
+Wed Jan 16 01:55:53 1991  John Gilmore  (gnu at rtl)
+
+       * ChangeLog:  Started ChangeLog for BFD.
+       * ToDo:  Create file for suggestions.
+
+       * Makefile:  Support easy loading into Saber C.
+       Add dependencies for icoff.o and bcs88kcoff.o.
+       Rename coff.c to coff-code.h.  Change callers.
+
+       * bfd.c (bfd_check_format):  Allow the check_format routines
+       to return the desired target vector, rather than just a Boolean.
+       bfd.h (bfd_check_format):  Change function pointer return type.
+       archive.c (bfd_generic_archive_p):  change callee.
+       b.out.c (b_out_little_object_p, b_out_big_object_p,
+       b_out_real_object_p):  change callee.
+       libbfd.c (_bfd_dummy_target):  Dummy routine replacing bfd_false
+       in check_format transfer vectors that need a filler.
+       libbfd.h (bfd_generic_archive_p, _bfd_dummy_target):  Fix decls.
+       bcs88kcoff.c:  change callee.
+       coff-code.h (coff_real_object_p, coff_big_object_p):  change callee.
+       icoff.c:  change callee.
+       sunos.c (sunos4_object_p, sunos4_core_file_p):  change callee.
+
+       * libbfd.c (zalloc):  It should actually zero the storage!
+       This was commented out for some reason.
+
+       * libbfd.h:  Add malloc, xmalloc, memcpy, and fatal decls.
+       This is so callers can avoid <stdlib.h> which doesn't exist
+       on older systems.
+
+       * bfd.c (map_over_sections):  Add debugging code, since I
+       noticed the section count for sunos core files was bad, but only
+       GDB had detected the problem.
+       (bfd_set_section_lineno_size, bfd_set_section_linenos,
+       bfd_get_section_linenos):  Remove obsolete functions.
+       (bfd_apply_relocations):  Use longs, not ints, for the math.
+
+       * bfd.h:  Declare enum boolean and struct bfd_target as well
+       as typedefs for them.  Remove obsolete
+       bfd_get_section_lineno_size.
+
+       * cache.c:  Make the "fdopen" support work.  Keep better track
+       of how many files are open.  Centralize the opening of files
+       and be sure bfd_open[rw] actually try to open the file.  Evade
+       linked list initialization problems.
+
+       * b.out.c, coff-code.h, opncls.c, sunos.c:  lint.
+
+       * coff-code.h (coff_slurp_symbol_table):  Null-terminate symtab names.
+
+       * cplus-dem.c:  Delete file, since it is not part of BFD.
+
+       * opncls.c (bfd_openr):  Eliminate misplaced #if 0 code.
+       (bfd_openr, bfd_openw):  Actually open the file, give error now.
+       
+       * sunos.c (sunos4_core_file_p):  Set section count.
+       (sunos4_set_section_linenos, stab_names, fprint_name):  Eliminiate
+       obsolete definitions.
+       (_write_symbol_table):  Initialize <idx> counter.
+       (foop):  Eliminate debugging code.
+
+
+
+
diff --git a/bfd/Makefile b/bfd/Makefile
new file mode 100755 (executable)
index 0000000..54dfd90
--- /dev/null
@@ -0,0 +1,158 @@
+#
+# Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+#
+# This file is part of BFD, the Binary File Diddler.
+#
+# BFD 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 1, or (at your option)
+# any later version.
+#
+# BFD 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 BFD; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+# $Id$
+
+srcdir=.
+
+RANLIB = ranlib
+CSWITCHES = -g  # -Wall
+#CDEFINES = # -DHOST_SYS=AIX_SYS # -DCOFF_TIMESTAMP -DANSI_LIBRARIES
+INCDIR = ${srcdir}/../../include-cygnus
+CSEARCH = -I$(INCDIR)
+
+TARG = libbfd.a
+CFLAGS = $(CDEFINES) $(CSEARCH) $(CSWITCHES) -DINTEL960VERSION
+
+
+BFD_LIBS = libbfd.o opncls.o bfd.o archive.o targets.o cache.o archures.o
+
+BFD_BACKENDS = sunos.o icoff.o b.out.o # srec.o # bcs88kcoff.o
+
+BFD_H=$(INCDIR)/bfd.h
+SYSDEP_H=$(INCDIR)/sysdep.h
+
+# C source files that correspond to .o's.
+CFILES = libbfd.c opncls.c bfd.c archive.c targets.c cache.c archures.c \
+        sunos.c icoff.c b.out.c # srec.c # bcs88kcoff.c
+
+all: $(TARG) 
+
+POINTOS = $(BFD_LIBS) $(BFD_BACKENDS)
+
+$(TARG): $(POINTOS)
+        rm -f $(TARG)
+        ar clq $(TARG) $(BFD_LIBS) $(BFD_BACKENDS)
+        ranlib $(TARG)
+
+tags etags: TAGS
+
+TAGS: .force
+       etags $(INCDIR)/*.h *.h *.c
+
+clean:
+       rm -f $(BFD_LIBS) $(BFD_BACKENDS) *~ core libbfd.a
+
+clobber realclean: clean
+       rm -f libbfd.a TAGS
+
+$(BFD_LIBS) $(BFD_BACKENDS):  libbfd.h $(BFD_H)
+
+saber:
+       #suppress 65 on bfd_map_over_sections 
+       #suppress 66 on bfd_map_over_sections 
+       #suppress 67 on bfd_map_over_sections 
+       #suppress 68 on bfd_map_over_sections 
+       #suppress 69 on bfd_map_over_sections 
+       #suppress 70 on bfd_map_over_sections 
+       #suppress 110 in bfd_map_over_sections 
+       #suppress 112 in bfd_map_over_sections 
+       #suppress 530 
+       #suppress 590 in swap_exec_header 
+       #suppress 590 in _bfd_dummy_core_file_matches_executable_p 
+       #suppress 590 in bfd_dont_truncate_arname
+       #suppress 590 on ignore 
+       #suppress 590 on abfd 
+       #setopt load_flags $(CFLAGS)
+       #load $(CFILES)
+
+archive.o : archive.c libbfd.h $(BFD_H) $(SYSDEP_H)  
+archures.o : archures.c $(BFD_H) $(SYSDEP_H) archures.h 
+b.out.o : b.out.c libbfd.h $(BFD_H) $(SYSDEP_H) liba.out.h archures.h 
+bcs88kcoff.o : bcs88kcoff.c libbfd.h $(BFD_H) $(SYSDEP_H) libcoff.h coff-code.h archures.h 
+bfd.o : bfd.c libbfd.h $(BFD_H) $(SYSDEP_H)     
+cache.o : cache.c libbfd.h $(BFD_H) $(SYSDEP_H)     
+coff.o : coff.c  
+cplus-dem.o : cplus-dem.c  
+filemode.o : filemode.c 
+icoff.o : icoff.c libbfd.h $(BFD_H) $(SYSDEP_H) libcoff.h coff-code.h archures.h 
+libbfd.o : libbfd.c libbfd.h $(BFD_H) $(SYSDEP_H)      
+misc.o : misc.c 
+opncls.o : opncls.c libbfd.h $(BFD_H) $(SYSDEP_H)     
+sunos.o : sunos.c libbfd.h $(BFD_H) $(SYSDEP_H) liba.out.h
+targets.o : targets.c libbfd.h $(BFD_H) $(SYSDEP_H)      
+
+#-----------------------------------------------------------------------------
+#              '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
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+       @V=`cat VERSION`                ; \
+       MAJ=`sed 's/\..*//' VERSION`    ; \
+       MIN=`sed 's/.*\.//' VERSION`    ; \
+       V=$$MAJ.`expr $$MIN + 1`        ; \
+       rm -f VERSION                   ; \
+       echo $$V >VERSION               ; \
+       echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+.force:
+FORCE:
+
+# 'G960BASE' will be defined at invocation
+install:
+       make ${TARG} OPT=-O
+
+# 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 '\aSpecify "make make HOST=???"'; \
+               exit 1; \
+       fi ; \
+       grep -s "^#The next line was generated by 'make make'" Makefile; \
+       if test $$? = 0 ; then  \
+               echo "\aMakefile 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: ../common/Makefile
+       mv Makefile Makefile.backup
+       cp ../common/Makefile .
+       $(MAKE) "HOST=$(HOST)" make
diff --git a/bfd/TODO b/bfd/TODO
new file mode 100644 (file)
index 0000000..45cf905
--- /dev/null
+++ b/bfd/TODO
@@ -0,0 +1,49 @@
+Things that still need to be handled: -*- Text -*-
+
+ o - check all the swapping code.
+ o - change the memory usage to reflect the message which follows the
+     page break.
+ o - implement bfd_abort, which should close the bfd but not alter the
+     filesystem.
+ o - remove the following obsolete functions:
+        bfd_symbol_value
+        bfd_symbol_name
+        bfd_get_first_symbol
+        bfd_get_next_symbol
+        bfd_classify_symbol
+        bfd_symbol_hasclass
+ o - update the bfd doc; write a how-to-write-a-backend doc.
+ o - change reloc handling as per Steve's suggestion.
+
+\f
+Changing the way bfd uses memory.  The new convention is simple: 
+
+ o - bfd will never write into user-supplied memory, nor attempt to
+     free it.
+ o - closing a bfd may reclaim all bfd-allocated memory associated
+     with that bfd.
+ - - bfd_target_list will be the one exception; you must reclaim the
+     returned vector yourself.
+
+Interface implications are minor (get_symcount_upper_bound will go
+away; bfd_cannicalize_symtab will allocate its own memory, etc).
+
+Certain operations consume a lot of memory; for them manual
+reclaimation is available:
+
+ o - bfd_canonicalize_symtab will return a pointer to a
+     null-terminated vector of symbols.  Subsequent calls may or may
+     not return the same pointer.
+     bfd_canonicalize_relocs will do the same; returning a pointer to
+     an array of arelocs.  Calling this function will read symbols in
+     too.
+
+ o - bfd_reclaim_relocs will free the memory used by these relocs.
+     the symbols will be untouched.
+     bfd_reclaim_symtab (ne bfd_reclaim_symbol_table) will free the
+     memory allocated by canonialize_symtab.  
+     Since relocations point to symbols, any relocations obtained by a
+     call to bfd_canonicalize_relocs will be reclaimed as well.
+
+ o - if you don't call the reclaim_ functions, the memory will be
+     reclaimed at bfd_close time.
diff --git a/bfd/aout.c b/bfd/aout.c
new file mode 100755 (executable)
index 0000000..f857897
--- /dev/null
@@ -0,0 +1,1904 @@
+/*** bfd backend for sunos binaries */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$
+ * $Log$
+ * Revision 1.1  1991/03/21 21:11:23  gumby
+ * Initial revision
+ *
+ * Revision 1.2  1991/03/15  18:16:52  rich
+ * *** empty log message ***
+ *
+ * Revision 1.12  1991/03/10  19:11:41  rich
+ *  Modified Files:
+ *     bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
+ *
+ * Working bugs out of coff support.
+ *
+ * Revision 1.11  1991/03/09  03:40:04  rich
+ *  Modified Files:
+ *     Makefile b.out.c liba.out.h libbfd.c sunos.c sysdep.h
+ *
+ * Changes dictated by porting binutils.
+ *
+ * Revision 1.10  1991/03/08  07:52:02  sac
+ * Reinstalled things which went away after latest merge from Intel.
+ *
+ * Fixed a couple of problems in symbol handling too.
+ *
+ * Revision 1.9  1991/03/08  04:18:16  rich
+ * *** empty log message ***
+ *
+ * Revision 1.8  1991/03/07  21:57:26  sac
+ * Moved type info out of the asymbol into the private space.
+ * Cleaned up C++ stuff
+ *
+ * Revision 1.7  1991/03/06  21:49:02  sac
+ * Modified bfd_find_filename to return name of function too.
+ *
+ * Revision 1.6  1991/03/06  02:19:36  sac
+ * Moved howto table, added support for constructor sections and provided
+ * sunos4_find_nearest_line
+ *
+ * Revision 1.5  1991/03/05  16:25:44  sac
+ * Modified howto vector to include inplace and mask fields.
+ *
+ */
+
+#define TARGET_BYTE_ORDER_BIG_P 1
+#define TARGET TARGET_SPARC
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include <stdio.h>
+
+
+/*SUPPRESS558*/
+/*SUPPRESS529*/
+
+
+
+
+typedef void generic_symbol_type;
+/* These values are correct for the SPARC.  I dunno about anything else */
+#define PAGE_SIZE 0x02000
+#define SEGMENT_SIZE PAGE_SIZE
+#define TEXT_START_ADDR PAGE_SIZE
+#include "a.out.gnu.h"
+#include "stab.gnu.h"
+#include "ar.h"
+#include "liba.out.h"           /* BFD a.out internal data structures */
+
+#include "a.out.sun4.h"
+
+#define CTOR_TABLE_RELOC_IDX 2
+static  reloc_howto_type howto_table[] = 
+{
+  /* type                   rs   size bsz  pcrel bitpos  abs ovrf sf name partial inplace mask*/
+{ (unsigned int) RELOC_8,      0,  0,          8,  false, 0, true,  true,0,"8",        false, 0x000000ff},
+{ (unsigned int) RELOC_16,     0,  1,  16, false, 0, true,  true,0,"16",       false, 0x0000ffff},
+{ (unsigned int) RELOC_32,     0,  2,  32, false, 0, true,  true,0,"32",       false,  0xffffffff},
+{ (unsigned int) RELOC_DISP8,  0,  0,  8,  true,  0, false, true,0,"DISP8",    false, 0x000000ff},
+{ (unsigned int) RELOC_DISP16, 0,  1,  16, true,  0, false, true,0,"DISP16",   false, 0x0000ffff},
+{ (unsigned int) RELOC_DISP32, 0,  2,  32, true,  0, false, true,0,"DISP32",   false, 0xffffffff},
+{ (unsigned int) RELOC_WDISP30,2,  2,  30, true,  0, false, true,0,"WDISP30",  false, 0x3fffffff},
+{ (unsigned int) RELOC_WDISP22,2,  2,  22, true,  0, false, true,0,"WDISP22",  false, 0x003fffff},
+{ (unsigned int) RELOC_HI22,   10, 2,  22, false, 0, false, true,0,"HI22",     false, 0x003fffff},
+{ (unsigned int) RELOC_22,      0, 2,  22, false, 0, false, true,0,"22",       false, 0x003fffff},
+{ (unsigned int) RELOC_13,     0, 2,   13, false, 0, false, true,0,"13",       false, 0x00001fff},
+{ (unsigned int) RELOC_LO10,   0, 2,   10, false, 0, false, true,0,"LO10",     false, 0x000003ff},
+{ (unsigned int) RELOC_SFA_BASE,0, 2,  32, false, 0, false, true,0,"SFA_BASE", false, 0xffffffff},
+{ (unsigned int) RELOC_SFA_OFF13,0,2,  32, false, 0, false, true,0,"SFA_OFF13",false, 0xffffffff},
+{ (unsigned int) RELOC_BASE10, 0,  2,  16, false, 0, false, true,0,"BASE10",   false, 0x0000ffff},
+{ (unsigned int) RELOC_BASE13, 0,  2,  13, false, 0, false, true,0,"BASE13",   false, 0x00001fff},
+{ (unsigned int) RELOC_BASE22, 0,  2,  0,  false, 0, false, true,0,"BASE22",   false, 0x00000000},
+{ (unsigned int) RELOC_PC10,   0,  2,  10, false, 0, false, true,0,"PC10",     false, 0x000003ff},
+{ (unsigned int) RELOC_PC22,   0,  2,  22, false, 0, false, true,0,"PC22",     false, 0x003fffff},
+{ (unsigned int) RELOC_JMP_TBL,0,  2,  32, false, 0, false, true,0,"JMP_TBL",  false, 0xffffffff},
+{ (unsigned int) RELOC_SEGOFF16,0, 2,  0,  false, 0, false, true,0,"SEGOFF16", false, 0x00000000},
+{ (unsigned int) RELOC_GLOB_DAT,0, 2,  0,  false, 0, false, true,0,"GLOB_DAT", false, 0x00000000},
+{ (unsigned int) RELOC_JMP_SLOT,0, 2,  0,  false, 0, false, true,0,"JMP_SLOT", false, 0x00000000},
+{ (unsigned int) RELOC_RELATIVE,0, 2,  0,  false, 0, false, true,0,"RELATIVE", false, 0x00000000},
+{ (unsigned int) RELOC_JUMPTARG,2, 13, 16, true,  0, false, true,0,"JUMPTARG", false, 0x0000ffff},
+{ (unsigned int) RELOC_CONST,  0, 13,  16, false, 0, false, true,0,"CONST",    false, 0x0000ffff},
+{ (unsigned int) RELOC_CONSTH, 16, 13, 16, false, 0, false, true,0,"CONSTH",   false, 0x0000ffff},
+};
+
+/** a.out files */
+
+PROTO (static void, swap_exec_header, (bfd *abfd, struct exec *execp));
+PROTO (void , sunos4_write_syms, ());
+PROTO (static boolean,sunos4_squirt_out_relocs,(bfd *abfd, asection *section));
+
+/* Steve wants some way to frob this stuff from Saber while he's debugging
+   ld, so we have these funny shadow functions */
+/* ZMAGIC's start at 0 (making the exec part of the text section),
+  other formats start after the exec
+*/
+unsigned int n_txtoff(ptr)
+struct exec *ptr;
+{return N_MAGIC(*ptr)== ZMAGIC ? 0: sizeof(struct exec);}
+
+unsigned int n_datoff(ptr)
+struct exec *ptr;
+{return n_txtoff(ptr) + ptr->a_text;}
+
+unsigned int n_treloff(ptr)
+struct exec *ptr;
+{return n_datoff(ptr) + ptr->a_data;}
+
+unsigned int n_dreloff(ptr)
+struct exec *ptr;
+{return n_treloff(ptr) + ptr->a_trsize;}
+
+unsigned int n_symoff(ptr)
+struct exec *ptr;
+{return n_dreloff(ptr) + ptr->a_drsize;}
+
+unsigned int n_stroff(ptr)
+struct exec *ptr;
+{return n_symoff(ptr) + ptr->a_syms;}
+
+unsigned int n_badmag(ptr)
+     struct exec *ptr;
+{
+  switch (N_MAGIC(*ptr)) {
+  case OMAGIC: case NMAGIC: case ZMAGIC: return 0;
+  default: return 1;
+  }
+}
+
+
+bfd_target *
+sunos4_object_p (abfd)
+     bfd *abfd;
+{
+  unsigned long magic;
+  struct exec anexec;           /* save consing when you don't have to. */
+  struct exec *execp = &anexec;
+  void *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)&magic, 1, sizeof (magic), abfd) != sizeof (magic))
+    return 0;
+  magic = bfd_h_getlong (abfd, &magic);
+
+  /* Baroque syntax to mask deficiencies of the Sun compiler */
+  /* if (N_BADMAG (*((struct exec *) &magic))) return 0; */
+  if (n_badmag ((struct exec *) &magic)) return 0;
+
+  if (bfd_seek (abfd, 0L, SEEK_SET) < 0) return 0;
+
+  if (bfd_read ((void *) execp, 1, sizeof (struct exec), abfd)
+      != sizeof (struct exec)) {
+    bfd_error = wrong_format;
+    return 0;
+  }
+
+  /* Use an intermediate variable for clarity */
+  rawptr = (void *) zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  abfd->tdata =(void *)( (struct sunexdata *) rawptr);
+  exec_hdr (abfd) =
+    (struct exec *) ((char *)rawptr + sizeof (struct sunexdata));
+
+  swap_exec_header (abfd, execp);
+  memcpy (exec_hdr (abfd), execp, sizeof (struct exec));
+
+  /* Set the file flags */
+  abfd->flags = NO_FLAGS;
+  if (execp->a_drsize || execp->a_trsize)
+    abfd->flags |= HAS_RELOC;
+  if (execp->a_entry) 
+    abfd->flags |= EXEC_P;
+  if (execp->a_syms) 
+    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+
+  if (N_MAGIC (anexec) == ZMAGIC) abfd->flags |= D_PAGED;
+  if (N_MAGIC (anexec) == NMAGIC) abfd->flags |= WP_TEXT;
+
+  /* Determine the architecture and machine type of the object file.  */
+  abfd->obj_arch = bfd_arch_unknown;   /* Default values */
+  abfd->obj_machine = 0;
+  switch (N_MACHTYPE (anexec)) {
+
+  case M_UNKNOWN:
+       break;
+
+  case M_68010:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68010;
+       break;
+
+  case M_68020:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68020;
+       break;
+
+  case M_SPARC:
+       abfd->obj_arch = bfd_arch_sparc;
+       break;
+
+  case M_386:
+       abfd->obj_arch = bfd_arch_i386;
+       break;
+
+  case M_29K:
+       abfd->obj_arch = bfd_arch_a29k;
+       break;
+
+  default:
+       abfd->obj_arch = bfd_arch_obscure;
+       break;
+  }
+
+  bfd_get_start_address (abfd) = execp->a_entry;
+
+  /* Remember the positions of the string table and symbol table.  */
+  obj_str_filepos (abfd) = n_stroff (&anexec);
+  obj_sym_filepos (abfd) = n_symoff (&anexec);
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  obj_aout_symbols(abfd) = (aout_symbol_type *)NULL;
+  (void)bfd_make_section(abfd, ".text");
+  (void)bfd_make_section(abfd, ".data");
+  (void)bfd_make_section(abfd, ".bss");
+
+  obj_datasec (abfd)->size = execp->a_data;
+  obj_bsssec (abfd)->size = execp->a_bss;
+  obj_textsec (abfd)->size = execp->a_text;
+  obj_datasec (abfd)->vma = N_DATADDR(anexec);
+  obj_bsssec (abfd)->vma = N_BSSADDR(anexec);
+  obj_textsec (abfd)->vma = N_TXTADDR(anexec);
+
+  obj_textsec (abfd)->filepos = n_txtoff(&anexec);
+  obj_datasec (abfd)->filepos = n_datoff(&anexec);
+
+  obj_textsec (abfd)->rel_filepos = n_treloff(&anexec);
+  obj_datasec (abfd)->rel_filepos = n_dreloff(&anexec);
+
+  obj_textsec (abfd)->flags =
+    (execp->a_trsize != 0 ?
+                 (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
+                 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
+  obj_datasec (abfd)->flags =
+    (execp->a_drsize != 0 ?
+                               (SEC_ALLOC | SEC_LOAD | SEC_RELOC  | SEC_HAS_CONTENTS) :
+                               (SEC_ALLOC | SEC_LOAD  | SEC_HAS_CONTENTS));
+  obj_bsssec (abfd)->flags = SEC_ALLOC;
+
+  abfd->sections = obj_textsec (abfd);
+  obj_textsec (abfd)->next = obj_datasec (abfd);
+  obj_datasec (abfd)->next = obj_bsssec (abfd);
+  return abfd->xvec;
+}
+
+
+boolean
+sunos4_mkobject (abfd)
+     bfd *abfd;
+{
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  /* Use an intermediate variable for clarity */
+  rawptr =  zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  abfd->tdata = (void *)((struct sunexdata *) rawptr);
+  exec_hdr (abfd) = (struct exec *) (rawptr + sizeof (struct sunexdata));
+
+  /* For simplicity's sake we just make all the sections right here. */
+
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  bfd_make_section (abfd, ".text");
+  bfd_make_section (abfd, ".data");
+  bfd_make_section (abfd, ".bss");
+
+  return true;
+}
+
+/* Keep track of machine architecture and machine type for a.out's.
+   Return the machine_type for a particular arch&machine, or M_UNKNOWN
+   if that exact arch&machine can't be represented in a.out format.
+
+   If the architecture is understood, machine type 0 (default) should
+   always be understood.  */
+
+static enum machine_type
+aout_machine_type (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  enum machine_type arch_flags;
+
+  arch_flags = M_UNKNOWN;
+
+  switch (arch) {
+  case bfd_arch_sparc:
+       if (machine == 0)       arch_flags = M_SPARC;
+       break;
+
+  case bfd_arch_m68k:
+       switch (machine) {
+       case 0:                 arch_flags = M_UNKNOWN; break;
+       case 68000:             arch_flags = M_UNKNOWN; break;
+       case 68010:             arch_flags = M_68010; break;
+       case 68020:             arch_flags = M_68020; break;
+       default:                arch_flags = M_UNKNOWN; break;
+       }
+       break;
+
+  case bfd_arch_i386:
+       if (machine == 0)       arch_flags = M_386;
+       break;
+
+  case bfd_arch_a29k:
+       if (machine == 0)       arch_flags = M_29K;
+       break;
+
+  default:
+       arch_flags = M_UNKNOWN;
+       break;
+  }
+  return arch_flags;
+}
+
+boolean
+sunos4_set_arch_mach (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  if (arch != bfd_arch_unknown &&
+      aout_machine_type (arch, machine) == M_UNKNOWN)
+    return false;              /* We can't represent this type */
+  return true;                 /* We're easy ... */
+}
+
+boolean
+sunos4_write_object_contents (abfd)
+     bfd *abfd;
+{
+  int data_pad = 0;
+  struct exec *execp = exec_hdr (abfd);
+
+
+
+  /* Magic number, maestro, please!  */
+  switch (bfd_get_architecture(abfd)) {
+  case bfd_arch_m68k:
+    switch (bfd_get_machine(abfd)) {
+    case 68010:
+      N_SET_MACHTYPE(*execp, M_68010);
+      break;
+    default:
+    case 68020:
+      N_SET_MACHTYPE(*execp, M_68020);
+      break;
+    }
+    break;
+  case bfd_arch_sparc:
+    N_SET_MACHTYPE(*execp, M_SPARC);
+    break;
+  case bfd_arch_i386:
+    N_SET_MACHTYPE(*execp, M_386);
+    break;
+  case bfd_arch_a29k:
+    N_SET_MACHTYPE(*execp, M_29K);
+    break;
+  default:
+    N_SET_MACHTYPE(*execp, M_UNKNOWN);
+  }
+  execp->a_text = obj_textsec (abfd)->size;
+  N_SET_MAGIC (*execp, OMAGIC);
+  if (abfd->flags & D_PAGED) {
+    execp->a_text = obj_textsec (abfd)->size + sizeof(struct exec);
+    N_SET_MAGIC (*execp, ZMAGIC);
+  } else if (abfd->flags & WP_TEXT) {
+    N_SET_MAGIC (*execp, NMAGIC);
+  }
+  N_SET_FLAGS (*execp, 0x1);   /* copied from ld.c; who the hell knows? */
+
+  if (abfd->flags & D_PAGED) 
+    {
+      data_pad = ((obj_datasec(abfd)->size + PAGE_SIZE -1)
+                 & (- PAGE_SIZE)) - obj_datasec(abfd)->size;
+
+      if (data_pad > obj_bsssec(abfd)->size)
+       execp->a_bss = 0;
+      else 
+       execp->a_bss = obj_bsssec(abfd)->size - data_pad;
+      execp->a_data = obj_datasec(abfd)->size + data_pad;
+
+    }
+  else {
+    execp->a_data = obj_datasec (abfd)->size;
+    execp->a_bss = obj_bsssec (abfd)->size;
+  }
+
+  execp->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
+  execp->a_entry = bfd_get_start_address (abfd);
+  execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+                    sizeof (struct reloc_info_extended));
+  execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+                    sizeof (struct reloc_info_extended));;
+
+  swap_exec_header (abfd, execp);
+
+  bfd_seek (abfd, 0L, SEEK_SET);
+  bfd_write ((void *) execp, 1, sizeof (struct exec), abfd);
+
+  /* Now write out reloc info, followed by syms and strings */
+
+  if (bfd_get_symcount (abfd) != 0) 
+    {
+      bfd_seek (abfd,
+               (long)(N_SYMOFF(*execp)), SEEK_SET);
+
+      sunos4_write_syms (abfd);
+
+      bfd_seek (abfd,  (long)(N_TROFF(*execp)), SEEK_SET);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
+      bfd_seek (abfd, (long)(N_DROFF(*execp)), SEEK_SET);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
+    }
+  return true;
+}
+
+static void
+swap_exec_header (abfd, execp)
+bfd *abfd;
+     struct exec *execp;
+{
+  if (bfd_header_twiddle_required(abfd)) {
+    /* execp->a_info = bfd_h_getlong (abfd, &execp->a_info); */
+    *(unsigned long *) execp =
+                     bfd_h_getlong (abfd, (unsigned long *) execp);
+    execp->a_text   = bfd_h_getlong (abfd, &execp->a_text);
+    execp->a_data   = bfd_h_getlong (abfd, &execp->a_data);
+    execp->a_bss    = bfd_h_getlong (abfd, &execp->a_bss);
+    execp->a_syms   = bfd_h_getlong (abfd, &execp->a_syms);
+    execp->a_entry  = bfd_h_getlong (abfd, &execp->a_entry);
+    execp->a_trsize = bfd_h_getlong (abfd, &execp->a_trsize);
+    execp->a_drsize = bfd_h_getlong (abfd, &execp->a_drsize);
+  }
+} /* swap_exec_header() */
+\f
+/** core files */
+
+#define CORE_MAGIC 0x080456
+#define CORE_NAMELEN 16
+
+/* The core structure is taken from the Sun documentation.
+   Unfortunately, they don't document the FPA structure, or at least I
+   can't find it easily.  Fortunately the core header contains its own
+   length.  So this shouldn't cause problems, except for c_ucode, which
+   so far we don't use but is easy to find with a little arithmetic. */
+
+/* But the reg structure can be gotten from the SPARC processor handbook.
+   This really should be in a GNU include file though so that gdb can use
+   the same info. */
+struct regs {
+  int r_psr;
+  int r_pc;
+  int r_npc;
+  int r_y;
+  int r_g1;
+  int r_g2;
+  int r_g3;
+  int r_g4;
+  int r_g5;
+  int r_g6;
+  int r_g7;
+  int r_o0;
+  int r_o1;
+  int r_o2;
+  int r_o3;
+  int r_o4;
+  int r_o5;
+  int r_o6;
+  int r_o7;
+};
+
+/* Taken from Sun documentation: */
+
+struct core {
+  int c_magic;                 /* Corefile magic number */
+  int c_len;                   /* Sizeof (struct core) */
+  struct regs c_regs;          /* General purpose registers */
+  struct exec c_aouthdr;       /* A.out header */
+  int c_signo;                 /* Killing signal, if any */
+  int c_tsize;                 /* Text size (bytes) */
+  int c_dsize;                 /* Data size (bytes) */
+  int c_ssize;                 /* Stack size (bytes) */
+  char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+  double fp_stuff[1];          /* external FPU state (size unknown by us) */
+                       /* The type "double" is critical here, for alignment.
+                          SunOS declares a struct here, but the struct's
+                          alignment is double since it contains doubles. */
+  int c_ucode;                 /* Exception no. from u_code */
+                       /* (this member not accessible by name since we don't
+                          portably know the size of fp_stuff.) */
+};
+
+/* Supposedly the user stack grows downward from the bottom of kernel memory.
+   Presuming that this remains true, this definition will work. */
+#define USRSTACK (-(128*1024*1024))
+
+PROTO (static void, swapcore, (bfd *abfd, struct core *core));
+
+/* need this cast b/c ptr is really void * */
+#define core_hdr(bfd) (((struct suncordata *) (bfd->tdata))->hdr)
+#define core_datasec(bfd) (((struct suncordata *) ((bfd)->tdata))->data_section)
+#define core_stacksec(bfd) (((struct suncordata*)((bfd)->tdata))->stack_section)
+#define core_regsec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg_section)
+#define core_regsec2(bfd) (((struct suncordata *) ((bfd)->tdata))->reg2_section)
+
+/* These are stored in the bfd's tdata */
+struct suncordata {
+  struct core *hdr;             /* core file header */
+  asection *data_section;
+  asection *stack_section;
+  asection *reg_section;
+  asection *reg2_section;
+};
+
+bfd_target *
+sunos4_core_file_p (abfd)
+     bfd *abfd;
+{
+  /* includes redundent variables for code clarity */
+  int core_size;
+  int core_mag;
+  struct core *core;
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)&core_mag, 1, sizeof (int), abfd) != sizeof (int))
+    return 0;
+  core_mag = bfd_h_getlong(abfd, &core_mag);
+
+  if (core_mag != CORE_MAGIC) return 0;
+
+  /* SunOS core headers can vary in length; second word is size; */
+  if (bfd_read ((void *)&core_size, 1, sizeof (int), abfd) != sizeof (int))
+    return 0;
+  core_size = bfd_h_getlong(abfd, &core_size);
+
+  if (bfd_seek (abfd, 0L, SEEK_SET) < 0) return 0;
+
+  rawptr = zalloc (core_size + sizeof (struct suncordata));
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  core = (struct core *) (rawptr + sizeof (struct suncordata));
+
+  if ((bfd_read ((void *) core, 1, core_size, abfd)) != core_size) {
+    bfd_error = system_call_error;
+    free ((void *)rawptr);
+    return 0;
+  }
+
+  swapcore (abfd, core);
+  abfd->tdata = (void *)((struct suncordata *) rawptr);
+  core_hdr (abfd) = core;
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  core_stacksec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_stacksec (abfd) == NULL) {
+  loser:
+    bfd_error = no_memory;
+    free ((void *)rawptr);
+    return 0;
+  }
+  core_datasec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_datasec (abfd) == NULL) {
+  loser1:
+    free ((void *)core_stacksec (abfd));
+    goto loser;
+  }
+  core_regsec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_regsec (abfd) == NULL) {
+  loser2:
+    free ((void *)core_datasec (abfd));
+    goto loser1;
+  }
+  core_regsec2 (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_regsec2 (abfd) == NULL) {
+    free ((void *)core_regsec (abfd));
+    goto loser2;
+  }
+
+  core_stacksec (abfd)->name = ".stack";
+  core_datasec (abfd)->name = ".data";
+  core_regsec (abfd)->name = ".reg";
+  core_regsec2 (abfd)->name = ".reg2";
+
+  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_regsec (abfd)->flags = SEC_ALLOC;
+  core_regsec2 (abfd)->flags = SEC_ALLOC;
+
+  core_stacksec (abfd)->size = core->c_ssize;
+  core_datasec (abfd)->size = core->c_dsize;
+  core_regsec (abfd)->size = (sizeof core->c_regs);
+  /* Float regs take up end of struct, except c_ucode. */
+  core_regsec2 (abfd)->size = core_size - (sizeof core->c_ucode) - 
+                               (file_ptr)(((struct core *)0)->fp_stuff);
+
+  core_stacksec (abfd)->vma = (USRSTACK - core->c_ssize);
+  core_datasec (abfd)->vma = N_DATADDR(core->c_aouthdr);
+  core_regsec (abfd)->vma = -1;
+  core_regsec2 (abfd)->vma = -1;
+
+  core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
+  core_datasec (abfd)->filepos = core->c_len;
+                        /* In file header: */
+  core_regsec (abfd)->filepos = (file_ptr)(&((struct core *)0)->c_regs);
+  core_regsec2 (abfd)->filepos = (file_ptr)(((struct core *)0)->fp_stuff);
+
+  /* Align to word at least */
+  core_stacksec (abfd)->alignment_power = 2;
+  core_datasec (abfd)->alignment_power = 2;
+  core_regsec (abfd)->alignment_power = 2;
+  core_regsec2 (abfd)->alignment_power = 2;
+
+  abfd->sections = core_stacksec (abfd);
+  core_stacksec (abfd)->next = core_datasec (abfd);
+  core_datasec (abfd)->next = core_regsec (abfd);
+  core_regsec (abfd)->next = core_regsec2 (abfd);
+
+  abfd->section_count = 4;
+
+  return abfd->xvec;
+}
+
+char *
+sunos4_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_cmdname;
+}
+
+int
+sunos4_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_signo;
+}
+
+boolean
+sunos4_core_file_matches_executable_p  (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if (core_bfd->xvec != exec_bfd->xvec) {
+    bfd_error = system_call_error;
+    return false;
+  }
+
+  return (bcmp (&core_hdr (core_bfd), &exec_hdr (exec_bfd),
+                sizeof (struct exec)) == 0) ? true : false;
+}
+
+/* byte-swap core structure */
+static void
+swapcore (abfd, core)
+bfd *abfd;
+     struct core *core;
+{
+  if (bfd_header_twiddle_required(abfd)) {
+    core->c_magic = bfd_h_getlong (abfd, &core->c_magic);
+    core->c_len   = bfd_h_getlong (abfd, &core->c_len);
+    /* regs */
+    swap_exec_header (abfd, &(core->c_aouthdr));
+    core->c_signo = bfd_h_getlong (abfd, &core->c_signo);
+    core->c_tsize = bfd_h_getlong (abfd, &core->c_tsize);
+    core->c_dsize = bfd_h_getlong (abfd, &core->c_dsize);
+    core->c_ssize = bfd_h_getlong (abfd, &core->c_ssize);
+    core->c_ucode = bfd_h_getlong (abfd, &core->c_ucode);
+    /* I don't understand how to swap an FP register */
+  }
+}
+\f
+/** exec and core file sections */
+
+boolean
+sunos4_new_section_hook (abfd, newsect)
+     bfd *abfd;
+     asection *newsect;
+{
+  /* align to double at least */
+  newsect->alignment_power = 3;
+
+  if (bfd_get_format (abfd) == bfd_object) {
+    if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
+      obj_textsec(abfd)= newsect;
+      return true;
+    }
+
+    if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
+      obj_datasec(abfd) = newsect;
+      return true;
+    }
+
+    if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
+      obj_bsssec(abfd) = newsect;
+      return true;
+    }
+  }
+
+#if 0                          /* FIXME -- this is temporary for steve */
+  bfd_error = invalid_operation;
+
+  return false;
+#endif
+
+  /* We allow more than three sections internally */
+  return true;
+}
+
+boolean
+sunos4_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     unsigned char *location;
+     file_ptr offset;
+      int count;
+{
+  if (abfd->output_has_begun == false)
+    {                          /* set by bfd.c handler */
+      if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)
+         
+         /*||
+           (obj_textsec (abfd)->size == 0) || (obj_datasec (abfd)->size=
+           0)*/
+         ) 
+       {
+         bfd_error = invalid_operation;
+         return false;
+       }
+
+
+#if 0
+      if (abfd->flags & D_PAGED)
+       {
+         obj_textsec (abfd)->filepos = sizeof(struct exec);
+         obj_datasec(abfd)->filepos =  obj_textsec (abfd)->size;
+       }
+      else 
+#endif
+{
+       obj_textsec (abfd)->filepos = sizeof(struct exec);
+       obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos  + obj_textsec (abfd)->size;
+
+      }
+    }
+  /* regardless, once we know what we're doing, we might as well get going */
+
+  bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+  if (count) {
+    return (bfd_write ((void *)location, 1, count, abfd) == count) ? true : false;
+  }
+  return false;
+}
+boolean
+sunos4_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     void  *location;
+     file_ptr offset;
+     int count;
+{
+  if (count) {
+    if (offset >= section->size) return false;
+
+    bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+    return (bfd_read (location, 1, count, abfd) == count) ? true:false;
+  }
+  else return true;
+}
+
+\f
+/* Classify stabs symbols */
+
+
+#define sym_in_text_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
+
+#define sym_in_data_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
+
+#define sym_in_bss_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
+
+/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
+   zero in the "value" field.  Nonzeroes there are fortrancommon
+   symbols.  */
+#define sym_is_undefined(sym) \
+        ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
+
+/* Symbol is a global definition if N_EXT is on and if it has
+   a nonzero type field.  */
+#define sym_is_global_defn(sym) \
+        (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
+
+/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
+   are on.  */
+#define sym_is_debugger_info(sym) \
+        ((sym)->n_type & ~(N_EXT | N_TYPE))
+
+#define sym_is_fortrancommon(sym)       \
+        (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
+
+/* Symbol is absolute if it has N_ABS set */
+#define sym_is_absolute(sym) \
+              (((sym)->n_type  & N_TYPE)== N_ABS)
+
+
+#define sym_is_indirect(sym) \
+              (((sym)->n_type  & N_ABS)== N_ABS)
+
+/* Only in their own functions for ease of debugging; when sym flags have
+   stabilised these should be inlined into their (single) caller */
+
+static void
+translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
+     struct nlist *sym_pointer;
+     aout_symbol_type *cache_ptr;
+     bfd *abfd;
+{
+  switch (cache_ptr->type & N_TYPE) {
+  case N_SETA:
+  case N_SETT:
+  case N_SETD:
+  case N_SETB:
+    {
+      asection *section = bfd_make_section(abfd,
+                                          cache_ptr->symbol.name);
+      arelent_chain *reloc = (arelent_chain *)malloc(sizeof(arelent_chain));
+
+      switch ( (cache_ptr->type  & N_TYPE) ) {
+      case N_SETA:
+       reloc->relent.section =  (asection *)NULL;
+       cache_ptr->symbol.section = (asection *)NULL;
+       break;
+      case N_SETT:
+       reloc->relent.section = (asection *)obj_textsec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETD:
+       reloc->relent.section = (asection *)obj_datasec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETB:
+       reloc->relent.section = (asection *)obj_bsssec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      }
+      cache_ptr->symbol.section = reloc->relent.section;
+      reloc->relent.addend = cache_ptr->symbol.value ;
+      /* 
+        We modify the symbol to belong to a section depending upon the
+        name of the symbol - probably __CTOR__ or __DTOR__ but we don't
+        really care, and add to the size of the section to contain a
+        pointer to the symbol. Build a reloc entry to relocate to this
+        symbol attached to this section.
+        */
+
+
+      section->flags = SEC_CONSTRUCTOR;
+      section->reloc_count++;
+      section->alignment_power = 2;
+      reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
+      reloc->next = section->constructor_chain;
+      section->constructor_chain = reloc;
+      reloc->relent.address = section->size;
+      section->size += sizeof(int *);
+
+      reloc->relent.howto = howto_table +CTOR_TABLE_RELOC_IDX;
+      cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
+      }
+    break;
+  default:
+
+    if (sym_is_debugger_info (sym_pointer)) {
+      cache_ptr->symbol.flags = BSF_DEBUGGING ;
+      /* Work out the section correct for this symbol */
+      switch (sym_pointer->n_type & N_TYPE) 
+       {
+       case N_TEXT:
+       case N_FN:
+         cache_ptr->symbol.section = obj_textsec (abfd);
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         break;
+       case N_DATA:
+         cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+         break;
+       case N_BSS :
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+         break;
+       case N_ABS:
+       default:
+         cache_ptr->symbol.section = 0;
+         break;
+       }
+    }
+    else {
+      if (sym_is_fortrancommon (sym_pointer))
+       {
+         cache_ptr->symbol.flags = BSF_FORT_COMM;
+         cache_ptr->symbol.section = (asection *)NULL;
+       }
+      else {
+       if (sym_is_undefined (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_UNDEFINED;
+       }
+       else if (sym_is_global_defn (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+       }
+
+       else if (sym_is_absolute (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_ABSOLUTE;
+       }
+       else {
+         cache_ptr->symbol.flags = BSF_LOCAL;
+       }
+
+       /* In a.out, the value of a symbol is always relative to the 
+        * start of the file, if this is a data symbol we'll subtract
+        * the size of the text section to get the section relative
+        * value. If this is a bss symbol (which would be strange)
+        * we'll subtract the size of the previous two sections
+        * to find the section relative address.
+        */
+
+       if (sym_in_text_section (sym_pointer))   {
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         cache_ptr->symbol.section = obj_textsec (abfd);
+       }
+       else if (sym_in_data_section (sym_pointer)){
+         cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+       }
+       else if (sym_in_bss_section(sym_pointer)) {
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+       }
+       else {
+         cache_ptr->symbol.section = (asection *)NULL;
+         cache_ptr->symbol.flags |= BSF_ABSOLUTE;
+       }
+      }
+    }
+  }
+}
+void
+translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
+     struct nlist *sym_pointer;
+     generic_symbol_type *cache_ptr_g;
+     bfd *abfd;
+{
+  asymbol *cache_ptr = (asymbol *)cache_ptr_g;
+
+  /* FIXME check for wrigin bss */
+  if (bfd_get_section(cache_ptr)) {
+    if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+      sym_pointer->n_type |= N_BSS;
+    }
+    else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+      sym_pointer->n_type |= N_DATA;
+    }
+    else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+      sym_pointer->n_type |= N_TEXT;
+    }
+    else {
+      BFD_ASSERT(0);
+    }
+    /* Turn the symbol from section relative to absolute again */
+    sym_pointer->n_value +=
+      cache_ptr->section->output_section->vma 
+       + cache_ptr->section->output_offset ;
+  }
+  else {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
+    sym_pointer->n_type = (N_UNDF | N_EXT);
+    return;
+  }
+
+  if (cache_ptr->flags & BSF_ABSOLUTE) {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+    sym_pointer->n_type |= N_EXT;
+  }
+  if (cache_ptr->flags & BSF_DEBUGGING) {
+    sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
+  }
+  
+}
+\f
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+   function exits.  We read the strings into a buffer large enough to
+   hold them all plus all the cached symbol entries. */
+
+asymbol *
+sunos4_make_empty_symbol (abfd)
+bfd *abfd;
+{
+  aout_symbol_type  *new =
+    (aout_symbol_type *)zalloc (sizeof (aout_symbol_type));
+  new->symbol.the_bfd = abfd;
+
+  return &new->symbol;
+}
+
+boolean
+sunos4_slurp_symbol_table (abfd)
+     bfd *abfd;
+{
+  unsigned int symbol_count;
+  size_t symbol_size;
+  size_t string_size;
+  struct nlist *syms;
+  char *strings;
+  aout_symbol_type *cached;
+
+  /* If there's no work to be done, don't do any */
+  if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
+  symbol_size = exec_hdr(abfd)->a_syms;
+  if (symbol_size == 0) {
+    bfd_error = no_symbols;
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)&string_size, 4, 1, abfd) != 4)
+    return false;
+  string_size = bfd_h_getlong (abfd, (unsigned char *)&string_size);
+
+  symbol_count = symbol_size / sizeof (struct nlist);
+
+  /* Malloc (should alloca) space for native symbols, and
+     malloc space for string table and symbol cache. */
+
+  syms = (struct nlist *) zalloc (symbol_size);
+  if (syms == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  cached = (aout_symbol_type *) zalloc ((size_t)(string_size + 1 +
+                               (symbol_count * sizeof (aout_symbol_type))));
+  if (cached == NULL) {
+    bfd_error = no_memory;
+    free ((void *)syms);
+    return false;
+  }
+
+  strings = ((char *) cached) + (symbol_count * sizeof (aout_symbol_type));
+
+  bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)syms, 1, symbol_size, abfd) != symbol_size) {
+  bailout:
+    free ((void *)cached);
+    free ((void*)syms);
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)strings, 1, string_size, abfd) != string_size) {
+    goto bailout;
+  }
+
+  /* OK, now walk the new symtable, cacheing symbol properties */
+  {
+    register struct nlist *sym_pointer;
+    register struct nlist *sym_end = syms + symbol_count;
+    register aout_symbol_type *cache_ptr = cached;
+
+    if (bfd_header_twiddle_required (abfd) == true) {
+      /* run through the table and byte swap if needed */
+      for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
+        sym_pointer->n_un.n_strx =
+         bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
+        sym_pointer->n_desc =
+         bfd_h_get_x (abfd, &sym_pointer->n_desc);
+        sym_pointer->n_value =
+         bfd_h_get_x (abfd, &sym_pointer->n_value);
+       sym_pointer->n_other = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_other);
+       sym_pointer->n_type = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_type);
+
+      }
+    }
+    /* Run through table and copy values */
+    for (sym_pointer = syms, cache_ptr = cached;
+        sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
+      {
+       cache_ptr->symbol.the_bfd = abfd;
+       if (sym_pointer->n_un.n_strx)
+         cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
+       else
+         cache_ptr->symbol.name = (char *)NULL;
+       cache_ptr->symbol.value = sym_pointer->n_value;
+       cache_ptr->desc = sym_pointer->n_desc;
+       cache_ptr->other = sym_pointer->n_other;
+       cache_ptr->type = sym_pointer->n_type;
+       cache_ptr->symbol.udata = 0;
+       translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
+
+      }
+  }
+
+  obj_aout_symbols (abfd) =  cached;
+  bfd_get_symcount (abfd) = symbol_count;
+  free ((void *)syms);
+
+  return true;
+}
+
+\f
+void
+sunos4_write_syms (abfd)
+     bfd *abfd;
+{
+  unsigned int count ;
+  asymbol **generic = bfd_get_outsymbols (abfd);
+
+  unsigned int stindex = sizeof(stindex); /* initial string length */
+
+  for (count = 0; count < bfd_get_symcount (abfd); count++) {
+    asymbol *g = generic[count];
+    struct nlist nsp;
+
+    if (g->name) {
+      unsigned int length = strlen(g->name) +1;
+      bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
+      stindex += length;
+    }
+    else {
+      bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
+    }
+
+    if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
+      {
+       nsp.n_desc = aout_symbol( g)->desc;
+       nsp.n_other = aout_symbol(g)->other;
+       nsp.n_type = aout_symbol(g)->type;
+      }
+    else
+      {
+       nsp.n_desc = 0;
+       nsp.n_other = 0;
+       nsp.n_type = 0;
+      }
+
+
+    nsp.n_value = g->value;
+    translate_to_native_sym_flags (&nsp, (generic_symbol_type *)g, abfd);
+
+
+    bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
+    bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
+    bfd_write((void *)&nsp,1, sizeof(nsp), abfd);
+  }
+
+
+  /* Now output the strings.  Be sure to put string length into correct
+   * byte ordering before writing it.
+   */
+  bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
+
+  bfd_write((void *)&stindex, 1, sizeof(stindex), abfd);
+  
+  generic = bfd_get_outsymbols(abfd);
+  for (count = 0; count < bfd_get_symcount(abfd); count++) 
+    {
+      asymbol *g = *(generic++);
+
+      if (g->name != (char *)NULL) 
+       {
+         size_t length = strlen(g->name)+1;
+         bfd_write((void *)g->name, 1, length, abfd);
+       }
+      if ((g->flags & BSF_FAKE)==0) {
+       g->name = itos(count);  /* smash the generic symbol */
+      }
+    }
+}
+
+\f
+void
+sunos4_reclaim_symbol_table (abfd)
+     bfd *abfd;
+{
+  asection *section;
+
+  if (!bfd_get_symcount (abfd)) return;
+
+  for (section = abfd->sections;
+       section != (asection *) NULL;
+       section = section->next)
+    if (section->relocation) {
+      free ((void *)section->relocation);
+      section->relocation = NULL;
+      section->reloc_count = 0;
+    }
+
+  bfd_get_symcount (abfd) = 0;
+  free ((void *)obj_aout_symbols (abfd));
+  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+}
+\f
+unsigned int
+sunos4_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
+}
+
+unsigned int
+sunos4_get_symtab (abfd, location)
+     bfd *abfd;
+     asymbol **location;
+{
+  unsigned int counter = 0;
+  aout_symbol_type *symbase;
+
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
+    *(location++) = (asymbol *)( symbase++);
+  *location++ =0;
+  return bfd_get_symcount(abfd);
+}
+
+\f
+/* Obsolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+   BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+sunos4_get_symcount_upper_bound (abfd)
+     bfd *abfd;
+{
+  /* In case we're doing an output file or something...?  */
+  if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+  return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+}
+
+symindex
+sunos4_get_first_symbol (ignore_abfd)
+     bfd * ignore_abfd;
+{
+  return 0;
+}
+
+symindex
+sunos4_get_next_symbol (abfd, oidx)
+     bfd *abfd;
+     symindex oidx;
+{
+  if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+  return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
+}
+
+char *
+sunos4_symbol_name (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.name;
+}
+
+long
+sunos4_symbol_value (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.value;
+}
+
+symclass
+sunos4_classify_symbol (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+  if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
+  if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
+  if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
+  if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+
+  return bfd_symclass_unknown;
+}
+
+boolean
+sunos4_symbol_hasclass (abfd, idx, class)
+     bfd *abfd;
+     symindex idx;
+     symclass class;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+  switch (class) {
+  case bfd_symclass_fcommon:
+    return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+  case bfd_symclass_global:
+    return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+  case bfd_symclass_debugger:
+    return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+  case bfd_symclass_undefined:
+    return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+  default: return false;
+  }
+}
+\f
+/** Some reloc hackery */
+
+
+boolean
+sunos4_slurp_reloc_table (abfd, asect, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     asymbol **symbols;
+{
+  unsigned int count;
+  size_t reloc_size;
+  struct reloc_info_extended *relocs;
+  arelent *reloc_cache;
+
+  if (asect->relocation) return true;
+
+  if (asect->flags & SEC_CONSTRUCTOR) return true;
+
+  if (asect == obj_datasec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_drsize;
+    goto doit;
+  }
+
+  if (asect == obj_textsec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_trsize;
+    goto doit;
+  }
+
+  bfd_error = invalid_operation;
+  return false;
+
+ doit:
+  bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
+  count = reloc_size / sizeof (struct reloc_info_extended);
+
+  relocs = (struct reloc_info_extended *) malloc (reloc_size);
+  if (!relocs) {
+    bfd_error = no_memory;
+    return false;
+  }
+  reloc_cache = (arelent *) zalloc ((size_t)(count * sizeof (arelent)));
+  if (reloc_cache == (arelent *)NULL) {
+    free ((void *)relocs);
+    bfd_error = no_memory;
+    return false;
+  }
+
+  if (bfd_read ((void*) relocs, 1, reloc_size, abfd) != reloc_size) {
+    bfd_error = system_call_error;
+    free (reloc_cache);
+    free (relocs);
+    return false;
+  }
+
+  {
+    register struct reloc_info_extended *rptr = relocs;
+    unsigned int counter = 0;
+    arelent *cache_ptr = reloc_cache;
+
+    for (; counter < count; counter++, rptr++, cache_ptr++) {
+      /* john's old swap_reloc was a hell of a lot hairier... */
+      /* FIXME, it needs to be!!! */
+      rptr->r_address = bfd_h_getlong (abfd, &rptr->r_address);
+      /* FIXME NOW!
+       *  The following can't be done because r_index is a bit field:
+       *
+       * rptr->r_index   = bfd_h_getlong (abfd, &rptr->r_index);
+       */
+      rptr->r_addend  = bfd_h_getlong (abfd, &rptr->r_addend);
+      if (rptr->r_extern) {
+       /* If this bit is set then the r_index is a index into the symbol table
+        * if the bit is not set then r_index contains a section map.
+        * We either fill in the sym entry with a pointer to the symbol,
+        * or point to the correct section
+        */
+       
+       cache_ptr->sym_ptr_ptr = symbols + rptr->r_index;
+       cache_ptr->addend =  rptr->r_addend;
+       cache_ptr->section = (asection *)NULL;
+      }
+      else 
+       {
+         /* Remember that in a.out symbols are relative to the
+        beginning of the file rather than sections ? (look in
+        translate_from_native_sym_flags) The reloc entry addend
+        has added to it the offset into the  file of the data, so
+        subtract the base to make the reloc section relative */
+
+         cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
+         switch (rptr->r_index) {
+         case N_TEXT:
+         case N_TEXT | N_EXT:
+           cache_ptr->section = obj_textsec(abfd);
+           cache_ptr->addend = rptr->r_addend -  obj_textsec(abfd)->vma  ;
+           break;
+         case N_DATA:
+         case N_DATA | N_EXT:
+           cache_ptr->section = obj_datasec(abfd);
+           cache_ptr->addend = rptr->r_addend -  obj_datasec(abfd)->vma  ;
+           break;
+         case N_BSS:
+         case N_BSS | N_EXT:
+           cache_ptr->section = obj_bsssec(abfd);
+           cache_ptr->addend = rptr->r_addend - obj_bsssec(abfd)->vma;
+           break;
+         case N_ABS:
+         case N_ABS | N_EXT:
+           BFD_ASSERT(1);
+           break;
+         default:
+           BFD_ASSERT(1);
+           break;
+         }
+       
+       }
+
+      cache_ptr->address = rptr->r_address;
+      cache_ptr->howto =  howto_table + (unsigned int)( rptr->r_type);
+    }
+  }
+
+  free (relocs);
+  asect->relocation = reloc_cache;
+  asect->reloc_count = count;
+  return true;
+}
+
+static boolean
+sunos4_squirt_out_relocs (abfd, section)
+     bfd *abfd;
+     asection *section;
+{
+  arelent **generic;
+
+  unsigned int count = section->reloc_count;
+  struct reloc_info_extended *native, *natptr;
+  size_t natsize = count * sizeof (struct reloc_info_extended);
+
+  if (count == 0) return true;
+  generic   = section->orelocation;
+  native = ((struct reloc_info_extended *) zalloc (natsize));
+  if (!native) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  for (natptr = native; count != 0; --count, ++natptr, ++generic) 
+    {
+      arelent *g = *generic;
+
+      natptr->r_address = g->address;
+      /* Find a type in the output format which matches the input howto - 
+       * at the moment we assume input format == output format FIXME!!
+       */
+      natptr->r_type = (enum reloc_type) g->howto->type;
+      /* name clobbered by sunos4_write_syms to be symbol index*/
+
+      if (g->sym_ptr_ptr != (asymbol **)NULL) 
+       {
+         if ((*(g->sym_ptr_ptr))->section) {
+           /* replace the section offset into the addent */
+           g->addend += (*(g->sym_ptr_ptr))->section->vma;
+         }
+
+         natptr->r_index = stoi((*(g->sym_ptr_ptr))->name);
+       BFD_ASSERT(natptr->r_index < 0xfff);
+         natptr->r_extern = 1;
+         natptr->r_addend = g->addend;
+       }
+      else {
+       natptr->r_extern = 0;
+       if (g->section == (asection *)NULL) {
+         BFD_ASSERT(0);
+         natptr->r_index = N_ABS | N_EXT;
+         natptr->r_addend = g->addend;
+       }
+       else  if(g->section->output_section == obj_textsec(abfd)) {
+         natptr->r_index = N_TEXT | N_EXT;
+         natptr->r_addend = g->addend + obj_textsec(abfd)->vma;
+       }
+       else if (g->section->output_section == obj_datasec(abfd)) {
+         natptr->r_index = N_DATA | N_EXT;
+         natptr->r_addend = g->addend + obj_datasec(abfd)->vma;
+       }
+       else if (g->section->output_section == obj_bsssec(abfd)) {
+         natptr->r_index = N_BSS | N_EXT ;
+         natptr->r_addend = g->addend + obj_bsssec(abfd)->vma;
+
+       }
+       else {
+         BFD_ASSERT(0);
+       }
+      }
+  
+      if ( bfd_header_twiddle_required(abfd) ){
+        bfd_h_putlong ( abfd, natptr->r_address, &natptr->r_address );
+
+        /* FIXME -- NOW!
+        *
+         * I came through here as part of my campaign to make compile-time
+         * definition of host and target byte orders unnecessary. The new
+        * code won't even compile because but r_index is a bit field.
+        * But the simple-minded byte swap that was here before wasn't going
+        * to work on a bit field anyway.
+        *
+         * The old code used to be #ifdef'd on 
+         *             TARGET_BYTE_ORDER_BIG_P != HOST_BYTE_ORDER_BIG_P
+         * Apparently, it was never tested in such a condition: the
+         * macro invocations here (of swapoutlong) had the wrong number
+         * of arguments and would never have compiled.
+         *                     Chris
+        bfd_h_putlong ( abfd, natptr->r_index, &natptr->r_index );
+         */
+
+        bfd_h_putlong ( abfd, natptr->r_addend, &natptr->r_addend );
+      }
+
+    }
+
+  if ( bfd_write ((void *) native, 1, natsize, abfd) != natsize) {
+    free(native);
+    return false;
+  }
+  free (native);
+
+  return true;
+}
+
+/* This is stupid.  This function should be a boolean predicate */
+unsigned int
+sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  arelent *tblptr = section->relocation;
+  unsigned int count;
+
+  if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
+    return 0;
+
+  if (section->flags & SEC_CONSTRUCTOR) {
+    arelent_chain *chain = section->constructor_chain;
+    for (count = 0; count < section->reloc_count; count ++) {
+      *relptr ++ = &chain->relent;
+      chain = chain->next;
+    }
+  }
+  else {
+    tblptr = section->relocation;
+    if (!tblptr) return 0;
+
+    for (count = 0; count++ < section->reloc_count;) 
+      {
+       *relptr++ = tblptr++;
+      }
+  }
+  *relptr = 0;
+
+  return section->reloc_count;
+}
+
+unsigned int
+sunos4_get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  if (bfd_get_format (abfd) != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+  if (asect->flags & SEC_CONSTRUCTOR) {
+    return (sizeof (arelent *) * (asect->reloc_count+1));
+  }
+
+  if (asect == obj_datasec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_drsize / sizeof (struct reloc_info_extended))
+             +1));
+
+  if (asect == obj_textsec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_trsize / sizeof (struct reloc_info_extended))
+             +1));
+
+  bfd_error = invalid_operation;
+  return 0;
+}
+
+void
+sunos4_reclaim_reloc (ignore_abfd, section)
+     bfd *ignore_abfd;
+     sec_ptr section;
+{
+  if (section->relocation) {
+    free (section->relocation);
+    section->relocation = NULL;
+    section->reloc_count = 0;
+    }
+}
+\f
+
+alent *
+sunos4_get_lineno(ignore_abfd, ignore_symbol)
+bfd *ignore_abfd;
+generic_symbol_type *ignore_symbol;
+{
+return (alent *)NULL;
+}
+
+void 
+sunos4_print_symbol(ignore_abfd, file,  symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+  switch (how) {
+  case bfd_print_symbol_name_enum:
+    fprintf(file,"%s", symbol->name);
+    break;
+  case bfd_print_symbol_type_enum:
+    fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
+           (unsigned)(   aout_symbol(symbol)->other  & 0xff),
+           (unsigned)(aout_symbol(symbol)->type));
+    break;
+  case bfd_print_symbol_all_enum:
+    {
+      char *section_name = symbol->section == (asection *)NULL ?
+       "*abs" : symbol->section->name;
+
+      bfd_print_symbol_vandf((void *)file,symbol);
+
+      fprintf(file," %-5s %04x %02x %02x %s",
+             section_name,
+             (unsigned)(aout_symbol(symbol)->desc & 0xffff),
+             (unsigned)(aout_symbol(symbol)->other  & 0xff),
+             (unsigned)(aout_symbol(symbol)->type  & 0xff),
+             symbol->name);
+    }
+    break;
+  }
+}
+/* Once we know all the stuff that could be consed, we know how to clean
+   it up.  So why don't we? */
+
+boolean
+sunos4_close_and_cleanup (abfd)
+     bfd *abfd;
+{
+  if (!bfd_read_p (abfd))
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) return false; break;
+    case bfd_object:
+      if (!sunos4_write_object_contents (abfd))  return false; break;
+    default: bfd_error = invalid_operation; return false;
+    }
+
+#define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
+  cleaner (tdata);
+
+  if (abfd->my_archive)
+    cleaner (filename);
+
+#undef cleaner
+  return true;
+}
+
+/* 
+ provided a bfd, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location.
+*/
+boolean
+sunos4_find_nearest_line(abfd,
+                        section,
+                        symbols,
+                        offset,
+                        filename_ptr,
+                        functionname_ptr,
+                        line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+  /* Run down the file looking for the filename, function and linenumber */
+  asymbol **p;
+  static  char buffer[100];
+  bfd_vma high_line_vma = ~0;
+  bfd_vma low_func_vma = 0;
+  asymbol *func = 0;
+  *filename_ptr = abfd->filename;
+  *functionname_ptr = 0;
+  *line_ptr = 0;
+  if (symbols != (asymbol **)NULL) {
+    for (p = symbols; *p; p++) {
+      aout_symbol_type  *q = (aout_symbol_type *)(*p);
+      switch (q->type){
+      case N_SO:
+       *filename_ptr = q->symbol.name;
+       if (obj_textsec(abfd) != section) {
+         return true;
+       }
+       break;
+      case N_SLINE:
+
+      case N_DSLINE:
+      case N_BSLINE:
+       /* We'll keep this if it resolves nearer than the one we have already */
+       if (q->symbol.value >= offset &&
+           q->symbol.value < high_line_vma) {
+         *line_ptr = q->desc;
+         high_line_vma = q->symbol.value;
+       }
+       break;
+      case N_FUN:
+       {
+         /* We'll keep this if it is nearer than the one we have already */
+         if (q->symbol.value >= low_func_vma &&
+             q->symbol.value <= offset) {
+           low_func_vma = q->symbol.value;
+           func = (asymbol *)q;
+         }
+         if (*line_ptr && func) {
+           char *function = func->name;
+           char *p;
+           strncpy(buffer, function, sizeof(buffer)-1);
+           buffer[sizeof(buffer)-1] = 0;
+           /* Have to remove : stuff */
+           p = strchr(buffer,':');
+           if (p != NULL) {*p = NULL; }
+           *functionname_ptr = buffer;
+           return true;
+
+         }
+       }
+       break;
+      }
+    }
+  }
+  
+  return true;
+
+}
+
+bfd_target aoutvec =
+{
+  "a.out-generic-big",         /* name */
+  bfd_target_aout_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  sunos4_close_and_cleanup,    /* _close_and_cleanup */
+  sunos4_set_section_contents, /* bfd_set_section_contents */
+  sunos4_get_section_contents, /* bfd_get_section_contents */
+  sunos4_new_section_hook,     /* new_section_hook */
+  sunos4_core_file_failing_command, /* _core_file_failing_command */
+  sunos4_core_file_failing_signal, /* _core_file_failing_signal */
+  sunos4_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_bsd_armap,         /* bfd_slurp_armap */
+  bfd_true,                    /* bfd_slurp_extended_name_table */
+  bfd_bsd_truncate_arname,     /* bfd_truncate_arname */
+
+  sunos4_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  sunos4_get_symtab,           /* canonicalize_symtab */
+  sunos4_reclaim_symbol_table, /* bfd_reclaim_symbol_table */
+  sunos4_get_reloc_upper_bound,        /* get_reloc_upper_bound */
+  sunos4_canonicalize_reloc,   /* bfd_canonicalize_reloc */
+  sunos4_reclaim_reloc,                /* bfd_reclaim_reloc */
+  sunos4_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  sunos4_get_first_symbol,     /* bfd_get_first_symbol */
+  sunos4_get_next_symbol,      /* bfd_get_next_symbol */
+  sunos4_classify_symbol,      /* bfd_classify_symbol */
+  sunos4_symbol_hasclass,      /* bfd_symbol_hasclass */
+  sunos4_symbol_name,          /* bfd_symbol_name */
+  sunos4_symbol_value,         /* bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, sunos4_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, sunos4_core_file_p},
+  {bfd_false, sunos4_mkobject, /* bfd_zxset_format */
+     _bfd_generic_mkarchive, bfd_false},
+  sunos4_make_empty_symbol,
+  sunos4_print_symbol,
+  sunos4_get_lineno,
+  sunos4_set_arch_mach,
+  bsd_write_armap,
+  bfd_generic_openr_next_archived_file,
+  sunos4_find_nearest_line,    /* bfd_find_nearest_line */
+  bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
diff --git a/bfd/archive.c b/bfd/archive.c
new file mode 100644 (file)
index 0000000..53cd0bd
--- /dev/null
@@ -0,0 +1,1223 @@
+/*** archive.c -- an attempt at combining the machine-independent parts of
+  archives */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Assumes:
+   o - all archive elements start on an even boundary, newline padded;
+   o - all arch headers are char *;
+   o - all arch headers are the same size (across architectures).
+*/
+
+/* $Id$ 
+ * $Log$
+ * Revision 1.1  1991/03/21 21:10:42  gumby
+ * Initial revision
+ *
+ * Revision 1.3  1991/03/16  05:55:25  rich
+ * pop
+ *
+ * Revision 1.2  1991/03/15  18:15:50  rich
+ * *** empty log message ***
+ *
+ * Revision 1.7  1991/03/08  04:18:02  rich
+ * *** empty log message ***
+ *
+ * Revision 1.6  1991/03/07  21:55:31  sac
+ * Added primitive file caching, a file open only for input and
+ * less than BFD_INCORE_FILE_SIZE will be malloced and read in
+ * only once.
+ *
+ * Revision 1.5  1991/03/05  16:31:12  sac
+ * lint
+ *
+ */
+
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "ar.h"
+#include "ranlib.h"
+
+/* We keep a cache of archive filepointers to archive elements to
+   speed up searching the archive by filepos.  We only add an entry to
+   the cache when we actually read one.  We also don't sort the cache;
+   it's short enough to search linearly.
+   Note that the pointers here point to the front of the ar_hdr, not
+   to the front of the contents!
+*/
+struct ar_cache {
+  file_ptr ptr;
+  bfd* arelt;
+  struct ar_cache *next;
+};
+
+#define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
+#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
+
+#define arch_hdr(bfd) ((struct ar_hdr *)   \
+                      (((struct areltdata *)((bfd)->arelt_data))->arch_header))
+
+\f
+
+boolean
+_bfd_generic_mkarchive (abfd)
+     bfd *abfd;
+{
+  abfd->tdata =(void *) zalloc (sizeof (struct artdata));
+
+  if (abfd->tdata == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+bfd_ardata(abfd)->cache = 0;
+  return true;
+}
+
+symindex
+bfd_get_next_mapent (abfd, prev, entry)
+     bfd *abfd;
+   symindex prev;
+     carsym **entry;
+{
+  if (!bfd_has_map (abfd)) {
+    bfd_error = invalid_operation;
+    return BFD_NO_MORE_SYMBOLS;
+  }
+  
+  if (prev == BFD_NO_MORE_SYMBOLS) prev = 0;
+  else if (++prev >= (symindex)(bfd_ardata (abfd)->symdef_count))
+    return BFD_NO_MORE_SYMBOLS;
+
+  *entry = (bfd_ardata (abfd)->symdefs + prev);
+  return prev;
+}
+
+
+/* To be called by backends only */
+bfd *
+_bfd_create_empty_archive_element_shell (obfd)
+     bfd *obfd;
+{
+  bfd *nbfd;
+
+  nbfd = new_bfd_contained_in(obfd);
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+  return nbfd;
+}
+
+boolean
+bfd_set_archive_head (output_archive, new_head)
+     bfd *output_archive, *new_head;
+{
+  output_archive->archive_head = new_head;
+  return true;
+}
+
+bfd *
+look_for_bfd_in_cache (arch_bfd, filepos)
+     bfd *arch_bfd;
+     file_ptr filepos;
+{
+  struct ar_cache *current;
+
+  for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
+       current = current->next)
+    if (current->ptr == filepos) return current->arelt;
+
+  return NULL;
+}
+
+/* Kind of stupid to call cons for each one, but we don't do too many */
+boolean
+add_bfd_to_cache (arch_bfd, filepos, new_elt)
+     bfd *arch_bfd, *new_elt;
+     file_ptr filepos;
+{
+  struct ar_cache *new_cache = ((struct ar_cache *)
+                               zalloc (sizeof (struct ar_cache)));
+
+  if (new_cache == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  new_cache->ptr = filepos;
+  new_cache->arelt = new_elt;
+  new_cache->next = (struct ar_cache *)NULL;
+  if (bfd_ardata (arch_bfd)->cache == NULL)
+    bfd_ardata (arch_bfd)->cache = new_cache;
+  else {
+    struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
+
+    for (; current->next != NULL; current = current->next);
+    current->next = new_cache;
+  }
+    
+  return true;
+}
+
+\f
+
+/* The name begins with space.  Hence the rest of the name is an index into
+   the string table. */
+
+char *
+get_extended_arelt_filename (arch, name)
+     bfd *arch;
+     char *name;
+{
+    extern int errno;
+    unsigned long index = 0;
+
+    /* Should extract string so that I can guarantee not to overflow into
+       the next region, but I"m too lazy. */
+    errno = 0;
+    index = strtol (name, NULL, 10);
+    if (errno != 0) {
+       bfd_error = malformed_archive;
+       return NULL;
+    }
+
+    return bfd_ardata (arch)->extended_names + index;
+}  
+
+/* This functions reads an arch header and returns an areltdata pointer, or
+   NULL on error.
+
+   Presumes the file pointer is already in the right place (ie pointing
+   to the ar_hdr in the file).   Moves the file pointer; on success it
+   should be pointing to the front of the file contents; on failure it
+   could have been moved arbitrarily.
+*/
+
+struct areltdata *
+snarf_ar_hdr (abfd)
+     bfd *abfd;
+{
+    extern int errno;
+    struct ar_hdr hdr;
+    char *hdrp = (char *) &hdr;
+    unsigned int parsed_size;
+    struct areltdata *ared;
+    char *filename = NULL;
+    unsigned int namelen = 0;
+    unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
+    char *allocptr;
+
+    if (bfd_read ((void *)hdrp, 1, sizeof (struct ar_hdr), abfd)
+       != sizeof (struct ar_hdr)) {
+       bfd_error = no_more_archived_files;
+       return NULL;
+    }
+    if (strncmp ((hdr.ar_fmag), ARFMAG, 2)) {
+       bfd_error = malformed_archive;
+       return NULL;
+    }
+
+    errno = 0;
+    parsed_size = strtol (hdr.ar_size, NULL, 10);
+    if (errno != 0) {
+       bfd_error = malformed_archive;
+       return NULL;
+    }
+
+    /* extract the filename from the archive */
+    if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
+       filename = get_extended_arelt_filename (abfd, hdr.ar_name);
+       if (filename == NULL) {
+           bfd_error = malformed_archive;
+           return NULL;
+       }
+    } 
+    else 
+       {
+           /* We judge the end of the name by looking for a space or a
+              padchar */
+
+           namelen = 0;
+
+           while (namelen < ar_maxnamelen(abfd) &&
+                  ( hdr.ar_name[namelen] != 0 &&
+                   hdr.ar_name[namelen] != ' ' &&
+                   hdr.ar_name[namelen] != ar_padchar(abfd))) {
+               namelen++;
+           }
+
+           allocsize += namelen + 1;
+       }
+
+    allocptr = zalloc (allocsize);
+    if (allocptr == NULL) {
+       bfd_error = no_memory;
+       return NULL;
+    }
+
+    ared = (struct areltdata *) allocptr;
+
+    ared->arch_header = allocptr + sizeof (struct areltdata);
+    memcpy ((char *) ared->arch_header, &hdr, sizeof (struct ar_hdr));
+    ared->parsed_size = parsed_size;
+
+    if (filename != NULL) ared->filename = filename;
+    else {
+       ared->filename = allocptr + (sizeof (struct areltdata) +
+                                    sizeof (struct ar_hdr));
+       if (namelen)
+           memcpy (ared->filename, hdr.ar_name, namelen);
+       ared->filename[namelen] = '\0';
+    }
+  
+    return ared;
+}
+\f
+bfd *
+get_elt_at_filepos (archive, filepos)
+     bfd *archive;
+     file_ptr filepos;
+{
+  struct areltdata *new_areldata;
+  bfd *n_nfd;
+
+  n_nfd = look_for_bfd_in_cache (archive, filepos);
+  if (n_nfd) return n_nfd;
+
+  if (0 > bfd_seek (archive, filepos, SEEK_SET)) {
+    bfd_error = system_call_error;
+    return NULL;
+  }
+
+  if ((new_areldata = snarf_ar_hdr (archive)) == NULL) return NULL;
+  
+  n_nfd = _bfd_create_empty_archive_element_shell (archive);
+  if (n_nfd == NULL) {
+    free (new_areldata);
+    return NULL;
+  }
+  n_nfd->origin = bfd_tell (archive);
+  n_nfd->arelt_data = (void *) new_areldata;
+  n_nfd->filename = new_areldata->filename;
+
+  if (add_bfd_to_cache (archive, filepos, n_nfd))
+    return n_nfd;
+
+  /* huh? */
+  free (new_areldata);
+  free (n_nfd);
+  return NULL;
+}
+
+bfd *
+bfd_get_elt_at_index (abfd, index)
+     bfd *abfd;
+     int index;
+{
+  bfd *result =
+    get_elt_at_filepos
+      (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset);
+  return result;
+}
+
+/* If you've got an archive, call this to read each subfile. */
+bfd *
+bfd_openr_next_archived_file (archive, last_file)
+     bfd *archive, *last_file;
+{
+
+  if ((bfd_get_format (archive) != bfd_archive) ||
+      (archive->direction == write_direction)) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+
+
+  return BFD_SEND (archive,
+                  openr_next_archived_file,
+                  (archive,
+                   last_file));
+
+}
+
+bfd *bfd_generic_openr_next_archived_file(archive, last_file)
+     bfd *archive;
+     bfd *last_file;
+{
+  file_ptr filestart;
+
+  if (!last_file)
+    filestart = bfd_ardata (archive)->first_file_filepos;
+  else {
+  unsigned int size = arelt_size(last_file);
+    filestart = last_file->origin +size + size %2;
+}
+
+
+
+  return get_elt_at_filepos (archive, filestart);
+}
+\f
+
+bfd_target *
+bfd_generic_archive_p (abfd)
+     bfd *abfd;
+{
+  char armag[SARMAG+1];
+
+  if (bfd_read ((void *)armag, 1, SARMAG, abfd) != SARMAG) {
+    bfd_error = wrong_format;
+    return 0;
+  }
+
+  if (strncmp (armag, ARMAG, SARMAG)) return 0;
+
+  bfd_set_ardata(abfd, (struct artdata *) zalloc (sizeof (struct artdata)));
+
+  if (bfd_ardata (abfd)  == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  bfd_ardata (abfd)->first_file_filepos = SARMAG;
+  
+  if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) {
+    free (bfd_ardata (abfd));
+    abfd->tdata = NULL;
+    return 0;
+  }
+
+  /* armap could be left ungc'd! FIXME -- potential storage leak */
+  if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) {
+    free (bfd_ardata (abfd));
+    abfd->tdata = NULL;
+    return 0;
+  }
+  
+  return abfd->xvec;
+}
+
+/* Returns false on error, true otherwise */
+boolean
+bfd_slurp_bsd_armap (abfd)
+     bfd *abfd;
+{
+  struct areltdata *mapdata;
+  char nextname[17];
+  unsigned int counter = 0;
+  int *raw_armap, *rbase;
+  struct artdata *ardata = bfd_ardata (abfd);
+  char *stringbase;
+
+  if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
+      /* The archive has at least 16 bytes in it */
+      bfd_seek (abfd, -16L, SEEK_CUR);
+
+      if (strncmp (nextname, "__.SYMDEF       ", 16)) {
+         bfd_has_map (abfd) = false;
+         return true;
+      }
+
+      mapdata = snarf_ar_hdr (abfd);
+      if (mapdata == NULL) return false;
+
+      raw_armap = (int *) zalloc (mapdata->parsed_size);
+      if (raw_armap == NULL) {
+         bfd_error = no_memory;
+  byebye:
+         free (mapdata);
+         return false;
+      }
+
+      if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
+         mapdata->parsed_size) {
+         bfd_error = malformed_archive;
+         free (raw_armap);
+         goto byebye;
+      }
+
+      ardata->symdef_count = *(raw_armap) / sizeof (struct symdef);
+      ardata->cache = 0;
+      rbase = raw_armap+1;
+      ardata->symdefs = (carsym *) rbase;
+      stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
+
+      for (;counter < (unsigned)( ardata->symdef_count); counter++) {
+         struct symdef *sym = ((struct symdef *) rbase) + counter;
+         sym->s.name = sym->s.string_offset + stringbase;
+      }
+  
+      ardata->first_file_filepos = bfd_tell (abfd);
+      /* Pad to an even boundary if you have to */
+      ardata->first_file_filepos += (ardata-> first_file_filepos) %2;
+      free (mapdata);
+      bfd_has_map (abfd) = true;
+  }
+  return true;
+}
+
+/* Returns false on error, true otherwise */
+boolean
+bfd_slurp_coff_armap (abfd)
+     bfd *abfd;
+{
+  struct areltdata *mapdata;
+  char nextname;
+  int *raw_armap, *rawptr;
+  struct artdata *ardata = bfd_ardata (abfd);
+  char *stringbase;
+  unsigned int stringsize;
+  carsym *carsyms;
+
+  if (bfd_read ((void *)&nextname, 1, 1, abfd) != 1) {
+    bfd_has_map(abfd) = false;
+    return true;
+  }
+
+  if (nextname != '/') {
+    /* Actually I think this is an error for a COFF archive */
+    bfd_has_map (abfd) = false;
+    return true;
+  }
+
+  bfd_seek (abfd, -1L, SEEK_CUR);
+  mapdata = snarf_ar_hdr (abfd);
+  if (mapdata == NULL) return false;
+
+  raw_armap = (int *) zalloc (mapdata->parsed_size);
+  if (raw_armap == NULL) {
+    bfd_error = no_memory;
+  byebye:
+    free (mapdata);
+    return false;
+  }
+
+  if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
+      mapdata->parsed_size) {
+    bfd_error = malformed_archive;
+  oops:
+    free (raw_armap);
+    goto byebye;
+  }
+
+  /* The coff armap must be read sequentially.  So we construct a bsd-style
+     one in core all at once, for simplicity. */
+
+  stringsize = mapdata->parsed_size - (4 * (*raw_armap)) - 4;
+
+  {
+    unsigned int nsymz = *raw_armap;
+    unsigned int carsym_size = (nsymz * sizeof (carsym));
+    unsigned int ptrsize = (4 * nsymz);
+    unsigned int i;
+    ardata->symdefs = (carsym *) zalloc (carsym_size + stringsize + 1);
+    if (ardata->symdefs == NULL) {
+      bfd_error = no_memory;
+      goto oops;
+    }
+    carsyms = ardata->symdefs;
+
+    stringbase = ((char *) ardata->symdefs) + carsym_size;
+    memcpy (stringbase, (char*)raw_armap + ptrsize + 4,  stringsize);
+
+
+    /* OK, build the carsyms */
+    for (i = 0; i < nsymz; i++) 
+      {
+       rawptr = raw_armap + i + 1;
+       carsyms->file_offset = *rawptr;
+       carsyms->name = stringbase;
+       for (; *(stringbase++););
+       carsyms++;
+      }
+    *stringbase = 0;
+  }
+  ardata->symdef_count = *raw_armap;
+  ardata->first_file_filepos = bfd_tell (abfd);
+  /* Pad to an even boundary if you have to */
+  ardata->first_file_filepos += (ardata->first_file_filepos) %2;
+  free (raw_armap);
+  free (mapdata);
+  bfd_has_map (abfd) = true;
+  return true;
+}
+
+\f
+/** Extended name table.
+
+  Normally archives support only 14-character filenames.  Intel has extended
+  the format: longer names are stored in a special element (the first in the
+  archive, or second if there is an armap); the name in the ar_hdr is replaced
+  by <space><index into filename element>.  Index is the P.R. of an int (radix:
+  8). */
+
+/* Returns false on error, true otherwise */
+boolean
+_bfd_slurp_extended_name_table (abfd)
+     bfd *abfd;
+{
+  char nextname[17];
+  struct areltdata *namedata;
+
+  if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
+
+  bfd_seek (abfd, -16L, SEEK_CUR);
+
+  if (strncmp (nextname, "ARFILENAMES/    ", 16)) {
+    bfd_ardata (abfd)->extended_names = NULL;
+    return true;
+  }
+
+  namedata = snarf_ar_hdr (abfd);
+  if (namedata == NULL) return false;
+  
+  
+  bfd_ardata (abfd)->extended_names = zalloc (namedata->parsed_size);
+  if (bfd_ardata (abfd)->extended_names == NULL) {
+    bfd_error = no_memory;
+  byebye:
+    free (namedata);
+    return false;
+  }
+
+  if (bfd_read ((void*)bfd_ardata (abfd)->extended_names, 1,
+               namedata->parsed_size, abfd) != namedata->parsed_size) {
+    bfd_error = malformed_archive;
+    free (bfd_ardata (abfd)->extended_names);
+    bfd_ardata (abfd)->extended_names = NULL;
+    goto byebye;
+  }
+
+  /* Pad to an even boundary if you have to */
+  bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
+  bfd_ardata (abfd)->first_file_filepos +=
+    (bfd_ardata (abfd)->first_file_filepos) %2;
+
+  free (namedata);
+}
+  return true;
+}
+
+static
+char *normalize(file)
+char *file;
+{
+    char *    filename = strrchr(file, '/');
+    if (filename != (char *)NULL) {
+       filename ++;
+    }
+    else {
+       filename = file;
+    }
+return filename;
+}
+
+/* Follows archive_head and produces an extended name table if necessary.
+   Returns (in tabloc) a pointer to an extended name table, and in tablen
+   the length of the table.  If it makes an entry it clobbers the filename
+   so that the element may be written without further massage.
+   Returns true if it ran successfully, false if something went wrong.
+   A successful return may still involve a zero-length tablen!
+   */
+boolean
+bfd_construct_extended_name_table (abfd, tabloc, tablen)
+     bfd *abfd;
+     char **tabloc;
+     unsigned int *tablen;
+{
+    unsigned int maxname = abfd->xvec->ar_max_namelen;
+    unsigned int total_namelen = 0;
+    bfd *current;
+    char *strptr;
+
+    *tablen = 0;
+  
+    /* Figure out how long the table should be */
+    for (current = abfd->archive_head; current != NULL; current = current->next){
+       unsigned int thislen = strlen (normalize(current->filename));
+       if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \0 */
+    }
+
+    if (total_namelen == 0) return true;
+
+    *tabloc = zalloc (total_namelen);
+    if (*tabloc == NULL) {
+       bfd_error = no_memory;
+       return false;
+    }
+
+    *tablen = total_namelen;
+    strptr = *tabloc;
+
+    for (current = abfd->archive_head; current != NULL; current =
+        current->next) {
+       char *normal =normalize( current->filename);
+       unsigned int thislen = strlen (normal);
+       if (thislen > maxname) {
+           strcpy (strptr, normal);
+           current->filename[0] = ' ';
+           /* We know there will always be enough room (one of the few cases
+              where you may safely use sprintf). */
+           sprintf ((current->filename) + 1, "-%o", (unsigned) (strptr - *tabloc));
+
+           strptr += thislen + 1;
+       }
+    }
+
+    return true;
+}
+\f
+/** A couple of functions for creating ar_hdrs */
+
+/* Takes a filename, returns an arelt_data for it, or NULL if it can't make one.
+   The filename must refer to a filename in the filesystem.
+   The filename field of the ar_hdr will NOT be initialized
+*/
+
+struct areltdata *
+bfd_ar_hdr_from_filesystem (filename)
+     char *filename;
+{
+  struct stat status;
+  struct areltdata *ared;
+  struct ar_hdr *hdr;
+  char *temp, *temp1;
+
+
+  if (stat (filename, &status) != 0) {
+    bfd_error = system_call_error;
+    return NULL;
+  }
+
+  ared = (struct areltdata *) zalloc (sizeof (struct ar_hdr) +
+                                     sizeof (struct areltdata));
+  if (ared == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+  hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
+
+  /* ar headers are space padded, not null padded! */
+  temp = (char *) hdr;
+  temp1 = temp + sizeof (struct ar_hdr) - 2;
+  for (; temp < temp1; *(temp++) = ' ');
+  strncpy (hdr->ar_fmag, ARFMAG, 2);
+  
+  /* Goddamned sprintf doesn't permit MAXIMUM field lengths */
+  sprintf ((hdr->ar_date), "%-12ld", status.st_mtime);
+  sprintf ((hdr->ar_uid), "%d", status.st_uid);
+  sprintf ((hdr->ar_gid), "%d", status.st_gid);
+  sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode);
+  sprintf ((hdr->ar_size), "%-10ld", status.st_size);
+  /* Correct for a lossage in sprintf whereby it null-terminates.  I cannot
+     understand how these C losers could design such a ramshackle bunch of
+     IO operations */
+  temp = (char *) hdr;
+  temp1 = temp + sizeof (struct ar_hdr) - 2;
+  for (; temp < temp1; temp++) {
+    if (*temp == '\0') *temp = ' ';
+  }
+  strncpy (hdr->ar_fmag, ARFMAG, 2);
+  ared->parsed_size = status.st_size;
+  ared->arch_header = (char *) hdr;
+
+  return ared;
+}
+
+struct ar_hdr *
+bfd_special_undocumented_glue (filename)
+     char *filename;
+{
+
+  return (struct ar_hdr *) bfd_ar_hdr_from_filesystem (filename) -> arch_header;
+}
+
+
+/* Analogous to stat call */
+int
+bfd_generic_stat_arch_elt (abfd, buf)
+     bfd *abfd;
+     struct stat *buf;
+{
+  struct ar_hdr *hdr;
+  char *aloser;
+  
+  if (abfd->arelt_data == NULL) {
+    bfd_error = invalid_operation;
+    return -1;
+  }
+    
+  hdr = arch_hdr (abfd);
+
+#define foo(arelt, stelt, size)  \
+  buf->stelt = strtol (hdr->arelt, &aloser, size); \
+  if (aloser == hdr->arelt) return -1;
+  
+  foo (ar_date, st_mtime, 10);
+  foo (ar_uid, st_uid, 10);
+  foo (ar_gid, st_gid, 10);
+  foo (ar_mode, st_mode, 8);
+  foo (ar_size, st_size, 10);
+
+  return 0;
+}
+
+/* Don't do anything -- it'll be taken care of later */
+void
+bfd_dont_truncate_arname (ignore_abfd, ignore_filename, ignore_arhdr)
+     bfd *ignore_abfd;
+     char *ignore_filename;
+     char *ignore_arhdr;
+{
+  /* FIXME -- Actually this is incorrect.  If the name is short we
+    should insert into the header; only if it is long should we do
+    nothing.
+
+    Anyway, this interacts unpleasantly with ar's quick-append option,
+    for now just be compatible with the old system */
+
+  return;
+}
+
+void
+bfd_bsd_truncate_arname (abfd, pathname, arhdr)
+     bfd *abfd;
+     char *pathname;
+     char *arhdr;
+{
+  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+  int length;
+  char *filename = strrchr (pathname, '/');
+  int maxlen = ar_maxnamelen (abfd);
+
+
+  if (filename == NULL)
+    filename = pathname;
+  else
+    ++filename;
+
+  length = strlen (filename);
+
+  if (length <= maxlen)
+    memcpy (hdr->ar_name, filename, length);
+  else {
+    /* pathname: meet procrustes */
+    memcpy (hdr->ar_name, filename, maxlen);
+    length = maxlen;
+  }
+
+  if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
+}
+
+/* Store name into ar header.  Truncates the name to fit.
+   1> strip pathname to be just the basename.
+   2> if it's short enuf to fit, stuff it in.
+   3> If it doesn't end with .o, truncate it to fit
+   4> truncate it before the .o, append .o, stuff THAT in.
+*/
+
+/* This is what gnu ar does.  It's better but incompatible with the bsd ar. */
+void
+bfd_gnu_truncate_arname (abfd, pathname, arhdr)
+     bfd *abfd;
+     char *pathname;
+     char *arhdr;
+{
+  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+  int length;
+  char *filename = strrchr (pathname, '/');
+  int maxlen = ar_maxnamelen (abfd);
+       
+  if (filename == NULL)
+    filename = pathname;
+  else
+    ++filename;
+
+  length = strlen (filename);
+
+  if (length <= maxlen)
+    memcpy (hdr->ar_name, filename, length);
+  else {                       /* pathname: meet procrustes */
+    memcpy (hdr->ar_name, filename, maxlen);
+    if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) {
+      hdr->ar_name[maxlen - 2] = '.';
+      hdr->ar_name[maxlen - 1] = 'o';
+    }
+    length = maxlen;
+  }
+
+  if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
+}
+\f
+
+PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));
+
+/* The bfd is open for write and has its format set to bfd_archive */
+boolean
+_bfd_write_archive_contents (arch)
+     bfd *arch;
+{
+  bfd *current;
+  char *etable = NULL;
+  unsigned int elength = 0;
+  boolean makemap = bfd_has_map (arch);
+  boolean hasobjects = false;  /* if no .o's, don't bother to make a map */
+  unsigned int i;
+
+
+  /* Verify the viability of all entries; if any of them live in the
+     filesystem (as opposed to living in an archive open for input)
+     then construct a fresh ar_hdr for them.
+     */
+  for (current = arch->archive_head; current; current = current->next) {
+    if (bfd_write_p (current)) {
+      bfd_error = invalid_operation;
+      return false;
+    }
+    if (!current->arelt_data) {
+      current->arelt_data =
+         (void *) bfd_ar_hdr_from_filesystem (current->filename);
+      if (!current->arelt_data) return false;
+
+      /* Put in the file name */
+    
+    BFD_SEND (arch, _bfd_truncate_arname,(arch, 
+                                         current->filename,
+                                         arch_hdr(current)));
+
+      
+    }
+
+    if (makemap) {             /* don't bother if we won't make a map! */
+      if ((bfd_check_format (current, bfd_object))
+#if 0                          /* FIXME -- these are not set correctly */
+         && ((bfd_get_file_flags (current) & HAS_SYMS))
+#endif
+         )
+       hasobjects = true;
+    }
+  }
+
+  if (!bfd_construct_extended_name_table (arch, &etable, &elength))
+    return false;
+
+  bfd_seek (arch, 0, SEEK_SET);
+  bfd_write (ARMAG, 1, SARMAG, arch);
+
+  if (makemap && hasobjects) {
+
+    if (compute_and_write_armap (arch, elength) != true) {
+      if (etable) free (etable);
+      return false;
+    }
+  }
+
+  if (elength != 0) {
+    struct ar_hdr hdr;
+
+    memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+    sprintf (&(hdr.ar_name[0]), "ARFILENAMES/");
+    sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
+    hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
+    for (i = 0; i < sizeof (struct ar_hdr); i++)
+      if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
+    bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+    bfd_write (etable, 1, elength, arch);
+    if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
+    if (etable) free (etable);
+  }
+
+  for (current = arch->archive_head; current; current = current->next) {
+    char buffer[DEFAULT_BUFFERSIZE];
+    unsigned int remaining = arelt_size (current);
+    struct ar_hdr *hdr = arch_hdr(current);
+    /* write ar header */
+
+    if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
+    syserr:
+       bfd_error = system_call_error;
+       return false;
+      }
+    if (bfd_seek (current, 0L, SEEK_SET) != 0L) goto syserr;
+    while (remaining) {
+      unsigned int amt = ((remaining <= DEFAULT_BUFFERSIZE) ? remaining :
+                         DEFAULT_BUFFERSIZE);
+
+      if (bfd_read (buffer, amt, 1, current) != amt) goto syserr;
+      if (bfd_write (buffer, amt, 1, arch)   != amt) goto syserr;
+      remaining -= amt;
+    }
+    if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);
+  }
+return true;
+}
+\f
+/* Note that the namidx for the first symbol is 0 */
+
+  
+
+boolean
+compute_and_write_armap (arch, elength)
+     bfd *arch;
+     unsigned int elength;
+{
+  bfd *current;
+  file_ptr elt_no = 0;
+  struct orl *map;
+  int orl_max = 15000;         /* fine initial default */
+  int orl_count = 0;
+  int stridx = 0;              /* string index */
+
+  /* Dunno if this is the best place for this info... */
+  if (elength != 0) elength += sizeof (struct ar_hdr);
+  elength += elength %2 ;
+
+  map = (struct orl *) zalloc (orl_max * sizeof (struct orl));
+  if (map == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  /* Map over each element */
+  for (current = arch->archive_head;
+       current != (bfd *)NULL;
+       current = current->next, elt_no++) 
+      {
+    if ((bfd_check_format (current, bfd_object) == true)
+       && ((bfd_get_file_flags (current) & HAS_SYMS))) {
+      asymbol **syms;
+      unsigned int storage;
+      unsigned int symcount;
+      unsigned int src_count;
+
+      storage = get_symtab_upper_bound (current);
+      if (storage == 0) {
+      nosymz:
+       fprintf (stderr, "%s: Symflags set but there are none?\n",
+                bfd_get_filename (current));
+       exit (1);
+      }
+      syms = (asymbol **) zalloc (storage);
+      if (syms == NULL) {
+       bfd_error = no_memory;  /* FIXME -- memory leak */
+       return false;
+      }
+      symcount = bfd_canonicalize_symtab (current, syms);
+      if (symcount == 0) goto nosymz;
+
+      /* Now map over all the symbols, picking out the ones we want */
+      for (src_count = 0; src_count <symcount; src_count++) {
+       flagword flags = (syms[src_count])->flags;
+       if ((flags & BSF_GLOBAL) ||
+           (flags & BSF_FORT_COMM)) {
+
+         /* This symbol will go into the archive header */
+         if (orl_count == orl_max) 
+             {
+           orl_max *= 2;
+           map = (struct orl *) realloc ((char *) map,
+                                         orl_max * sizeof (struct orl));
+         }
+
+         (map[orl_count]).name = &((syms[src_count])->name);
+         (map[orl_count]).pos = elt_no;
+         (map[orl_count]).namidx = stridx;
+
+         stridx += strlen ((syms[src_count])->name) + 1;
+         ++orl_count;
+       }
+      }
+    }
+  }
+  /* OK, now we have collected all the data, let's write them out */
+  if (!BFD_SEND (arch, write_armap,
+                (arch, elength, map, orl_count, stridx))) {
+    free (map);
+    return false;
+  }
+
+  free (map);
+  return true;
+}
+
+\f
+ /* FIXME -- have to byte-swap this */
+
+boolean
+bsd_write_armap (arch, elength, map, orl_count, stridx)
+     bfd *arch;
+     unsigned int elength;
+     struct orl *map;
+     int orl_count;
+     int stridx;
+{
+  unsigned int ranlibsize = (orl_count * sizeof (struct ranlib)) + 4;
+  unsigned int stringsize = stridx + 4;
+  unsigned int mapsize = stringsize + ranlibsize;
+  file_ptr firstreal;
+  bfd *current = arch->archive_head;
+  int last_eltno = 0;          /* last element arch seen */
+  int temp;
+  int count;
+  struct ar_hdr hdr;
+  struct stat statbuf;
+  unsigned int i;
+  int padit = mapsize & 1;
+  
+  if (padit) mapsize ++;
+
+  firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
+
+  fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
+  memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+  sprintf (hdr.ar_name, "__.SYMDEF");
+  sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+  sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
+  hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
+  for (i = 0; i < sizeof (struct ar_hdr); i++)
+    if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
+  bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+
+  temp = orl_count /* + 4 */;
+  bfd_write (&temp, 1, sizeof (temp), arch);
+  
+  for (count = 0; count < orl_count; count++) {
+    struct symdef outs;
+    struct symdef *outp = &outs;
+    
+    if ((map[count]).pos != last_eltno) {
+      firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+      firstreal += firstreal % 2;
+    last_eltno = (map[count]).pos;
+      current = current->next;
+    }
+
+    outs.s.string_offset = ((map[count]).namidx) +4;
+    outs.file_offset = firstreal;
+    bfd_write ((char *)outp, 1, sizeof (outs), arch);
+  }
+
+  /* now write the strings themselves */
+  temp = stridx + 4;
+  bfd_write (&temp, 1, sizeof (temp), arch);
+  for (count = 0; count < orl_count; count++)
+    bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
+
+  /* The spec sez this should be a newline.  But in order to be
+     bug-compatible for sun's ar we use a null. */
+  if (padit)
+    bfd_write("\0",1,1,arch);
+
+  return true;
+}
+\f
+
+/* A coff armap looks like :
+ ARMAG
+ struct ar_hdr with name = '/' 
+ number of symbols
+ offset of file for symbol 0
+ offset of file for symbol 1
+    ..
+ offset of file for symbol n-1
+ symbol name 0
+ symbol name 1 
+    ..
+ symbol name n-1
+
+*/
+  
+boolean
+coff_write_armap (arch, elength, map, orl_count, stridx)
+     bfd *arch;
+     unsigned int elength;
+     struct orl *map;
+     int orl_count;
+     int stridx;
+{
+    unsigned int ranlibsize = (orl_count * 4) + 4;
+    unsigned int stringsize = stridx;
+    unsigned int mapsize = stringsize + ranlibsize;
+    file_ptr archive_member_file_ptr;
+    bfd *current = arch->archive_head;
+    int last_eltno = 0;                /* last element arch seen */
+    int count;
+    struct ar_hdr hdr;
+    struct stat statbuf;
+    unsigned int i;
+    int padit = mapsize & 1;
+  
+    if (padit) mapsize ++;
+
+    archive_member_file_ptr =
+       mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
+
+    fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
+    memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
+    hdr.ar_name[0] = '/';
+    sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+    sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
+    hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
+
+    for (i = 0; i < sizeof (struct ar_hdr); i++)
+       if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
+
+    /* Write the ar header for this item and the number of symbols */
+
+    bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+    bfd_write (&orl_count, 1, sizeof (orl_count), arch);
+
+    /* Two passes, first write the file offsets for each symbol -
+       remembering that each offset is on a two byte boundary
+       */
+
+    for (count = 0; count < orl_count; count++) {
+       while ((map[count]).pos != last_eltno) {
+           /* If this is the first time we've seen a ref to this archive
+              then remember it's size */
+           archive_member_file_ptr +=
+               arelt_size (current) + sizeof (struct ar_hdr);
+           archive_member_file_ptr += archive_member_file_ptr % 2;
+           current = current->next;
+           last_eltno++;
+       }
+       bfd_write (&archive_member_file_ptr,
+                  1,
+                  sizeof (archive_member_file_ptr),
+                  arch);
+    }
+
+    /* now write the strings themselves */
+    for (count = 0; count < orl_count; count++) {
+       bfd_write (*((map[count]).name),
+                  1,
+                  strlen (*((map[count]).name))+1, arch);
+
+    }
+    /* The spec sez this should be a newline.  But in order to be
+       bug-compatible for arc960 we use a null. */
+    if (padit)
+       bfd_write("\0",1,1,arch);
+
+    return true;
+}
diff --git a/bfd/archures.c b/bfd/archures.c
new file mode 100644 (file)
index 0000000..b7fdaf9
--- /dev/null
@@ -0,0 +1,368 @@
+/* BFD library support routines for architectures. */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "archures.h"
+
+static char *prt_num_mach ();
+static boolean scan_num_mach ();
+static char *prt_960_mach ();
+static boolean scan_960_mach ();
+
+struct arch_print {
+       enum bfd_architecture arch;
+       char *astr;
+       char *(*mach_print)();
+       boolean (*mach_scan)();
+} arch_print[] = {
+
+       {bfd_arch_unknown,      "unknown",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_obscure,      "obscure",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_m68k,         "m68k",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_vax,          "vax",          prt_num_mach,   scan_num_mach},
+       {bfd_arch_i960,         "i960",         prt_960_mach,   scan_960_mach},
+       {bfd_arch_a29k,         "a29k",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_sparc,        "sparc",        prt_num_mach,   scan_num_mach},
+       {bfd_arch_mips,         "mips",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_i386,         "i386",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_ns32k,        "ns32k",        prt_num_mach,   scan_num_mach},
+       {bfd_arch_tahoe,        "tahoe",        prt_num_mach,   scan_num_mach},
+       {bfd_arch_i860,         "i860",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_romp,         "romp",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_alliant,      "alliant",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_convex,       "convex",       prt_num_mach,   scan_num_mach},
+       {bfd_arch_m88k,         "m88k",         prt_num_mach,   scan_num_mach},
+       {bfd_arch_pyramid,      "pyramid",      prt_num_mach,   scan_num_mach},
+       {bfd_arch_unknown,      (char *)0,      prt_num_mach,   scan_num_mach},
+};
+
+/* Return a printable string representing the architecture and machine
+   type.  The result is only good until the next call to
+   bfd_printable_arch_mach.  */
+
+char *
+bfd_printable_arch_mach (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  struct arch_print *ap;
+
+  for (ap = arch_print; ap->astr; ap++) {
+    if (ap->arch == arch) {
+      if (machine == 0)
+       return ap->astr;
+      return (*ap->mach_print)(ap, machine);
+    }
+  }
+  return "UNKNOWN!";
+}
+
+static char *
+prt_num_mach (ap, machine)
+     struct arch_print *ap;
+     unsigned long machine;
+{
+  static char result[20];
+
+  sprintf(result, "%s:%ld", ap->astr, (long) machine);
+  return result;
+}
+
+/* Scan a string and attempt to turn it into an archive and machine type
+   combination.  */
+
+boolean
+bfd_scan_arch_mach (string, archp, machinep)
+     char *string;
+     enum bfd_architecture *archp;
+     unsigned long *machinep;
+{
+  struct arch_print *ap;
+  int len;
+
+  /* First look for an architecture, possibly followed by machtype. */
+  for (ap = arch_print; ap->astr; ap++) {
+    if (ap->astr[0] != string[0])
+      continue;
+    len = strlen (ap->astr);
+    if (!strncmp (ap->astr, string, len)) {
+      /* We found the architecture, now see about the machine type */
+      if (archp)
+       *archp = ap->arch;
+      if (string[len] != '\0') {
+       if (ap->mach_scan (string+len, ap, archp, machinep, 1))
+         return true;
+      }
+      if (machinep)
+       *machinep = 0;
+      return true;
+    }
+  }
+
+  /* Couldn't find an architecture -- try for just a machine type */
+  for (ap = arch_print; ap->astr; ap++) {
+    if (ap->mach_scan (string, ap, archp, machinep, 0))
+      return true;
+  }
+
+  return false;
+}
+
+static boolean
+scan_num_mach (string, ap, archp, machinep, archspec)
+     char *string;
+     struct arch_print *ap;
+     enum bfd_architecture *archp;
+     unsigned long *machinep;
+     int archspec;
+{
+  enum bfd_architecture arch;
+  unsigned long machine;
+  char achar;
+
+  if (archspec) {
+
+    /* Architecture already specified, now go for machine type.  */
+    if (string[0] != ':')
+      return false;
+    /* We'll take any valid number that occupies the entire string */
+    if (1 != sscanf (string+1, "%lu%c", &machine, &achar))
+      return false;
+    arch = ap->arch;
+
+  } else {
+
+    /* We couldn't identify an architecture prefix.  Perhaps the entire
+       thing is a machine type.  Be a lot picker.  */
+    if (1 != sscanf (string, "%lu%c", &machine, &achar))
+      return false;
+    switch (machine) {
+    case 68010:
+    case 68020:
+    case 68030:
+    case 68040:
+    case 68332:
+    case 68050:                arch = bfd_arch_m68k; break;
+    case 68000:                arch = bfd_arch_m68k; machine = 0; break;
+
+    case 80960:
+    case 960:          arch = bfd_arch_i960; machine = 0; break;
+
+    case 386:
+    case 80386:                arch = bfd_arch_i386; machine = 0; break;
+    case 486:          arch = bfd_arch_i386; break;
+
+    case 29000:                arch = bfd_arch_a29k; machine = 0; break;
+
+    case 32016:
+    case 32032:
+    case 32132:
+    case 32232:
+    case 32332:
+    case 32432:
+    case 32532:                arch = bfd_arch_ns32k; break;
+    case 32000:                arch = bfd_arch_ns32k; machine = 0; break;
+
+    case 860:
+    case 80860:                arch = bfd_arch_i860; machine = 0; break;
+
+    default:           return false;
+    }
+  }
+
+  if (archp)
+    *archp = arch;
+  if (machinep)
+    *machinep = machine;
+  return true;
+}
+\f
+/* Intel 960 machine variants.  */
+
+static char *
+prt_960_mach (ap, machine)
+     struct arch_print *ap;
+     unsigned long machine;
+{
+  static char result[20];
+  char *str;
+
+  switch (machine) {
+  case bfd_mach_i960_core:     str = "core"; break;
+  case bfd_mach_i960_kb_sb:    str = "kb"; break;
+  case bfd_mach_i960_mc:       str = "mc"; break;
+  case bfd_mach_i960_xa:       str = "xa"; break;
+  case bfd_mach_i960_ca:       str = "ca"; break;
+  case bfd_mach_i960_ka_sa:    str = "ka"; break;
+  default:
+       return prt_num_mach (ap, machine);
+  }
+  sprintf (result, "%s:%s", ap->astr, str);
+  return result;
+}
+
+static boolean
+scan_960_mach (string, ap, archp, machinep, archspec)
+     char *string;
+     struct arch_print *ap;
+     enum bfd_architecture *archp;
+     unsigned long *machinep;
+     int archspec;
+{
+  unsigned long machine;
+
+  if (!archspec)
+    return false;
+  if (string[0] != ':')
+    return false;
+  string++;
+  if (string[0] == '\0')
+    return false;
+  if (string[0] == 'c' && string[1] == 'o' && string[2] == 'r' &&
+      string[3] == 'e' && string[4] == '\0')
+    machine = bfd_mach_i960_core;
+  else if (string[1] == '\0' || string[2] != '\0')     /* rest are 2-char */
+    return false;
+  else if (string[0] == 'k' && string[1] == 'b')
+    machine = bfd_mach_i960_kb_sb;
+  else if (string[0] == 's' && string[1] == 'b')
+    machine = bfd_mach_i960_kb_sb;
+  else if (string[0] == 'm' && string[1] == 'c')
+    machine = bfd_mach_i960_mc;
+  else if (string[0] == 'x' && string[1] == 'a')
+    machine = bfd_mach_i960_xa;
+  else if (string[0] == 'c' && string[1] == 'a')
+    machine = bfd_mach_i960_ca;
+  else if (string[0] == 'k' && string[1] == 'a')
+    machine = bfd_mach_i960_ka_sa;
+  else if (string[0] == 's' && string[1] == 'a')
+    machine = bfd_mach_i960_ka_sa;
+  else
+    return false;
+
+  if (archp)
+    *archp = ap->arch;
+  if (machinep)
+    *machinep = machine;
+  return true;
+}
+
+
+\f
+/* Determine whether two BFDs' architectures and machine types are
+   compatible.  Return merged architecture and machine type if nonnull
+   pointers.  */
+
+boolean
+bfd_arch_compatible (abfd, bbfd, archp, machinep)
+    bfd *abfd;
+    bfd *bbfd;
+    enum bfd_architecture *archp;
+    unsigned long *machinep;
+{
+  enum bfd_architecture archa, archb;
+  unsigned long macha, machb;
+  int pick_a;
+
+  archa = bfd_get_architecture (abfd);
+  archb = bfd_get_architecture (bbfd);
+  macha = bfd_get_machine (abfd);
+  machb = bfd_get_machine (bbfd);
+
+  if (archb == bfd_arch_unknown)
+       pick_a = 1;
+  else if (archa == bfd_arch_unknown)
+       pick_a = 0;
+  else if (archa != archb)
+       return false;                   /* Not compatible */
+  else {
+    /* Architectures are the same.  Check machine types.  */
+    if (macha == machb)                /* Same machine type */
+      pick_a = 1;
+    else if (machb == 0)       /* B is default */
+      pick_a = 1;
+    else if (macha == 0)       /* A is default */
+      pick_a = 0;
+    else switch (archa) {
+      /* If particular machine types of one architecture are not
+        compatible with each other, this is the place to put those tests
+        (returning false if incompatible).  */
+    case bfd_arch_i960:
+      /* The i960 has to distinct subspecies which may not interbreed:
+        CORE CA          
+        CORE KA KB MC
+        Any architecture on the same line is compatible, the one on
+        the right is the least restrictive.
+        */
+      /* So, if either is a ca then the other must be a be core or ca */
+      if (macha == bfd_mach_i960_ca) {
+       if (machb != bfd_mach_i960_ca &&
+           machb != bfd_mach_i960_core) {
+         return false;
+       }
+       pick_a = 1;
+      }
+      else      if (machb == bfd_mach_i960_ca) {
+       if (macha != bfd_mach_i960_ca &&
+           macha != bfd_mach_i960_core) {
+         return false;
+       }
+       pick_a = 0;
+      }
+      else {
+       /* This must be from the bottom row, so take the higest */
+       pick_a = (macha > machb);
+      }
+        
+        
+
+      break;
+
+      /* For these chips, as far as we care, "lower" numbers are included
+        by "higher" numbers, e.g. merge 68010 and 68020 into 68020,
+        386 and 486 into 486, etc.  This will need to change
+        if&when we care about things like 68332.  */
+    case bfd_arch_m68k:
+    case bfd_arch_ns32k:
+    case bfd_arch_i386:
+      pick_a = (macha > machb);
+      break;
+    
+      /* By default, pick first file's type, for lack of something better.  */
+    default:
+      pick_a = 1;
+    }
+  }
+
+  /* Set result based on our pick */
+  if (!pick_a) {
+    archa = archb;
+    macha = machb;
+  }
+  if (archp)
+    *archp = archa;
+  if (machinep)
+    *machinep = macha;
+
+  return true;
+}
diff --git a/bfd/archures.h b/bfd/archures.h
new file mode 100755 (executable)
index 0000000..b1f5594
--- /dev/null
@@ -0,0 +1,41 @@
+/* Intel 960 machine types */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+   Machine architecture and type definitions for BFD.
+
+   These definitions are only used inside the BFD package.  External programs
+   access them by calling bfd_scan_arch_mach() and bfd_arch_mach_string().
+
+   The architectures themselves are defined in bfd.h since they are an
+   enum needed for BFD structs.  Numeric machine types are simply used
+   as-is, e.g. 68020.  Non-numeric machine types like "i960CA" have
+   names in this file.  */
+
+/* $Id$ */
+
+#define        bfd_mach_i960_core      1
+#define        bfd_mach_i960_kb_sb     2
+#define        bfd_mach_i960_mc        3
+#define        bfd_mach_i960_xa        4
+#define        bfd_mach_i960_ca        5
+#define        bfd_mach_i960_ka_sa     6
+
diff --git a/bfd/bfd.c b/bfd/bfd.c
new file mode 100644 (file)
index 0000000..d93bc72
--- /dev/null
+++ b/bfd/bfd.c
@@ -0,0 +1,882 @@
+                          /* -*- C -*- */
+
+/*** bfd -- binary file diddling routines by Gumby Wallace of Cygnus Support.
+           Every definition in this file should be exported and declared
+           in bfd.c.  If you don't want it to be user-visible, put it in
+           libbfd.c!
+*/
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+short _bfd_host_big_endian = 0x0100;
+       /* Accessing the above as (*(char*)&_bfd_host_big_endian), will
+        * return 1 if the host is big-endian, 0 otherwise.
+        * (See HOST_IS_BIG_ENDIAN_P in bfd.h.)
+        */
+
+
+
+\f
+/** Error handling
+    o - Most functions return nonzero on success (check doc for
+       precise semantics); 0 or NULL on error.
+    o - Internal errors are documented by the value of bfd_error.
+       If that is system_call_error then check errno.
+    o - The easiest way to report this to the user is to use bfd_perror.
+*/
+
+bfd_ec bfd_error = no_error;
+
+char *bfd_errmsgs[] = {"No error",
+                      "System call error",
+                      "Invalid target",
+                      "File in wrong format",
+                      "Invalid operation",
+                      "Memory exhausted",
+                      "No symbols",
+                      "No relocation info",
+                      "No more archived files",
+                      "Malformed archive",
+                      "Symbol not found",
+                      "File format not recognized",
+                      "File format is ambiguous",
+                          "Section has no contents",
+                      "#<Invalid error code>"
+                      };
+
+#if !defined(ANSI_LIBRARIES)
+char *
+strerror (code)
+     int code;
+{
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+
+  return (((code < 0) || (code >= sys_nerr)) ? "(unknown error)" :
+         sys_errlist [code]);
+}
+#endif /* not ANSI_LIBRARIES */
+
+char *
+bfd_errmsg (error_tag)
+     bfd_ec error_tag;
+{
+       extern int errno;
+
+  if (error_tag == system_call_error)
+    return strerror (errno);
+
+  if ((((int)error_tag <(int) no_error) ||
+       ((int)error_tag > (int)invalid_error_code)))
+    error_tag = invalid_error_code;/* sanity check */
+
+  return bfd_errmsgs [(int)error_tag];
+}
+
+void
+bfd_perror (message)
+     char *message;
+{
+  if (bfd_error == system_call_error)
+    perror(message);           /* must be system error then... */
+  else {
+    if (message == NULL || *message == '\0')
+      fprintf (stderr, "%s\n", bfd_errmsg (bfd_error));
+    else
+      fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_error));
+  }
+}
+
+/* for error messages */
+char *
+bfd_format_string (format)
+     bfd_format format;
+{
+  if (((int)format <(int) bfd_unknown) || ((int)format >=(int) bfd_type_end)) return "invalid";
+  
+  switch (format) {
+  case bfd_object: return "object"; /* linker/assember/compiler output */
+  case bfd_archive: return "archive"; /* object archive file */
+  case bfd_core: return "core";        /* core dump */
+  default: return "unknown";
+  }
+}
+\f
+/** Target configurations */
+
+extern bfd_target *target_vector[];
+
+/* Returns a pointer to the transfer vector for the object target
+   named target_name.  If target_name is NULL, chooses the one in the
+   environment variable GNUTARGET; if that is null or not defined then
+   the first entry in the target list is chosen.  Passing in the
+   string "default" or setting the environment variable to "default"
+   will cause the first entry in the target list to be returned. */
+
+bfd_target *
+bfd_find_target (target_name)
+     char *target_name;
+{
+  bfd_target **target;
+  extern char *getenv ();
+  char *targname = (target_name ? target_name : getenv ("GNUTARGET"));
+
+  /* This is safe; the vector cannot be null */
+  if (targname == NULL || !strcmp (targname, "default"))
+    return target_vector[0];
+
+  for (target = &target_vector[0]; *target != NULL; target++) {
+    if (!strcmp (targname, (*target)->name))
+      return *target;
+  }
+
+  bfd_error = invalid_target;
+  return NULL;
+}
+
+/* Returns a freshly-consed, NULL-terminated vector of the names of all the
+   valid bfd targets.  Do not modify the names */
+
+char **
+bfd_target_list ()
+{
+  int vec_length= 0;
+  bfd_target **target;
+  char **name_list, **name_ptr;
+
+  for (target = &target_vector[0]; *target != NULL; target++)
+    vec_length++;
+
+  name_ptr = name_list = (char **) zalloc ((vec_length + 1) * sizeof (char **));
+
+  if (name_list == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  for (target = &target_vector[0]; *target != NULL; target++)
+    *(name_ptr++) = (*target)->name;
+
+  return name_list;
+}
+\f
+/** Init a bfd for read of the proper format.
+ */
+
+/* We should be able to find out if the target was defaulted or user-specified.
+   If the user specified the target explicitly then we should do no search.
+   I guess the best way to do this is to pass an extra argument which specifies
+   the DWIM. */
+
+/* I have chanegd this always to set the filepos to the origin before
+   guessing.  -- Gumby, 14 Februar 1991*/
+
+boolean
+bfd_check_format (abfd, format)
+     bfd *abfd;
+     bfd_format format;
+{
+#if obsolete
+  file_ptr filepos;
+#endif
+  bfd_target **target, *save_targ, *right_targ;
+  int match_count;
+
+  if (!bfd_read_p (abfd) ||
+      ((int)(abfd->format) < (int)bfd_unknown) ||
+      ((int)(abfd->format) >= (int)bfd_type_end)) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
+
+  /* presume the answer is yes */
+  abfd->format = format;
+
+#if obsolete
+  filepos = bfd_tell (abfd);
+#endif
+  bfd_seek (abfd, (file_ptr)0, SEEK_SET);      /* instead, rewind! */
+
+
+  right_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+  if (right_targ) {
+    abfd->xvec = right_targ;           /* Set the target as returned */
+    return true;                       /* File position has moved, BTW */
+  }
+
+  /* This isn't a <format> file in the specified or defaulted target type.
+     See if we recognize it for any other target type.  (We check them
+     all to make sure it's uniquely recognized.)  */
+
+  save_targ = abfd->xvec;
+  match_count = 0;
+  right_targ = 0;
+
+  for (target = target_vector; *target != NULL; target++) {
+    bfd_target *temp;
+
+    abfd->xvec = *target;      /* Change BFD's target temporarily */
+#if obsolete
+    bfd_seek (abfd, filepos, SEEK_SET);        /* Restore original file position */
+#endif
+    bfd_seek (abfd, (file_ptr)0, SEEK_SET);
+    temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd));
+    if (temp) {                                /* This format checks out as ok! */
+      right_targ = temp;
+      match_count++;
+    }
+  }
+
+  if (match_count == 1) {
+    abfd->xvec = right_targ;           /* Change BFD's target permanently */
+    return true;                       /* File position has moved, BTW */
+  }
+
+  abfd->xvec = save_targ;              /* Restore original target type */
+  abfd->format = bfd_unknown;          /* Restore original format */
+  bfd_error = ((match_count == 0) ? file_not_recognized :
+              file_ambiguously_recognized);
+#if  obsolete
+  bfd_seek (abfd, filepos, SEEK_SET);  /* Restore original file position */
+#endif
+  return false;
+}
+
+boolean
+bfd_set_format (abfd, format)
+     bfd *abfd;
+     bfd_format format;
+{
+  file_ptr filepos;
+
+  if (bfd_read_p (abfd) ||
+      ((int)abfd->format < (int)bfd_unknown) ||
+      ((int)abfd->format >= (int)bfd_type_end)) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  if (abfd->format != bfd_unknown) return (abfd->format == format) ? true:false;
+
+  /* presume the answer is yes */
+  abfd->format = format;
+
+  filepos = bfd_tell (abfd);
+
+  if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
+    abfd->format = bfd_unknown;
+    bfd_seek (abfd, filepos, SEEK_SET);
+    return false;
+  }
+
+  return true;
+}
+\f
+/* Hack object and core file sections */
+
+sec_ptr
+bfd_get_section_by_name (abfd, name)
+     bfd *abfd;
+     char *name;
+{
+  asection *sect;
+  
+  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+    if (!strcmp (sect->name, name)) return sect;
+  return NULL;
+}
+
+/* If you try to create a section with a name which is already in use,
+   returns the old section by that name instead. */
+sec_ptr
+bfd_make_section (abfd, name)
+     bfd *abfd;
+     char *name;
+{
+  asection *newsect;  
+  asection **  prev = &abfd->sections;
+  asection * sect = abfd->sections;
+  
+  if (abfd->output_has_begun) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+
+  while (sect) {
+    if (!strcmp(sect->name, name)) return sect;
+    prev = &sect->next;
+    sect = sect->next;
+  }
+
+  newsect = (asection *) zalloc (sizeof (asection));
+  if (newsect == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  newsect->name = name;
+  newsect->index = abfd->section_count++;
+  newsect->flags = SEC_NO_FLAGS;
+
+#if ignore     /* the compiler doesn't know that zalloc clears the storage */
+  newsect->userdata = 0;
+  newsect->next = (asection *)NULL;
+  newsect->relocation = (arelent *)NULL;
+  newsect->reloc_count = 0;
+  newsect->line_filepos =0;
+#endif
+  if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true) {
+    free (newsect);
+    return NULL;
+  }
+
+  *prev = newsect;
+  return newsect;
+}
+
+/* Call operation on each section.  Operation gets three args: the bfd,
+   the section, and a void * pointer (whatever the user supplied). */
+
+/* This is attractive except that without lexical closures its use is hard
+   to make reentrant. */
+/*VARARGS2*/
+void
+bfd_map_over_sections (abfd, operation, user_storage)
+     bfd *abfd;
+     void (*operation)();
+     void *user_storage;
+{
+  asection *sect;
+  int i = 0;
+  
+  for (sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    (*operation) (abfd, sect, user_storage);
+
+  if (i != abfd->section_count)                /* Debugging */
+    abort();
+}
+
+boolean
+bfd_set_section_flags (abfd, section, flags)
+     bfd *abfd;
+     sec_ptr section;
+     flagword flags;
+{
+  if ((flags & bfd_applicable_section_flags (abfd)) != flags) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+   section->flags = flags;
+return true;
+}
+
+
+boolean
+bfd_set_section_size (abfd, ptr, val)
+     bfd *abfd;
+     sec_ptr ptr;
+     unsigned long val;
+{
+  /* Once you've started writing to any section you cannot create or change
+     the size of any others. */
+
+  if (abfd->output_has_begun) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  ptr->size = val;
+  
+  return true;
+}
+
+boolean
+bfd_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+void *location;
+     file_ptr offset;
+     int count;
+{
+       if (!(bfd_get_section_flags(abfd, section) &
+             SEC_HAS_CONTENTS)) {
+               bfd_error = no_contents;
+               return(false);
+       } /* if section has no contents */
+
+  if (BFD_SEND (abfd, _bfd_set_section_contents,
+           (abfd, section, location, offset, count))) {
+    abfd->output_has_begun = true;
+    return true;
+  }
+
+  return false;
+}
+
+boolean
+bfd_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     void *location;
+     file_ptr offset;
+     int count;
+{
+  if (section->flags & SEC_CONSTRUCTOR) {
+    memset(location, 0, count);
+    return true;
+  }
+  else {
+    return  (BFD_SEND (abfd, _bfd_get_section_contents,
+                      (abfd, section, location, offset, count)));
+  }
+}
+
+\f
+/** Some core file info commands */
+
+/* Returns a read-only string explaining what program was running when
+   it failed. */
+
+char *
+bfd_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  if (abfd->format != bfd_core) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+  return BFD_SEND (abfd, _core_file_failing_command, (abfd));
+}
+
+int
+bfd_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  if (abfd->format != bfd_core) {
+    bfd_error = invalid_operation;
+    return NULL;
+  }
+  return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
+}
+
+boolean
+core_file_matches_executable_p (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if ((core_bfd->format != bfd_core) || (exec_bfd->format != bfd_object)) {
+    bfd_error = wrong_format;
+    return false;
+  }
+
+  return BFD_SEND (core_bfd, _core_file_matches_executable_p, (core_bfd, exec_bfd));
+}
+\f
+/** Symbols */
+
+boolean
+bfd_set_symtab (abfd, location, symcount)
+     bfd *abfd;
+     asymbol **location;
+     unsigned int symcount;
+{
+  if ((abfd->format != bfd_object) || (bfd_read_p (abfd))) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  bfd_get_outsymbols (abfd) = location;
+  bfd_get_symcount (abfd) = symcount;
+  return true;
+}
+
+/* returns the number of octets of storage required */
+unsigned int
+get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  if (abfd->format != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+
+  return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
+}
+
+unsigned int
+bfd_canonicalize_reloc (abfd, asect, location, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     arelent **location;
+     asymbol **symbols;
+{
+  if (abfd->format != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+
+  return BFD_SEND (abfd, _bfd_canonicalize_reloc, (abfd, asect, location, symbols));
+}
+
+void
+bfd_print_symbol_vandf(file, symbol)
+void *file;
+asymbol *symbol;
+{
+  flagword type = symbol->flags;
+  if (symbol->section != (asection *)NULL)
+    {
+      fprintf(file,"%08lx ", symbol->value+symbol->section->vma);
+    }
+  else 
+    {
+      fprintf(file,"%08lx ", symbol->value);
+    }
+  fprintf(file,"%c%c%c%c%c%c%c",
+         (type & BSF_LOCAL)  ? 'l':' ',
+         (type & BSF_GLOBAL) ? 'g' : ' ',
+         (type & BSF_IMPORT) ? 'i' : ' ',
+         (type & BSF_EXPORT) ? 'e' : ' ',
+         (type & BSF_UNDEFINED) ? 'u' : ' ',
+         (type & BSF_FORT_COMM) ? 'c' : ' ',
+         (type & BSF_DEBUGGING) ? 'd' :' ');
+
+}
+
+
+boolean
+bfd_set_file_flags (abfd, flags)
+     bfd *abfd;
+     flagword flags;
+{
+  if (abfd->format != bfd_object) {
+    bfd_error = wrong_format;
+    return false;
+  }
+
+  if (bfd_read_p (abfd)) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  if ((flags & bfd_applicable_file_flags (abfd)) != flags) {
+    bfd_error = invalid_operation;
+    return false;
+  }
+
+  bfd_get_file_flags (abfd) = flags;
+return true;
+}
+
+
+void
+bfd_set_reloc (ignore_abfd, asect, location, count)
+     bfd *ignore_abfd;
+     sec_ptr asect;
+     arelent **location;
+     unsigned int count;
+{
+  asect->orelocation  = location;
+  asect->reloc_count = count;
+}
+/*
+If an output_bfd is supplied to this function the generated image
+will be relocatable, the relocations are copied to the output file
+after they have been changed to reflect the new state of the world.
+There are two ways of reflecting the results of partial linkage in an
+output file; by modifying the output data in place, and by modifying
+the relocation record. Some native formats (eg basic a.out and basic
+coff) have no way of specifying an addend in the relocation type, so
+the addend has to go in the output data.  This is no big deal since in
+these formats the output data slot will always be big enough for the
+addend. Complex reloc types with addends were invented to solve just
+this problem.
+*/
+
+bfd_reloc_status_enum_type
+bfd_perform_relocation(abfd,
+                      reloc_entry,
+                      data,
+                      input_section,
+                      output_bfd)
+bfd *abfd;
+arelent *reloc_entry;
+void  *data;
+asection *input_section;
+bfd *output_bfd;
+{
+  bfd_vma relocation;
+  bfd_reloc_status_enum_type flag = bfd_reloc_ok;
+  bfd_vma relocation_before;
+  bfd_vma mask;
+  bfd_vma target_mask;
+  bfd_vma addr = reloc_entry->address ;
+  bfd_vma output_base = 0;
+  struct rint_struct *howto = reloc_entry->howto;
+  asection *reloc_target_output_section;
+  asection *reloc_target_input_section;
+  asymbol *symbol;
+
+  if (reloc_entry->sym_ptr_ptr) {
+    symbol = *( reloc_entry->sym_ptr_ptr);
+    if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) {
+      flag = bfd_reloc_undefined;
+    }
+  }
+  else {
+    symbol = (asymbol*)NULL;
+  }
+
+  if (howto->special_function) {
+    bfd_reloc_status_enum_type cont;
+    cont = howto->special_function(abfd,
+                                  reloc_entry,
+                                  symbol,
+                                  data,
+                                  input_section);
+    if (cont != bfd_reloc_continue) return cont;
+  }
+
+  /* 
+     Work out which section the relocation is targetted at and the
+     initial relocation command value.
+     */
+
+
+  if (symbol != (asymbol *)NULL){
+    if (symbol->flags & BSF_FORT_COMM) {
+      relocation = 0;
+    }
+    else {
+      relocation = symbol->value;
+    }
+    if (symbol->section != (asection *)NULL)
+      {
+       reloc_target_input_section = symbol->section;
+      }
+    else {
+      reloc_target_input_section = (asection *)NULL;
+    }
+  }
+  else if (reloc_entry->section != (asection *)NULL)
+    {
+      relocation = 0;
+      reloc_target_input_section = reloc_entry->section;
+    }
+  else {
+    relocation = 0;
+    reloc_target_input_section = (asection *)NULL;
+  }
+
+
+  if (reloc_target_input_section != (asection *)NULL) {
+
+    reloc_target_output_section =
+      reloc_target_input_section->output_section;
+
+    if (output_bfd && howto->partial_inplace==false) {
+      output_base = 0;
+    }
+    else {
+      output_base = reloc_target_output_section->vma;
+
+    }
+
+    relocation += output_base +   reloc_target_input_section->output_offset;
+  }
+
+  relocation += reloc_entry->addend ;
+
+
+  if(reloc_entry->address > (bfd_vma)(input_section->size)) 
+    {
+      return bfd_reloc_outofrange;
+    }
+         
+
+  if (howto->pc_relative == true)
+    {
+      /*
+        Anything which started out as pc relative should end up that
+        way too 
+        */
+
+      relocation -= 
+       output_base +   input_section->output_offset;
+
+    }
+
+  if (output_bfd!= (bfd *)NULL &&   howto->partial_inplace == false)  {
+    /*
+       This is a partial relocation, and we want to apply the relocation
+       to the reloc entry rather than the raw data. Modify the reloc
+       inplace to reflect what we now know.
+       */
+    reloc_entry->addend = relocation  ;
+    reloc_entry->section = reloc_target_input_section;
+    if (reloc_target_input_section != (asection *)NULL) {
+      /* If we know the output section we can forget the symbol */
+      reloc_entry->sym_ptr_ptr = (asymbol**)NULL;
+    }
+    reloc_entry->address += 
+      input_section->output_offset;
+  }
+  else {
+    reloc_entry->addend = 0;
+
+
+    /* 
+       Either we are relocating all the way, or we don't want to apply
+       the relocation to the reloc entry (probably because there isn't
+       any room in the output format to describe addends to relocs)
+       */
+    relocation >>= howto->rightshift;
+    if (howto->bitsize == 32) {
+      mask = ~0;
+    }
+    else {
+      mask = (1L << howto->bitsize) - 1 ;
+      mask |= mask - 1;                /* FIXME, what is this?  */
+    }
+
+    relocation &= mask;
+
+    /* Shift everything up to where it's going to be used */
+   
+    relocation <<= howto->bitpos;
+    mask <<= howto->bitpos;
+    target_mask = ~mask;
+
+    /* Wait for the day when all have the mask in them */
+
+    BFD_ASSERT(howto->mask == mask);
+
+
+
+    relocation_before = relocation;
+
+
+    switch (howto->size)
+      {
+      case 0:
+       {
+         char x = bfd_getchar(abfd, (char *)data + addr);
+         relocation +=  x & mask;
+         bfd_putchar(abfd,
+                     ( x & target_mask) | ( relocation & mask),
+                     (unsigned char *) data + addr);
+       }
+       break;
+
+      case 1:
+       { 
+         short x = bfd_getshort(abfd, (bfd_byte *)data + addr);
+         relocation += x & mask;
+         bfd_putshort(abfd, ( x & target_mask) | (relocation & mask),
+                      (unsigned char *)data + addr);
+       }
+       break;
+      case 2:
+       {
+         long  x = bfd_getlong(abfd, (bfd_byte *) data + addr);
+         relocation +=  x & mask;
+         bfd_putlong(abfd, ( x & target_mask) | (relocation & mask),
+                     (bfd_byte *)data + addr);
+       }          
+       break;
+      case 3:
+       /* Do nothing */
+       break;
+      default:
+       return bfd_reloc_other;
+      }
+
+    /* See if important parts of the relocation were chopped to make
+       it fit into the relocation field. (ie are there any significant
+       bits left over after the masking ? */
+    if ((relocation_before & target_mask) != 0 &&
+       howto->complain_on_overflow == true) 
+      {
+       /* Its ok if the bit which fell off is */
+       return bfd_reloc_overflow;
+      }
+  }
+
+  return flag;
+}
+
+void
+bfd_assert(file, line)
+char *file;
+int line;
+{
+  printf("bfd assertion fail %s:%d\n",file,line);
+}
+
+
+boolean
+bfd_set_start_address(abfd, vma)
+bfd *abfd;
+bfd_vma vma;
+{
+  abfd->start_address = vma;
+  return true;
+}
+
+
+bfd_vma bfd_log2(x)
+bfd_vma x;
+{
+  bfd_vma  result = 0;
+  while ( (bfd_vma)(1<< result) < x)
+    result++;
+  return result;
+}
+
+/* bfd_get_mtime:  Return cached file modification time (e.g. as read
+   from archive header for archive members, or from file system if we have
+   been called before); else determine modify time, cache it, and
+   return it.  */
+
+long
+bfd_get_mtime (abfd)
+     bfd *abfd;
+{
+  FILE *fp;
+  struct stat buf;
+
+  if (abfd->mtime_set)
+    return abfd->mtime;
+
+  fp = bfd_cache_lookup (abfd);
+  if (0 != fstat (fileno (fp), &buf))
+    return 0;
+
+  abfd->mtime_set = true;
+  abfd->mtime = buf.st_mtime;
+  return abfd->mtime;
+}
diff --git a/bfd/cache.c b/bfd/cache.c
new file mode 100644 (file)
index 0000000..39ffc7a
--- /dev/null
@@ -0,0 +1,200 @@
+/*** cache.c -- Allows you to have more bfds open than your system has fds. */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+/* These declarations should not be needed; libbfd.h's inclusion should
+   have handled it.
+   int fclose();
+   int fseek();
+*/
+
+
+/* The maximum number of FDs opened by bfd */
+#define BFD_CACHE_MAX_OPEN 10
+
+/* when this exceeds BFD_CACHE_MAX_OPEN, we get to work */
+static int open_files;
+
+static bfd *cache_sentinel;    /* Chain of bfds with active fds we've
+                                  opened */
+static void
+bfd_cache_delete();
+
+bfd *bfd_last_cache;
+\f
+
+static void
+close_one()
+{
+    bfd *kill = cache_sentinel;
+    if (kill == 0)             /* Nothing in the cache */
+       return ;
+
+    /* We can only close files that want to play this game.  */
+    while (!kill->cacheable) {
+       kill = kill->lru_prev;
+       if (kill == cache_sentinel) /* Nobody wants to play */
+          return ;
+    }
+
+    kill->where = ftell((FILE *)(kill->iostream));
+    bfd_cache_delete(kill);
+
+}
+/* Cuts the bfd abfd out of the chain in the cache */
+static void 
+snip (abfd)
+     bfd *abfd;
+{
+  abfd->lru_prev->lru_next = abfd->lru_next;
+  abfd->lru_next->lru_prev = abfd->lru_prev; 
+  if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
+}
+
+static void
+bfd_cache_delete (abfd)
+     bfd *abfd;
+{
+  fclose ((FILE *)(abfd->iostream));
+  snip (abfd);
+  abfd->iostream = NULL;
+  open_files--;
+}
+  
+static bfd *
+insert(x,y)
+bfd *x;
+bfd *y;
+{
+  if (y) {
+    x->lru_next = y;
+    x->lru_prev = y->lru_prev;
+    y->lru_prev->lru_next = x;
+    y->lru_prev = x;
+
+  }
+  else {
+    x->lru_prev = x;
+    x->lru_next = x;
+  }
+  return x;
+}
+\f
+
+/* Initialize a BFD by putting it on the cache LRU.  */
+void
+bfd_cache_init(abfd)
+bfd *abfd;
+{
+  cache_sentinel = insert(abfd, cache_sentinel);
+}
+
+void
+bfd_cache_close(abfd)
+bfd *abfd;
+{
+  /* If this file is open then remove from the chain */
+  if (abfd->iostream) 
+    {
+      bfd_cache_delete(abfd);
+    }
+}
+\f
+/* Call the OS to open a file for this BFD.  Returns the FILE *
+   (possibly null) that results from this operation.  Sets up the
+   BFD so that future accesses know the file is open.  */
+
+FILE *
+bfd_open_file (abfd)
+     bfd *abfd;
+{
+    abfd->cacheable = true;    /* Allow it to be closed later. */
+    if(open_files >= BFD_CACHE_MAX_OPEN) {
+       close_one();
+    }
+    switch (abfd->direction) {
+ case read_direction:
+ case no_direction:
+       abfd->iostream = (char *) fopen(abfd->filename, "r");
+       break;
+ case both_direction:
+ case write_direction:
+       if (abfd->opened_once == true) {
+           abfd->iostream = (char *) fopen(abfd->filename, "r+");
+           if (!abfd->iostream) {
+               abfd->iostream = (char *) fopen(abfd->filename, "w+");
+           }
+       } else {
+           /*open for creat */
+           abfd->iostream = (char *) fopen(abfd->filename, "w");
+           abfd->opened_once = true;
+       }
+       break;
+    }
+    if (abfd->iostream) {
+       open_files++;
+       bfd_cache_init (abfd);
+    }
+
+    return (FILE *)(abfd->iostream);
+}
+
+/* Find a file descriptor for this BFD.  If necessary, open it.
+   If there are already more than BFD_CACHE_MAX_OPEN files open, try to close
+   one first, to avoid running out of file descriptors.  */
+
+FILE *
+bfd_cache_lookup_worker (abfd)
+     bfd *abfd;
+{
+  if (abfd->my_archive) 
+    {
+      abfd = abfd->my_archive;
+    }
+  /* Is this file already open .. if so then quick exit */
+  if (abfd->iostream) 
+    {
+      if (abfd != cache_sentinel) {
+       /* Place onto head of lru chain */
+       snip (abfd);
+       cache_sentinel = insert(abfd, cache_sentinel);
+      }
+    }
+  /* This is a bfd without a stream -
+     so it must have been closed or never opened.
+     find an empty cache entry and use it.  */
+  else 
+    {
+
+      if (open_files >= BFD_CACHE_MAX_OPEN) 
+       {
+       close_one();
+    }
+
+      BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
+      fseek((FILE *)(abfd->iostream), abfd->where, false);
+    }
+bfd_last_cache = abfd;
+  return (FILE *)(abfd->iostream);
+}
diff --git a/bfd/coff-code.h b/bfd/coff-code.h
new file mode 100755 (executable)
index 0000000..8ec6ec2
--- /dev/null
@@ -0,0 +1,2561 @@
+/*
+   Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option) any later version.
+
+BFD 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
+   BFD; see the file COPYING.  If not, write to the Free Software Foundation,
+   675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* $Id$ */
+/*
+   FIXME-SOON.  There is a major, potentially invalid assumption in this
+   code. Namely, that incoming symbol tables will be broken up and glued back
+   together but only on C_FILE boundaries.  That is, if you break the symbol
+   table on some other boundary, or if you remove a single symbol in the
+   middle, it is possible to end up with garbage where you expect your
+   debugging info to be.  This only affects debugging info.  Specifically, it
+   affects all of the foondx's in the aux entries.  C_FILE entries ARE glued
+   back together properly.  Line numbers and relocations are tracked with
+   pointers so their ndx's aren't affected.
+
+On the other hand, if the symbol that a line number or reloc points to goes
+   away, or isn't included in an output bfd, then you'll end up with mush
+   anyway.
+
+I'm not sure at this point, (Sun Mar 3 00:56:11 PST 1991), but I suspect the
+   bfd library will need to provide at least the option of a higher and/or
+   lower abstraction for (at least debugging) symbols.  The current
+   abstraction is sufficient for linking, nm, and very nearly for stripping,
+   but is nowhere near what would be needed for gas to create coff symbols or
+   for gdb to read them.
+
+xoxorich.
+*/
+
+#include "archures.h"          /* Machine architectures and types */
+
+/* SUPPRESS 558 */
+/* SUPPRESS 590 */
+/* SUPPRESS 529 */
+/* SUPPRESS 530 */
+
+#define ALIGN(this, boundary) \
+  ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+
+#define sp(x) bfd_h_put_x(abfd, x, &x)
+
+
+
+/*
+   Align an address by rounding it up to a power of two.  It leaves the
+   address unchanged if align == 0 (2^0 = alignment of 1 byte)
+*/
+#define        i960_align(addr, align) \
+       ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+
+/* All the swapping routines */
+
+static void
+swap_reloc(abfd, reloc)
+    bfd            *abfd;
+    RELOC          *reloc;
+{
+    sp(reloc->r_vaddr);
+    sp(reloc->r_symndx);
+    sp(reloc->r_type);
+}
+
+
+static void
+swap_filehdr(abfd, filehdr)
+    bfd            *abfd;
+    FILHDR         *filehdr;
+{
+    sp(filehdr->f_magic);
+    sp(filehdr->f_nscns);
+    sp(filehdr->f_timdat);
+    sp(filehdr->f_symptr);
+    sp(filehdr->f_nsyms);
+    sp(filehdr->f_opthdr);
+    sp(filehdr->f_flags);
+
+
+}
+
+static void
+swap_aouthdr(abfd, aouthdr)
+    bfd            *abfd;
+    AOUTHDR        *aouthdr;
+{
+
+    sp(aouthdr->magic);
+    sp(aouthdr->vstamp);
+    sp(aouthdr->tsize);
+    sp(aouthdr->dsize);
+    sp(aouthdr->bsize);
+    sp(aouthdr->entry);
+    sp(aouthdr->text_start);
+    sp(aouthdr->data_start);
+#ifdef I960
+    sp(aouthdr->tagentries);
+#endif
+}
+
+static void
+swap_scnhdr(abfd, scnhdr)
+    bfd            *abfd;
+    SCNHDR         *scnhdr;
+{
+    sp(scnhdr->s_vaddr);
+    sp(scnhdr->s_paddr);
+    sp(scnhdr->s_size);
+    sp(scnhdr->s_scnptr);
+    sp(scnhdr->s_relptr);
+    sp(scnhdr->s_lnnoptr);
+    sp(scnhdr->s_nreloc);
+    sp(scnhdr->s_nlnno);
+    sp(scnhdr->s_flags);
+#ifdef I960
+    sp(scnhdr->s_align);
+#endif
+}
+
+static void
+swap_name(abfd, ptr)
+    bfd            *abfd;
+    long           *ptr;
+{
+    if (ptr[0] == 0) {
+       /* There is an index which needs to be swapped */
+       bfd_h_put_x(abfd, ptr[1], (ptr + 1));
+    }
+    else {
+       /* This is a string .. leave it alone */
+    }
+}
+
+void
+bfd_coff_swap_sym(abfd, se)
+    bfd            *abfd;
+    SYMENT         *se;
+{
+    swap_name(abfd, se->n_name);
+    bfd_h_put_x(abfd, se->n_value, &se->n_value);
+    bfd_h_put_x(abfd, se->n_scnum, &se->n_scnum);
+    bfd_h_put_x(abfd, se->n_type, &se->n_type);
+    bfd_h_put_x(abfd, se->n_sclass, &se->n_sclass);
+    bfd_h_put_x(abfd, se->n_numaux, &se->n_numaux);
+}
+
+void
+bfd_coff_swap_aux(abfd, au, type, class)
+    bfd            *abfd;
+    AUXENT         *au;
+    int             type;
+    int             class;
+{
+    switch (class) {
+    case C_FILE:
+       swap_name(abfd, &au->x_file.x_n);
+       break;
+    case C_STAT:
+#ifdef C_LEAFSTAT
+    case C_LEAFSTAT:
+#endif
+    case C_HIDDEN:
+       if (type == T_NULL) {
+           sp(au->x_scn.x_scnlen);
+           sp(au->x_scn.x_nreloc);
+           sp(au->x_scn.x_nlinno);
+           break;
+       }
+    default:
+       sp(au->x_sym.x_tagndx);
+       sp(au->x_sym.x_tvndx);
+
+       if (ISARY(type) || class == C_BLOCK) {
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[0]);
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[1]);
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[2]);
+           sp(au->x_sym.x_fcnary.x_ary.x_dimen[3]);
+       }
+       else {
+           sp(au->x_sym.x_fcnary.x_fcn.x_lnnoptr);
+           sp(au->x_sym.x_fcnary.x_fcn.x_endndx);
+       }
+       if (ISFCN(type)) {
+           sp(au->x_sym.x_misc.x_fsize);
+       }
+       else {
+           sp(au->x_sym.x_misc.x_lnsz.x_lnno);
+           sp(au->x_sym.x_misc.x_lnsz.x_size);
+       }
+    }
+}
+
+void
+bfd_coff_swap_lineno(abfd, lineno)
+    bfd            *abfd;
+    LINENO         *lineno;
+{
+    sp(lineno->l_addr.l_symndx);
+    sp(lineno->l_lnno);
+}
+
+
+/* void warning(); */
+extern asection abs_section;
+
+
+
+static int
+get_index(symbol)
+    asymbol        *symbol;
+{
+    return (int) symbol->value;
+}
+
+static void
+set_index(symbol, idx)
+    asymbol        *symbol;
+    unsigned int    idx;
+{
+    symbol->value = idx;
+}
+
+
+/*
+   initialize a section structure with information peculiar to this
+   particular implementation of coff
+*/
+
+static          boolean
+coff_new_section_hook(abfd_ignore, section_ignore)
+    bfd            *abfd_ignore;
+    asection       *section_ignore;
+{
+    return true;
+}
+/* actually it makes itself and its children from the file headers */
+static          boolean
+make_a_section_from_file(abfd, hdr)
+    bfd            *abfd;
+    struct scnhdr  *hdr;
+
+{
+    asection       *return_section;
+    {
+       char           *name = malloc(9);
+       if (name == NULL) {
+           bfd_error = no_memory;
+           return (BFD_FAILURE);
+       }                       /* on error */
+       strncpy(name, (char *) &hdr->s_name[0], 8);
+
+       return_section = bfd_make_section(abfd, name);
+       (return_section->name)[8] = 0;
+    }
+
+    /* s_paddr is presumed to be = to s_vaddr */
+#define assign(to, from) return_section->to = hdr->from
+    assign(vma, s_vaddr);
+    /* assign (vma, s_vaddr); */
+    assign(size, s_size);
+    assign(filepos, s_scnptr);
+    assign(rel_filepos, s_relptr);
+    assign(reloc_count, s_nreloc);
+#ifdef I960
+    {
+
+       assign(alignment_power, s_align);
+       {
+           unsigned int    i;
+           for (i = 0; i < 32; i++) {
+               if ((1 << i) >= (int) (return_section->alignment_power)) {
+                   return_section->alignment_power = i;
+                   break;
+               }
+           }
+       }
+    }
+#endif
+    assign(line_filepos, s_lnnoptr);
+    /*
+       return_section->linesize =   hdr->s_nlnno * sizeof (struct lineno);
+    */
+
+#undef assign
+    return_section->lineno_count = hdr->s_nlnno;
+    return_section->userdata = NULL;
+    return_section->next = (asection *) NULL;
+    if ((hdr->s_flags & STYP_TEXT) || (hdr->s_flags & STYP_DATA))
+       return_section->flags = (SEC_LOAD | SEC_ALLOC);
+    else if (hdr->s_flags & STYP_BSS)
+       return_section->flags = SEC_ALLOC;
+
+    if (hdr->s_nreloc != 0)
+       return_section->flags |= SEC_RELOC;
+    if (hdr->s_scnptr != 0)
+       return_section->flags |= SEC_HAS_CONTENTS;
+    return true;
+}
+
+
+static
+bfd_target     *
+coff_real_object_p(abfd, nscns, opthdr)
+    bfd            *abfd;
+    unsigned        nscns,
+                    opthdr;
+{
+    struct icofdata *tdata;
+    char           *file_info; /* buffer for all the headers */
+    size_t          readsize;  /* length of file_info */
+    struct filehdr *filehdr;   /* points into file_info */
+    struct scnhdr  *sections;  /* points into file_info */
+    /*
+       OK, now we know the format, read in the filehdr, soi-disant "optional
+       header", and all the sections.
+    */
+    readsize = sizeof(struct filehdr)
+       + opthdr
+       + (nscns * sizeof(struct scnhdr));
+
+    file_info = malloc(readsize);
+    if (file_info == NULL) {
+       bfd_error = no_memory;
+       return 0;
+    }
+    if (bfd_seek(abfd, 0L, SEEK_SET) < 0)
+       return 0;
+    if (bfd_read((void *) file_info, 1, readsize, abfd) != readsize)
+       return 0;
+    filehdr = (struct filehdr *) file_info;
+    sections = (struct scnhdr *) (file_info + sizeof(struct filehdr) + opthdr);
+
+
+    swap_filehdr(abfd, filehdr);
+
+    /* Now copy data as required; construct all asections etc */
+    tdata = (struct icofdata *) malloc(sizeof(struct icofdata) +
+                                      sizeof(AOUTHDR));
+    if (tdata == NULL) {
+       bfd_error = no_memory;
+       return 0;
+    }
+    tdata->symbol_index_slew = 0;
+    tdata->relocbase =0;
+    tdata->raw_syment_count = 0;
+    tdata->raw_linenos = 0;
+    tdata->raw_syments = 0;
+    tdata->sym_filepos =0;
+
+    if (nscns != 0) {
+       unsigned int    i;
+       for (i = 0; i < nscns; i++) {
+           swap_scnhdr(abfd, sections + i);
+           make_a_section_from_file(abfd, sections + i);
+       }
+    }
+    /* Determine the machine architecture and type.  */
+    abfd->obj_machine = 0;
+    switch (filehdr->f_magic) {
+#ifdef MC68MAGIC
+    case MC68MAGIC:
+    case MC68DMAGIC:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68020;
+       break;
+#endif
+#ifdef I960ROMAGIC
+    case I960ROMAGIC:
+    case I960RWMAGIC:
+       abfd->obj_arch = bfd_arch_i960;
+       switch (F_I960TYPE & filehdr->f_flags) {
+       case F_I960CORE:
+           abfd->obj_machine = bfd_mach_i960_core;
+           break;
+       case F_I960KB:
+           abfd->obj_machine = bfd_mach_i960_kb_sb;
+           break;
+       case F_I960MC:
+           abfd->obj_machine = bfd_mach_i960_mc;
+           break;
+       case F_I960XA:
+           abfd->obj_machine = bfd_mach_i960_xa;
+           break;
+       case F_I960CA:
+           abfd->obj_machine = bfd_mach_i960_ca;
+           break;
+       case F_I960KA:
+           abfd->obj_machine = bfd_mach_i960_ka_sa;
+           break;
+           /*
+              Doomed to fail but sneak out a bit of info in the process.
+           */
+       default:
+           abfd->obj_machine = filehdr->f_flags & F_I960TYPE;
+       }
+       break;
+#endif
+
+    default:                   /* Unreadable input file type */
+       abfd->obj_arch = bfd_arch_obscure;
+       break;
+    }
+
+    if (!(filehdr->f_flags & F_RELFLG))
+       abfd->flags |= HAS_RELOC;
+    if ((filehdr->f_flags & F_EXEC))
+       abfd->flags |= EXEC_P;
+    if (!(filehdr->f_flags & F_LNNO))
+       abfd->flags |= HAS_LINENO;
+    if (!(filehdr->f_flags & F_LSYMS))
+       abfd->flags |= HAS_LOCALS;
+
+    abfd->tdata = (void *) tdata;
+    bfd_get_symcount(abfd) = filehdr->f_nsyms;
+    if (filehdr->f_nsyms)
+       abfd->flags |= HAS_SYMS;
+
+    tdata->sym_filepos = filehdr->f_symptr;
+    tdata->hdr = (struct aouthdr *) (file_info + sizeof(struct filehdr));
+
+    swap_aouthdr(abfd, tdata->hdr);
+
+    tdata->symbols = (coff_symbol_type *) NULL;
+    bfd_get_start_address(abfd) = opthdr ? exec_hdr(abfd)->entry : 0;
+
+    return abfd->xvec;
+}
+static coff_symbol_type *
+coff_symbol_from(abfd, symbol)
+    bfd            *abfd;
+    asymbol        *symbol;
+{
+    return symbol->the_bfd->xvec->flavour == bfd_target_coff_flavour_enum
+       ?
+       (coff_symbol_type *) symbol
+       :
+       (coff_symbol_type *) NULL;
+
+}
+
+
+
+static bfd_target *
+coff_object_p(abfd)
+    bfd            *abfd;
+{
+    unsigned short  magic,
+                    nscns,
+                    opthdr;
+    bfd_error = system_call_error;
+
+    /* figure out how much to read */
+    if (bfd_read((void *) &magic, 1, sizeof(magic), abfd) != sizeof(magic))
+       return 0;
+
+    magic = bfd_h_getshort(abfd, (bfd_byte *) (&magic));
+
+    if (BADMAG(*((struct filehdr *) & magic))) {
+       bfd_error = wrong_format;
+       return 0;
+    }
+    if (bfd_read((void *) &nscns, 1, sizeof(nscns), abfd) != sizeof(nscns))
+       return 0;
+    nscns = bfd_h_getshort(abfd, (unsigned char *) &nscns);
+    if (bfd_seek(abfd, (file_ptr) & (((struct filehdr *) NULL)->f_opthdr), SEEK_SET)
+       < 0)
+       return (bfd_target *) NULL;
+    if (bfd_read((void *) &opthdr, 1, sizeof(opthdr), abfd) != sizeof(opthdr))
+       return (bfd_target *) NULL;
+    opthdr = bfd_h_getshort(abfd, (unsigned char *) &opthdr);
+
+    return coff_real_object_p(abfd, nscns, opthdr);
+}
+
+static          boolean
+coff_mkobject(abfd)
+    bfd            *abfd;
+{
+    char           *rawptr;
+
+
+    bfd_error = system_call_error;
+
+    /* Use an intermediate variable for clarity */
+    rawptr = malloc(sizeof(struct icofdata) + sizeof(AOUTHDR));
+    if (rawptr == NULL) {
+       bfd_error = no_memory;
+       return false;
+    }
+    abfd->tdata = (void *) ((struct icofdata *) rawptr);
+    exec_hdr(abfd) = (AOUTHDR *) (rawptr + sizeof(struct icofdata));
+    obj_relocbase(abfd) =0;
+    return true;
+}
+
+
+
+static void
+coff_count_linenumbers(abfd)
+    bfd            *abfd;
+{
+    unsigned int    limit = bfd_get_symcount(abfd);
+    unsigned int    i;
+    asymbol       **p;
+    {
+       asection       *s = abfd->sections->output_section;
+       while (s) {
+           BFD_ASSERT(s->lineno_count == 0);
+           s = s->next;
+       }
+    }
+
+
+    for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) {
+       asymbol        *q_maybe = *p;
+       if (q_maybe->the_bfd->xvec->flavour == bfd_target_coff_flavour_enum) {
+           coff_symbol_type *q = coffsymbol(q_maybe);
+           if (q->lineno) {
+               /*
+                  This symbol has a linenumber, increment the owning
+                  section's linenumber count
+               */
+               alent          *l = q->lineno;
+               q->symbol.section->output_section->lineno_count++;
+               l++;
+               while (l->line_number) {
+                   q->symbol.section->output_section->lineno_count++;
+                   l++;
+               }
+           }
+       }
+    }
+}
+
+/* 
+  This function returns true if the supplied SYMENT has an auxent with
+  and endndx field which should be relocated as the symbol moves
+  within the file.
+*/
+static 
+boolean
+uses_x_sym_x_fcnary_x_fcn_x_endndx_p(native)
+SYMENT *native;
+{
+    if (ISFCN(native->n_type))
+       return true;
+    if (native->n_sclass == C_BLOCK)
+       return true;
+    if (native->n_sclass == C_STRTAG) 
+       return true;
+    if (native->n_sclass == C_ENTAG)
+       return true;
+    if (native->n_sclass == C_UNTAG)
+       return true;
+    if (native->n_sclass == C_MOS)
+       return true;
+    if(native->n_sclass == C_EOS)
+       return true;
+    if(native->n_sclass == C_MOE) 
+       return true;
+    return false;
+
+}
+/*
+ This function returns true if the supplied SYMENT has an AUXENT with
+ a tagndx field which should be relocated.
+
+ The coff book says that all auxents have this and should be moved,
+ but all the actual implementations I've looked at do this ..
+ (sac@cygnus.com)
+
+*/
+static boolean
+uses_x_sym_x_tagndx_p(native)
+SYMENT *native;
+{
+    if (BTYPE(native->n_type) == T_STRUCT) return true;
+    if (BTYPE(native->n_type) == T_UNION) return true;
+    if (BTYPE(native->n_type) == T_ENUM)return true;
+    return false;
+}
+
+
+/*
+  Return  the canonical symbol we work out how far it has moved since it
+  started life. This is done by finding the base of the raw syments as
+  read in when a file was slurped, which discovers the original offset
+  into the file. Then we return the value which we've saved in the
+  n_offset field of that name - and voila.
+*/
+static 
+unsigned int 
+new_idx(symbol, original_offset)
+coff_symbol_type *symbol;
+unsigned int original_offset;
+{
+    struct icofdata *coff = obj_icof(symbol->symbol.the_bfd);
+
+    /* Point to the native we used to point to */
+    SYMENT *native = coff->raw_syments + original_offset;
+
+    /* We keep the native's new index in it's string space */
+    return native->n_offset;
+}
+
+
+/* Function to run through the raw parts of a coff symbol table and
+   loads each SYMENT's n_offset with its output index. If a symbol has
+   been deleted or moved to the end, still mark the offset of the one
+   following it. This makes refs to symbols which have moved point to
+   the symbol which now sits in the spot vacated.
+*/
+
+static 
+void 
+preload_n_offset(abfd)
+bfd *abfd;
+{
+    unsigned int    limit = bfd_get_symcount(abfd);
+    asymbol **p    = abfd->outsymbols;
+    bfd *thebfd  = (bfd *)NULL;
+    unsigned int native_index;
+
+    native_index = 0;
+
+    /* First phase, mark each SYMENT with final position */
+    while (limit --) {
+       coff_symbol_type *q = coff_symbol_from(abfd, *p);
+       if (q != (coff_symbol_type *)NULL && q->native) {
+           q->native->n_offset = native_index;
+           native_index += 1 + q->native->n_numaux;
+       }
+       else {
+           native_index++;
+       }
+       p++;
+    }
+       
+}
+
+
+/*
+   run through the internal symbol table and make all the pointers and things
+   within the table point to the right places
+*/
+
+static void
+coff_mangle_symbols(abfd)
+    bfd            *abfd;
+{
+    asymbol       **p;
+    unsigned int    native_index = 0;
+
+    unsigned int    last_file_index = 0;
+    unsigned int    limit = bfd_get_symcount(abfd);
+    SYMENT         *last_file_symbol = (SYMENT *) NULL;
+
+    /* Remember the bfd from the last symbol */
+    bfd            *last_bfd = (bfd *) NULL;
+    /* Remember the native from the last symbol */
+    SYMENT         *last_native = (SYMENT *) NULL;
+
+
+    preload_n_offset(abfd);
+
+    p = abfd->outsymbols;
+    limit = bfd_get_symcount(abfd);
+    native_index = 0;
+    while (limit--) 
+       {
+           coff_symbol_type *q = coff_symbol_from(abfd, *p);
+           if ((*p)->the_bfd != last_bfd) {
+               last_bfd = (*p)->the_bfd;
+               last_native = 0;
+               last_file_index = native_index;
+           }
+
+           if (!q) {
+               native_index++;
+           }
+           else {
+               SYMENT         *native = q->native;
+               if (native == (SYMENT *) NULL) {
+                   native_index++;
+               }
+               else {
+
+
+                   /* Alter the native representation */
+                   if (q->symbol.flags & BSF_FORT_COMM) {
+                       native->n_scnum = 0;
+                       native->n_value = q->symbol.value;
+                   }
+                   else if (q->symbol.flags & BSF_DEBUGGING) {
+                       /* native->n_scnum = -2; */
+                       native->n_value = q->symbol.value;
+                   }
+                   else if (q->symbol.flags & BSF_UNDEFINED) {
+                       native->n_scnum = 0;
+                       native->n_value = 0;
+                   }
+                   else if (q->symbol.flags & BSF_ABSOLUTE) {
+                       native->n_scnum = -1;
+                       native->n_value = q->symbol.value;
+                   }
+                   else {
+                       native->n_scnum = q->symbol.section->output_section->index + 1;
+                       native->n_value =
+                           q->symbol.value +
+                               q->symbol.section->output_offset +
+                                   q->symbol.section->output_section->vma;
+                   }
+                   if (native->n_numaux != 0) 
+                       {
+                           union auxent   *a = (union auxent *) (native + 1);
+
+                           /* If this symbol forward references another, put
+                              into it the real index of it by looking around
+                              */
+                           if (uses_x_sym_x_fcnary_x_fcn_x_endndx_p(native))
+                               {
+                                   /* If this is a FCN entry without a
+                                      following .bf then we cheat and
+                                      insert the correct value directy.
+                                      */
+                                   if (ISFCN(native->n_type) &&
+                                       (native+2)->n_sclass != C_BLOCK) {
+                                       a->x_sym.x_fcnary.x_fcn.x_endndx =
+                                           native_index+ native->n_numaux + 1;
+                                   }
+                                   else{
+                                       a->x_sym.x_fcnary.x_fcn.x_endndx =
+                                           new_idx(q,a->x_sym.x_fcnary.x_fcn.x_endndx);
+                                   }
+                    
+
+                               }
+                           if (uses_x_sym_x_tagndx_p(native))  {
+                               a->x_sym.x_tagndx =
+                                   new_idx(q,a->x_sym.x_tagndx);
+                           }
+#ifdef I960
+                           else if (native->n_sclass == C_FCN
+                                    || !strcmp((char *) q->symbol.name, ".bf")) {
+                               a->x_sym.x_fcnary.x_fcn.x_endndx = 0;
+                           }
+#endif                         /* I960 */
+
+                       }
+                   switch (native->n_sclass) {
+               case C_MOS:
+               case C_EOS:
+               case C_REGPARM:
+               case C_REG:
+#ifdef C_AUTOARG
+               case C_AUTOARG: /* 960-specific storage class */
+#endif
+                       /*
+                         Fix so that they have an absolute section
+                         */
+                       native->n_scnum = -1;
+                       break;
+
+               case C_FILE:
+                       if (last_file_symbol) {
+                           if (last_file_symbol->n_value != 0) {
+                               abort();
+                           }   /* sanity assertion */
+                           last_file_symbol->n_value = native_index;
+                       }       /* Chain all the .file symbols together */
+                       last_file_symbol = native;
+
+                       break;
+
+               case C_EXT:
+                       if (!ISFCN(native->n_type)
+                           && last_file_symbol != NULL) {
+                           if (last_file_symbol->n_value != 0) {
+                               abort();
+                           }   /* sanity assertion */
+                           last_file_symbol->n_value = native_index;
+                           last_file_symbol = NULL;
+                       }       /* This should be the first global variable. */
+                       break;
+
+               case C_FCN:
+               case C_NULL:
+               case C_AUTO:
+               case C_EXTDEF:
+               case C_LABEL:
+               case C_ULABEL:
+               case C_USTATIC:
+               case C_STRTAG:
+               case C_BLOCK:
+               case C_STAT:
+#ifdef I960
+               case C_LEAFEXT:
+               case C_LEAFSTAT:
+#endif
+                       break;
+               default:
+                       /*
+                         Bogus: This should be returning an error code, not
+                         printing something out!
+                         */
+                       /*
+                         warning("Unrecognised sclass %d", native->n_sclass);
+                         */
+                       break;
+                   }
+                   native_index += 1 + native->n_numaux;
+
+                   /* Remember the last native here */
+                   last_native = native + native->n_numaux;
+               }
+
+           }
+
+           p++;
+       }
+
+}
+
+
+static void
+coff_write_symbols(abfd)
+    bfd            *abfd;
+{
+    unsigned int    i;
+    unsigned int    limit = bfd_get_symcount(abfd);
+    unsigned int    written = 0;
+    SYMENT          dummy;
+    asymbol       **p;
+    unsigned int    string_size = 0;
+
+
+    /* Seek to the right place */
+    bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET);
+
+    /* Output all the symbols we have */
+
+    written = 0;
+    for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) {
+       asymbol        *symbol = *p;
+       coff_symbol_type *c_symbol = coff_symbol_from(abfd, symbol);
+
+       unsigned int    j;
+       SYMENT         *native;
+       if (c_symbol == (coff_symbol_type *) NULL ||
+           c_symbol->native == (SYMENT *) NULL) {
+           /*
+              This symbol has been created by the loader, or come from a non
+              coff format. It  has no native element to inherit, make our
+              own
+           */
+           native = &dummy;
+           native->n_type = T_NULL;
+           if (symbol->flags & BSF_ABSOLUTE) {
+               native->n_scnum = N_ABS;
+               native->n_value = symbol->value;
+           }
+           else if (symbol->flags & (BSF_UNDEFINED | BSF_FORT_COMM)) {
+               native->n_scnum = N_UNDEF;
+               native->n_value = symbol->value;
+           }
+           else if (symbol->flags & BSF_DEBUGGING) {
+               /*
+                  remove name so it doesn't take up any space
+               */
+               symbol->name = "";
+#if 0                          /* FIXME -- Steve hasn't decided what to do
+                                  with these */
+               /*
+                  Don't do anything with debugs from the loader
+               */
+               native->n_scnum = N_DEBUG;
+#endif
+               continue;
+           }
+           else {
+               native->n_scnum = symbol->section->output_section->index + 1;
+               native->n_value = symbol->value +
+                   symbol->section->output_section->vma +
+                   symbol->section->output_offset;
+           }
+
+#ifdef I960
+           /*
+              FIXME-SOON: THIS IS ALREADY WRONG FOR I960. Should echo the
+              flags in the filehdr. (?)
+           */
+           native->n_flags = 0;
+#else                          /* else not I960 */
+#ifdef HASPAD1
+           native->pad1[0] = 0;
+           native->pad1[0] = 0;
+#endif
+#endif                         /* I960 */
+           native->pad2[0] = 0;
+           native->pad2[1] = 0;
+
+           native->n_type = 0;
+           native->n_sclass = C_EXT;
+           native->n_numaux = 0;
+       }
+       else
+           /*
+              Does this symbol have an ascociated line number - if so then
+              make it remember this symbol index. Also tag the auxent of
+              this symbol to point to the right place in the lineno table
+           */
+       {
+           alent          *lineno = c_symbol->lineno;
+           native = c_symbol->native;
+           if (lineno) {
+               unsigned int    count = 0;
+               lineno[count].u.offset = written;
+               if (native->n_numaux) {
+                   union auxent   *a = (union auxent *) (native + 1);
+                   a->x_sym.x_fcnary.x_fcn.x_lnnoptr =
+                       c_symbol->symbol.section->output_section->moving_line_filepos;
+               }
+               /*
+                  And count and relocate all other linenumbers
+               */
+               count++;
+               while (lineno[count].line_number) {
+                   lineno[count].u.offset +=
+                       c_symbol->symbol.section->output_section->vma +
+                       c_symbol->symbol.section->output_offset;
+                   count++;
+               }
+               c_symbol->symbol.section->output_section->moving_line_filepos +=
+                   count * sizeof(struct lineno);
+
+           }
+       }                       /* if symbol new to coff */
+
+       /* Fix the symbol names */
+       {
+           unsigned int    name_length;
+           if (symbol->name == (char *) NULL) {
+               /*
+                  coff symbols always have names, so we'll make one up
+               */
+               symbol->name = "strange";
+           }
+           name_length = strlen(symbol->name);
+           if (name_length <= SYMNMLEN) {
+               /* This name will fit into the symbol neatly */
+               strncpy(native->n_name, symbol->name, SYMNMLEN);
+           }
+           else {
+               native->n_offset = string_size + 4;
+               native->n_zeroes = 0;
+               string_size += name_length + 1;
+           }
+           {
+               unsigned int    numaux = native->n_numaux;
+               int             type = native->n_type;
+               int             class = native->n_sclass;
+               bfd_coff_swap_sym(abfd, native);
+               bfd_write((void *) native, 1, SYMESZ, abfd);
+               for (j = 0; j != native->n_numaux; j++) {
+                   bfd_coff_swap_aux(abfd, native + j + 1, type, class);
+                   bfd_write((void *) (native + j + 1), 1, AUXESZ, abfd);
+
+               }
+               /*
+                  Reuse somewhere in the symbol to keep the index
+               */
+               set_index(symbol, written);
+               written += 1 + numaux;
+           }
+       }
+    }                          /* for each out symbol */
+
+    bfd_get_symcount(abfd) = written;
+    /* Now write out strings */
+
+    if (string_size) {
+       unsigned int    size = string_size + 4;
+       bfd_h_put_x(abfd, size, &size);
+       bfd_write((void *) &size, 1, sizeof(size), abfd);
+       for (p = abfd->outsymbols, i = 0; i < limit; i++, p++) {
+           asymbol        *q = *p;
+           size_t          name_length = strlen(q->name);
+           if (name_length > SYMNMLEN) {
+               bfd_write((void *) (q->name), 1, name_length + 1, abfd);
+           }
+       }
+    }
+    else {
+       /* We would normally not write anything here, but we'll write
+          out 4 so that any stupid coff reader which tries to read
+          the string table even when there isn't one won't croak.
+          */
+
+       uint32e_type size = 4;
+       bfd_h_put_x(abfd, size, &size);
+       bfd_write((void *)&size, 1, sizeof(size), abfd);
+       
+    }
+
+}
+
+static void
+coff_write_relocs(abfd)
+    bfd            *abfd;
+{
+    asection       *s;
+    for (s = abfd->sections; s != (asection *) NULL; s = s->next) {
+       unsigned int    i;
+       arelent       **p = s->orelocation;
+       bfd_seek(abfd, s->rel_filepos, SEEK_SET);
+       for (i = 0; i < s->reloc_count; i++) {
+           struct reloc    n;
+           arelent        *q = p[i];
+           memset(&n, 0, sizeof(n));
+           n.r_vaddr = q->address + s->vma;
+           n.r_symndx = get_index((*(q->sym_ptr_ptr)));
+           n.r_type = q->howto->type;
+           swap_reloc(abfd, &n);
+           bfd_write((void *) &n, 1, RELSZ, abfd);
+       }
+    }
+}
+static void
+coff_write_linenumbers(abfd)
+    bfd            *abfd;
+{
+    asection       *s;
+    for (s = abfd->sections; s != (asection *) NULL; s = s->next) {
+       if (s->lineno_count) {
+           asymbol       **q = abfd->outsymbols;
+           bfd_seek(abfd, s->line_filepos, SEEK_SET);
+           /* Find all the linenumbers in this section */
+           while (*q) {
+               asymbol        *p = *q;
+               alent          *l = BFD_SEND(p->the_bfd, _get_lineno, (p->the_bfd, p));
+               if (l) {
+                   /* Found a linenumber entry, output */
+                   struct lineno   out;
+                   out.l_lnno = 0;
+                   out.l_addr.l_symndx = l->u.offset;
+#ifdef LINENO_PADDING
+                   out.padding[0] = 0;
+                   out.padding[1] = 0;
+#endif
+                   bfd_coff_swap_lineno(abfd, &out);
+                   bfd_write((void *) &out, 1, LINESZ, abfd);
+                   l++;
+                   while (l->line_number) {
+                       out.l_lnno = l->line_number;
+                       out.l_addr.l_symndx = l->u.offset;
+                       bfd_coff_swap_lineno(abfd, &out);
+                       bfd_write((void *) &out, 1, LINESZ, abfd);
+                       l++;
+                   }
+               }
+               q++;
+           }
+       }
+    }
+}
+
+
+static asymbol *
+coff_make_empty_symbol(abfd)
+    bfd            *abfd;
+{
+    coff_symbol_type *new = (coff_symbol_type *) malloc(sizeof(coff_symbol_type));
+    if (new == NULL) {
+       bfd_error = no_memory;
+       return (NULL);
+    }                          /* on error */
+    new->native = 0;
+    new->lineno = (alent *) NULL;
+    new->symbol.the_bfd = abfd;
+    return &new->symbol;
+}
+
+static void
+coff_print_symbol(ignore_abfd, file, symbol, how)
+    bfd            *ignore_abfd;
+    FILE           *file;
+    asymbol        *symbol;
+    bfd_print_symbol_enum_type how;
+{
+    switch (how) {
+    case bfd_print_symbol_name_enum:
+       fprintf(file, "%s", symbol->name);
+       break;
+    case bfd_print_symbol_type_enum:
+       fprintf(file, "coff %lx %lx", (unsigned long) coffsymbol(symbol)->native,
+               (unsigned long) coffsymbol(symbol)->lineno);
+       break;
+    case bfd_print_symbol_all_enum:
+       {
+           char           *section_name = symbol->section == (asection *) NULL ?
+           "*abs" : symbol->section->name;
+           bfd_print_symbol_vandf((void *) file, symbol);
+
+           fprintf(file, " %-5s %s %s %s",
+                   section_name,
+                   coffsymbol(symbol)->native ? "n" : "g",
+                   coffsymbol(symbol)->lineno ? "l" : " ",
+                   symbol->name);
+       }
+
+
+       break;
+    }
+}
+static alent   *
+coff_get_lineno(ignore_abfd, symbol)
+    bfd            *ignore_abfd;
+    asymbol        *symbol;
+{
+    return coffsymbol(symbol)->lineno;
+}
+/*
+   Set flags and magic number of a coff file from architecture and machine
+   type.  Result is true if we can represent the arch&type, false if not.
+*/
+static          boolean
+coff_set_flags(abfd, magicp, flagsp)
+    bfd            *abfd;
+    unsigned       *magicp,
+                   *flagsp;
+{
+
+
+    switch (abfd->obj_arch) {
+
+#ifdef I960ROMAGIC
+
+    case bfd_arch_i960:
+
+       {
+           unsigned        flags;
+           *magicp = I960ROMAGIC;
+           /*
+              ((bfd_get_file_flags(abfd) & WP_TEXT) ? I960ROMAGIC :
+              I960RWMAGIC);   FIXME???
+           */
+           switch (abfd->obj_machine) {
+           case bfd_mach_i960_core:
+               flags = F_I960CORE;
+               break;
+           case bfd_mach_i960_kb_sb:
+               flags = F_I960KB;
+               break;
+           case bfd_mach_i960_mc:
+               flags = F_I960MC;
+               break;
+           case bfd_mach_i960_xa:
+               flags = F_I960XA;
+               break;
+           case bfd_mach_i960_ca:
+               flags = F_I960CA;
+               break;
+           case bfd_mach_i960_ka_sa:
+               flags = F_I960KA;
+               break;
+           default:
+               return false;
+           }
+           *flagsp = flags;
+           return true;
+       }
+       break;
+#endif
+#ifdef MC68MAGIC
+    case bfd_arch_m68k:
+       *magicp = MC68MAGIC;
+       return true;
+#endif
+#if M88DMAGIC
+    case bfd_arch_m88k:
+       *magicp = MC88DMAGIC;
+       return true;
+       break;
+#endif
+
+    default:                   /* Unknown architecture */
+       return false;
+    }
+
+    return false;
+}
+
+
+static          boolean
+coff_set_arch_mach(abfd, arch, machine)
+    bfd            *abfd;
+    enum bfd_architecture arch;
+    unsigned long   machine;
+{
+    unsigned        dummy1,
+                    dummy2;
+    abfd->obj_arch = arch;
+    abfd->obj_machine = machine;
+    if (arch != bfd_arch_unknown &&
+       coff_set_flags(abfd, &dummy1, &dummy2) != true)
+       return false;           /* We can't represent this type */
+    return true;               /* We're easy ... */
+}
+
+
+/* Calculate the file position for each section. */
+
+static void
+coff_compute_section_file_positions(abfd)
+    bfd            *abfd;
+{
+    asection       *current;
+    file_ptr        sofar = FILHSZ;
+    if (bfd_get_start_address(abfd)) {
+       /*
+          A start address may have been added to the original file. In this
+          case it will need an optional header to record it.
+       */
+       abfd->flags |= EXEC_P;
+    }
+    if (abfd->flags & EXEC_P)
+       sofar += AOUTSZ;
+
+
+    sofar += abfd->section_count * SCNHSZ;
+
+    for (current = abfd->sections; current != NULL; current = current->next) {
+       current->filepos = sofar;
+       /* Only add sections which have contents */
+       if (current->flags & SEC_HAS_CONTENTS)
+           sofar += current->size;
+    }
+    obj_relocbase(abfd) = sofar;
+}
+
+/* SUPPRESS 558 */
+/* SUPPRESS 529 */
+static          boolean
+coff_write_object_contents(abfd)
+    bfd            *abfd;
+{
+    struct filehdr  file_header;
+    asection       *current;
+    boolean         hasrelocs = false;
+    boolean         haslinno = false;
+    file_ptr        reloc_base;
+    file_ptr        lineno_base;
+    file_ptr        sym_base;
+    file_ptr        scn_base;
+    file_ptr        data_base;
+    unsigned long   reloc_size = 0;
+    unsigned long   lnno_size = 0;
+    asection       *text_sec = NULL;
+    asection       *data_sec = NULL;
+    asection       *bss_sec = NULL;
+    unsigned        magic,
+    flags;
+    bfd_error = system_call_error;
+
+
+    if(abfd->output_has_begun == false) {
+       coff_compute_section_file_positions(abfd);
+    }
+    scn_base = (file_ptr) (sizeof(struct filehdr)
+                          + ((abfd->flags & EXEC_P) ? sizeof(AOUTHDR) : 0));
+
+    if (bfd_seek(abfd, scn_base, SEEK_SET) != 0)
+       return false;
+    reloc_base = obj_relocbase(abfd);
+
+
+    /*
+      Make a pass through the symbol table to count line number entries and
+      put them into the correct asections
+      */
+    coff_count_linenumbers(abfd);
+    data_base = scn_base;
+    /* Work out the size of the reloc and linno areas */
+
+    for (current = abfd->sections; current != NULL; current = current->next) {
+       reloc_size += current->reloc_count * sizeof(struct reloc);
+       lnno_size += current->lineno_count * sizeof(struct lineno);
+       data_base += sizeof(struct scnhdr);
+    }
+
+
+    lineno_base = reloc_base + reloc_size;
+    sym_base = lineno_base + lnno_size;
+
+    /* Indicate in each section->line_filepos its actual file address */
+    for (current = abfd->sections; current != NULL; current = current->next) {
+       if (current->lineno_count) {
+           current->line_filepos = lineno_base;
+           current->moving_line_filepos = lineno_base;
+           lineno_base += current->lineno_count * sizeof(struct lineno);
+
+       }
+       else {
+           current->line_filepos = 0;
+       }
+       if (current->reloc_count) {
+           current->rel_filepos = reloc_base;
+           reloc_base += current->reloc_count * sizeof(struct reloc);
+       }
+       else {
+           current->rel_filepos = 0;
+       }
+    }
+
+
+
+    bfd_seek(abfd,
+            (file_ptr) ((abfd->flags & EXEC_P) ?
+                        (FILHSZ + AOUTSZ) : FILHSZ),
+            SEEK_SET);
+    {
+#if 0
+       unsigned int    pad = abfd->flags & D_PAGED ? data_base : 0;
+#endif
+       unsigned int    pad = 0;
+       for (current = abfd->sections; current != NULL; current = current->next) {
+           SCNHDR          section;
+           strncpy(&(section.s_name[0]), current->name, 8);
+           section.s_vaddr = current->vma + pad;
+           section.s_paddr = current->vma + pad;
+           section.s_size = current->size - pad;
+           /*
+             If this section has no size or is unloadable then the scnptr
+             will be 0 too
+             */
+           if (current->size - pad == 0 ||
+               (current->flags & SEC_LOAD) == 0) {
+               section.s_scnptr = 0;
+
+           }
+           else {
+               section.s_scnptr = current->filepos;
+           }
+           section.s_relptr = current->rel_filepos;
+           section.s_lnnoptr = current->line_filepos;
+           section.s_nreloc = current->reloc_count;
+           section.s_nlnno = current->lineno_count;
+           if (current->reloc_count != 0)
+               hasrelocs = true;
+           if (current->lineno_count != 0)
+               haslinno = true;
+
+           if (!strcmp(current->name, _TEXT)) {
+               text_sec = current;
+               section.s_flags = STYP_TEXT; /* kind stupid optimisation */
+           }
+           else {
+
+               if (!strcmp(current->name, _DATA)) {
+                   data_sec = current;
+                   section.s_flags = STYP_DATA; /* kind stupid
+                                                   optimisation */
+               }
+               else if (!strcmp(current->name, _BSS)) {
+                   bss_sec = current;
+                   section.s_flags = STYP_BSS; /* kind stupid optimisation */
+               }
+           }
+
+
+#ifdef I960
+           section.s_align = (current->alignment_power
+                              ? 1 << current->alignment_power
+                              : 0);
+
+#endif
+           swap_scnhdr(abfd, &section);
+           bfd_write((void *) (&section), 1, SCNHSZ, abfd);
+           pad = 0;
+       }
+
+    }
+    /* OK, now set up the filehdr... */
+
+    bfd_h_put_x(abfd, abfd->section_count, &file_header.f_nscns);
+    /*
+      We will NOT put a fucking timestamp in the header here. Every time you
+      put it back, I will come in and take it out again. I'm sorry. This
+      field does not belong here.  We fill it with a 0 so it compares the
+      same but is not a reasonable time. -- gnu@cygnus.com
+      */
+    /*
+      Well, I like it, so I'm conditionally compiling it in.
+      steve@cygnus.com
+      */
+#ifdef COFF_TIMESTAMP
+    bfd_h_put_x(abfd, time(0), &file_header.f_timdat);
+#else
+    bfd_h_put_x(abfd, 0, &file_header.f_timdat);
+#endif
+
+    if (bfd_get_symcount(abfd) != 0)
+       bfd_h_put_x(abfd, sym_base, &file_header.f_symptr);
+    else
+       bfd_h_put_x(abfd, 0, &file_header.f_symptr);
+
+    file_header.f_flags = 0;
+
+    if (abfd->flags & EXEC_P)
+       bfd_h_put_x(abfd, sizeof(AOUTHDR), &file_header.f_opthdr);
+    else
+       bfd_h_put_x(abfd, 0, &file_header.f_opthdr);
+
+    if (!hasrelocs)
+       file_header.f_flags |= F_RELFLG;
+    if (!haslinno)
+       file_header.f_flags |= F_LNNO;
+    if (0 == bfd_get_symcount(abfd))
+       file_header.f_flags |= F_LSYMS;
+    if (abfd->flags & EXEC_P)
+       file_header.f_flags |= F_EXEC;
+    if (!abfd->xvec->byteorder_big_p)
+       file_header.f_flags |= F_AR32WR;
+    /*
+      FIXME, should do something about the other byte orders and
+      architectures.
+      */
+
+    /* Set up architecture-dependent stuff */
+
+    magic = 0;
+    flags = 0;
+    coff_set_flags(abfd, &magic, &flags);
+    file_header.f_flags |= flags;
+
+    bfd_h_put_x(abfd, magic, &file_header.f_magic);
+    bfd_h_put_x(abfd, file_header.f_flags, &file_header.f_flags);
+
+    /* ...and the "opt"hdr... */
+#ifdef I960
+    bfd_h_put_x(abfd, (magic == I960ROMAGIC ? NMAGIC : OMAGIC),
+               &(exec_hdr(abfd)->magic));
+#endif
+#if M88
+    exec_hdr(abfd)->magic = PAGEMAGIC3;
+#endif
+
+    /* Now should write relocs, strings, syms */
+    obj_sym_filepos(abfd) = sym_base;
+
+    if (bfd_get_symcount(abfd) != 0) {
+       coff_mangle_symbols(abfd);
+       coff_write_symbols(abfd);
+       coff_write_linenumbers(abfd);
+       coff_write_relocs(abfd);
+    }
+    if (text_sec) {
+       bfd_h_put_x(abfd, text_sec->size, &exec_hdr(abfd)->tsize);
+       bfd_h_put_x(abfd,
+                   text_sec->size ? text_sec->vma : 0,
+                   &exec_hdr(abfd)->text_start);
+    }
+    if (data_sec) {
+       bfd_h_put_x(abfd, data_sec->size, &exec_hdr(abfd)->dsize);
+       bfd_h_put_x(abfd,
+                   data_sec->size ? data_sec->vma : 0,
+                   &exec_hdr(abfd)->data_start);
+    }
+    if (bss_sec) {
+       bfd_h_put_x(abfd, bss_sec->size, &exec_hdr(abfd)->bsize);
+    }
+    bfd_h_put_x(abfd, bfd_get_start_address(abfd), &exec_hdr(abfd)->entry);
+
+
+    /* now write them */
+    bfd_h_put_x(abfd, bfd_get_symcount(abfd), &file_header.f_nsyms);
+    if (bfd_seek(abfd, 0L, SEEK_SET) != 0)
+       return false;
+
+    bfd_write((void *) &file_header, 1, FILHSZ, abfd);
+
+    if (abfd->flags & EXEC_P) {
+
+       bfd_write((void *) exec_hdr(abfd), 1, AOUTSZ, abfd);
+    }
+    return true;
+}
+
+
+
+static          boolean
+coff_set_section_contents(abfd, section, location, offset, count)
+    bfd            *abfd;
+    sec_ptr         section;
+    void           *location;
+    file_ptr        offset;
+    size_t          count;
+{
+    if (abfd->output_has_begun == false)       /* set by bfd.c handler */
+       coff_compute_section_file_positions(abfd);
+
+    bfd_seek(abfd, (file_ptr) (section->filepos + offset), SEEK_SET);
+
+    if (count != 0) {
+       return (bfd_write(location, 1, count, abfd) == count) ? true : false;
+    }
+    return true;
+}
+static          boolean
+coff_get_section_contents(abfd, section, location, offset, count)
+    bfd            *abfd;
+    sec_ptr         section;
+    void           *location;
+    file_ptr        offset;
+    int             count;
+{
+    if (count == 0
+       || offset >= section->size
+       || bfd_seek(abfd, section->filepos + offset, SEEK_SET) == -1
+       || bfd_read(location, 1, count, abfd) != count) {
+       return (false);
+    }                          /* on error */
+    return (true);
+}                              /* coff_get_section_contents() */
+
+
+static          boolean
+coff_close_and_cleanup(abfd)
+    bfd            *abfd;
+{
+    if (!bfd_read_p(abfd))
+       switch (abfd->format) {
+       case bfd_archive:
+           if (!_bfd_write_archive_contents(abfd))
+               return false;
+           break;
+       case bfd_object:
+           if (!coff_write_object_contents(abfd))
+               return false;
+           break;
+       default:
+           bfd_error = invalid_operation;
+           return false;
+       }
+
+#define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
+    cleaner(tdata);
+
+    if (abfd->my_archive)
+       cleaner(filename);
+
+#undef cleaner
+    return true;
+}
+
+
+
+
+
+
+static void    *
+buy_and_read(abfd, where, seek_direction, size)
+    bfd            *abfd;
+    file_ptr        where;
+    int             seek_direction;
+    size_t          size;
+{
+    void           *area = (void *) malloc(size);
+    if (!area) {
+       bfd_error = no_memory;
+       return (NULL);
+    }
+    bfd_seek(abfd, where, seek_direction);
+    if (bfd_read(area, 1, size, abfd) != size) {
+       bfd_error = system_call_error;
+       free(area);
+       return (NULL);
+    }                          /* on error */
+    return (area);
+}                              /* buy_and_read() */
+
+static void
+offset_symbol_indices(symtab, count, offset)
+    SYMENT         *symtab;
+    unsigned long   count;
+    long            offset;
+{
+    SYMENT         *end = symtab + count;
+    for (; symtab < end; ++symtab) {
+       if (symtab->n_sclass == C_FILE) {
+           symtab->n_value = 0;
+       }
+       else if (symtab->n_sclass == C_ALIAS) {
+           /*
+              These guys have indices in their values.
+           */
+           symtab->n_value += offset;
+
+       }
+       else if (symtab->n_numaux) {
+           /*
+              anybody else without an aux, has no indices.
+           */
+
+           if (symtab->n_sclass == C_EOS
+               || (BTYPE(symtab->n_type) == T_STRUCT
+                   && symtab->n_sclass != C_STRTAG)
+               || BTYPE(symtab->n_type) == T_UNION
+               || BTYPE(symtab->n_type) == T_ENUM) {
+
+               ((AUXENT *) (symtab + 1))->x_sym.x_tagndx += offset;
+
+           }                   /* These guys have a tagndx */
+           if (symtab->n_sclass == C_STRTAG
+               || symtab->n_sclass == C_UNTAG
+               || symtab->n_sclass == C_ENTAG
+               || symtab->n_sclass == C_BLOCK
+               || symtab->n_sclass == C_FCN
+               || ISFCN(symtab->n_type)) {
+
+               ((AUXENT *) (symtab + 1))->x_sym.x_fcnary.x_fcn.x_endndx += offset;
+
+           }                   /* These guys have an endndx */
+#ifndef I960
+           if (ISFCN(symtab->n_type)) {
+               ((AUXENT *) (symtab + 1))->x_sym.x_tvndx += offset;
+           }                   /* These guys have a tvndx.  I think...
+                                  (FIXME) */
+#endif                         /* Not I960 */
+
+       }                       /* if value, else if aux */
+       symtab += symtab->n_numaux;
+    }                          /* walk the symtab */
+
+    return;
+}                              /* offset_symbol_indices() */
+/* swap the entire symbol table */
+static void
+swap_raw_symtab(abfd, raw_symtab)
+    bfd            *abfd;
+    SYMENT         *raw_symtab;
+{
+    long            i;
+    SYMENT         *end = raw_symtab + bfd_get_symcount(abfd);
+    for (; raw_symtab < end; ++raw_symtab) {
+       bfd_coff_swap_sym(abfd, raw_symtab);
+
+       for (i = raw_symtab->n_numaux; i; --i, ++raw_symtab) {
+           bfd_coff_swap_aux(abfd,
+                             raw_symtab + 1,
+                             raw_symtab->n_type,
+                             raw_symtab->n_sclass);
+       }                       /* swap all the aux entries */
+    }                          /* walk the symbol table */
+
+    return;
+}                              /* swap_raw_symtab() */
+/*
+   read a symbol table into freshly mallocated memory, swap it, and knit the
+   symbol names into a normalized form. By normalized here I mean that all
+   symbols have an n_offset pointer that points to a NULL terminated string.
+   Oh, and the first symbol MUST be a C_FILE.  If there wasn't one there
+   before, put one there.
+*/
+
+static SYMENT  *
+get_normalized_symtab(abfd)
+    bfd            *abfd;
+{
+    SYMENT         *end;
+    SYMENT         *retval;
+    SYMENT         *s;
+    char           *string_table = NULL;
+    unsigned long   size;
+    unsigned long   string_table_size = 0;
+    /*
+       I used to SEEK_END here to read the symtab and string table all at
+       once.  This fails if this bfd is really an archive element.  Thus, the
+       somewhat convoluted approach to reading in the string table. xoxorich.
+    */
+    /*
+       $if ((bfd_seek(abfd, 0, SEEK_END) == -1) || ((end_of_file =
+       bfd_tell(abfd)) == -1) || (bfd_seek(abfd, obj_sym_filepos(abfd),
+       SEEK_SET) == -1) || ((beginning_of_symtab = bfd_tell(abfd)) == -1)) {
+    
+    bfd_error = system_call_error; return(NULL); }$
+    *//* on error */
+
+    /* $if ((size = end_of_file - beginning_of_symtab) == 0) {$ */
+
+    if ((size = bfd_get_symcount(abfd) * sizeof(SYMENT)) == 0) {
+       bfd_error = no_symbols;
+       return (NULL);
+    }                          /* no symbols */
+    /*
+       This is a hack.  Some tool chains fail to put a C_FILE symbol at the
+       beginning of the symbol table.  To make life simpler for our users, we
+       inject one if it wasn't there originally.
+    
+    We'd like to keep all of this bfd's native symbols in one block to keep
+       table traversals simple.  To do that, we need to know whether we will
+       be prepending the C_FILE symbol before we read the rest of the table.
+    */
+    if ((s = (SYMENT *) malloc(sizeof(SYMENT) * 2)) == NULL) {
+       bfd_error = no_memory;
+       return (NULL);
+    }                          /* on error */
+    if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1
+       || bfd_read(s, sizeof(SYMENT), 1, abfd) != sizeof(SYMENT)) {
+       bfd_error = system_call_error;
+       return (NULL);
+    }                          /* on error */
+    bfd_coff_swap_sym(abfd, s);
+
+    if (s->n_sclass == C_FILE) {
+       obj_symbol_slew(abfd) = 0;
+
+       if ((retval = (SYMENT *) malloc(size)) == NULL) {
+           bfd_error = no_memory;
+           return (NULL);
+       }                       /* on malloc error */
+    }
+    else {
+       unsigned long   namelength = 0;
+       char           *filename;
+       obj_symbol_slew(abfd) = 2;
+
+       if ((retval = (SYMENT *) malloc(size
+                                       + (obj_symbol_slew(abfd)
+                                          * sizeof(SYMENT)))) == NULL) {
+           bfd_error = no_memory;
+           return (NULL);
+       }                       /* on malloc error */
+       bzero((char *) retval, size + (obj_symbol_slew(abfd) * sizeof(SYMENT)));
+
+#define FILE_ENTRY_NAME        ".file"
+
+       if ((retval->n_offset = (int) malloc(strlen(FILE_ENTRY_NAME)
+                                            + 1)) == NULL) {
+           bfd_error = no_memory;
+           return (NULL);
+       }                       /* on malloc error */
+       strcpy((char *) retval->n_offset, FILE_ENTRY_NAME);
+       retval->n_sclass = C_FILE;
+       retval->n_scnum = N_DEBUG;
+       retval->n_numaux = 1;
+
+#undef FILE_ENTRY_NAME
+
+       if ((filename = bfd_get_filename(abfd)) == NULL) {
+           filename = "fake";
+       }                       /* if we know it's name */
+       if ((namelength = strlen(filename)) <= FILNMLEN) {
+           strncpy(((AUXENT *) (retval + 1))->x_file.x_fname, filename, FILNMLEN);
+       }
+       else {
+           if ((((AUXENT *) (retval + 1))->x_file.x_n.x_offset
+                = (int) malloc(namelength)) == NULL) {
+               bfd_error = no_memory;
+               return (NULL);
+           }                   /* on error */
+           strcpy((char *) (((AUXENT *) (retval + 1))->x_file.x_n.x_offset),
+                  filename);
+
+       }                       /* if "short" name */
+    }                          /* missing file entry. */
+
+    free(s);
+
+    if (bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET) == -1
+       || bfd_read(retval + obj_symbol_slew(abfd), size, 1, abfd) != size) {
+       bfd_error = system_call_error;
+       return (NULL);
+    }                          /* on read error */
+    /* mark the end of the symbols */
+    end = retval + obj_symbol_slew(abfd) + bfd_get_symcount(abfd);
+    /*
+       FIXME SOMEDAY.  A string table size of zero is very weird, but
+       probably possible.  If one shows up, it will probably kill us.
+    */
+
+    swap_raw_symtab(abfd, retval + obj_symbol_slew(abfd));
+
+    /* ...and normalize symbol names. */
+
+    for (s = retval + obj_symbol_slew(abfd); s < end; ++s) {
+
+       if (s->n_zeroes != 0) {
+           /*
+              This is a "short" name.  Make it long.
+           */
+           unsigned long   i = 0;
+           char           *newstring = NULL;
+           /*
+              find the length of this string without walking into memory
+              that isn't ours.
+           */
+
+           for (i = 0; i <= 8; ++i) {
+               if (s->n_name[i] == '\0') {
+                   break;
+               }               /* if end of string */
+           }                   /* possible lengths of this string. */
+
+           if ((newstring = malloc(++i)) == NULL) {
+               bfd_error = no_memory;
+               return (NULL);
+           }                   /* on error */
+           bzero(newstring, i);
+           strncpy(newstring, s->n_name, 8);
+           s->n_offset = (int) newstring;
+           s->n_zeroes = 0;
+
+       }
+       else {
+           if (string_table == NULL) {
+               /*
+                  NOTE: we don't read the string table until now because we
+                  don't necessarily know that we have one until now.
+               */
+               /*
+                  At this point we should be "seek"'d to the end of the
+                  symbols === the symbol table size.
+               */
+
+               if (bfd_read((char *) &string_table_size, sizeof(string_table_size), 1, abfd) != sizeof(string_table_size)) {
+                   bfd_error = system_call_error;
+                   return (NULL);
+               }               /* on error */
+               sp(string_table_size);
+
+               if ((string_table = malloc(string_table_size -= 4)) == NULL) {
+                   bfd_error = no_memory;
+                   return (NULL);
+               }               /* on mallocation error */
+               if (bfd_read(string_table, string_table_size, 1, abfd) != string_table_size) {
+                   bfd_error = system_call_error;
+                   return (NULL);
+               }               /* on error */
+           }                   /* have not yet read the string table. */
+           /*
+              This is a long name already. Just point it at the string in
+              memory.
+           */
+           s->n_offset = (int) (string_table - 4 + s->n_offset);
+       }                       /* switch on type of symbol name */
+
+       s += s->n_numaux;
+    }                          /* for each symbol */
+    /*
+       If we had to insert a C_FILE symbol, then everybody's indices are off
+       by 2, so correct them.
+    */
+
+    if (obj_symbol_slew(abfd) > 0) {
+       offset_symbol_indices(retval + 2, bfd_get_symcount(abfd), 2);
+
+       /* and let the world know there are two more of them. */
+       bfd_get_symcount(abfd) += 2;
+    }                          /* if we added a C_FILE */
+    obj_raw_syments(abfd) = retval;
+    obj_string_table(abfd) = string_table;
+
+    return (retval);
+}                              /* get_normalized_symtab() */
+
+static
+struct sec_struct *
+section_from_bfd_index(abfd, index)
+    bfd            *abfd;
+    int             index;
+{
+    if (index > 0) {
+       struct sec_struct *answer = abfd->sections;
+       while (--index) {
+           answer = answer->next;
+       }
+       return answer;
+    }
+    return 0;
+}
+
+static int
+coff_get_symcount_upper_bound(ignore_abfd)
+    bfd            *ignore_abfd;
+{
+    BFD_ASSERT(0);
+    return 0;
+}
+
+static          symindex
+coff_get_first_symbol(ignore_abfd)
+    bfd            *ignore_abfd;
+{
+    return 0;
+}
+
+static          symindex
+coff_get_next_symbol(abfd, oidx)
+    bfd            *abfd;
+    symindex        oidx;
+{
+    if (oidx == BFD_NO_MORE_SYMBOLS)
+       return BFD_NO_MORE_SYMBOLS;
+    return ++oidx >= bfd_get_symcount(abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
+}
+
+static char    *
+coff_symbol_name(abfd, idx)
+    bfd            *abfd;
+    symindex        idx;
+{
+    return (obj_symbols(abfd) + idx)->symbol.name;
+}
+
+static long
+coff_symbol_value(abfd, idx)
+    bfd            *abfd;
+    symindex        idx;
+{
+    return (obj_symbols(abfd) + idx)->symbol.value;
+}
+
+static          symclass
+coff_classify_symbol(abfd, idx)
+    bfd            *abfd;
+    symindex        idx;
+{
+    coff_symbol_type *sym = obj_symbols(abfd) + idx;
+    if ((sym->symbol.flags & BSF_FORT_COMM) != 0)
+       return bfd_symclass_fcommon;
+    if ((sym->symbol.flags & BSF_GLOBAL) != 0)
+       return bfd_symclass_global;
+    if ((sym->symbol.flags & BSF_DEBUGGING) != 0)
+       return bfd_symclass_debugger;
+    if ((sym->symbol.flags & BSF_UNDEFINED) != 0)
+       return bfd_symclass_undefined;
+
+    return bfd_symclass_unknown;
+}
+
+static          boolean
+coff_symbol_hasclass(abfd, idx, class)
+    bfd            *abfd;
+    symindex        idx;
+    symclass        class;
+{
+
+    coff_symbol_type *sym = obj_symbols(abfd) + idx;
+    switch (class) {
+    case bfd_symclass_fcommon:
+       return (sym->symbol.flags & BSF_FORT_COMM) ? true : false;
+    case bfd_symclass_global:
+       return (sym->symbol.flags & BSF_GLOBAL) ? true : false;
+    case bfd_symclass_debugger:
+       return (sym->symbol.flags & BSF_DEBUGGING) ? true : false;;
+    case bfd_symclass_undefined:
+       return (sym->symbol.flags & BSF_UNDEFINED) ? true : false;;
+    default:
+       return false;
+    }
+
+}
+
+
+
+
+static
+                boolean
+coff_slurp_line_table(abfd, asect)
+    bfd            *abfd;
+    asection       *asect;
+{
+    struct lineno  *native_lineno;
+    alent          *lineno_cache;
+    BFD_ASSERT(asect->lineno == (alent *) NULL);
+
+
+    native_lineno = (struct lineno *) buy_and_read(abfd,
+                                                  asect->line_filepos,
+                                                  SEEK_SET,
+                                          (size_t) (sizeof(struct lineno) *
+                                                    asect->lineno_count));
+    lineno_cache =
+       (alent *) malloc((size_t) ((asect->lineno_count + 1) * sizeof(alent)));
+    if (lineno_cache == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    } {                                /* on error */
+       unsigned int    counter = 0;
+       alent          *cache_ptr = lineno_cache;
+       struct lineno  *src = native_lineno;
+       while (counter < asect->lineno_count) {
+           bfd_coff_swap_lineno(abfd, src);
+           cache_ptr->line_number = src->l_lnno;
+
+           if (cache_ptr->line_number == 0) {
+               coff_symbol_type *sym =
+               (coff_symbol_type *) (src->l_addr.l_symndx
+                                     + obj_symbol_slew(abfd)
+                                     + obj_raw_syments(abfd))->n_zeroes;
+               cache_ptr->u.sym = (asymbol *) sym;
+               sym->lineno = cache_ptr;
+           }
+           else {
+               cache_ptr->u.offset = src->l_addr.l_paddr
+                   - bfd_section_vma(abfd, asect);
+           }                   /* If no linenumber expect a symbol index */
+
+           cache_ptr++;
+           src++;
+           counter++;
+       }
+       cache_ptr->line_number = 0;
+
+    }
+    free(native_lineno);
+    asect->lineno = lineno_cache;
+    return true;
+}                              /* coff_slurp_line_table() */
+
+static SYMENT  *
+find_next_file_symbol(current, end)
+    SYMENT         *current;
+    SYMENT         *end;
+{
+    /* ignore the first symbol which is probably a C_FILE. */
+
+    current += current->n_numaux + 1;
+
+    for (; current < end; ++current) {
+       if (current->n_sclass == C_FILE) {
+           return (current);
+       }                       /* found one */
+       current += current->n_numaux;
+    }                          /* walk the remaining table */
+
+    /* not found */
+    return (end);
+}                              /* find_next_file_symbol() */
+/*
+   Note that C_FILE symbols can, and some do, have more than 1 aux entry.
+*/
+
+static void
+force_indices_file_symbol_relative(abfd, symtab)
+    bfd            *abfd;
+    SYMENT         *symtab;
+{
+    SYMENT         *end = symtab + bfd_get_symcount(abfd);
+    SYMENT         *current;
+    SYMENT         *next;
+    /* the first symbol had damn well better be a C_FILE. */
+    BFD_ASSERT(symtab->n_sclass == C_FILE);
+    symtab->n_value = 0;
+
+    for (current = find_next_file_symbol(symtab, end);
+        current < end;
+        current = next) {
+       offset_symbol_indices(current,
+                             ((next =
+                               find_next_file_symbol(current,
+                                                     end)) - current),
+                             symtab - current);
+    }                          /* walk the table */
+
+    return;
+}                              /* force_indices_file_symbol_relative() */
+
+static          boolean
+coff_slurp_symbol_table(abfd)
+    bfd            *abfd;
+{
+    SYMENT         *native_symbols;
+    coff_symbol_type *cached_area;
+    unsigned int   *table_ptr;
+    char           *string_table = (char *) NULL;
+    unsigned int    number_of_symbols = 0;
+    if (obj_symbols(abfd))
+       return true;
+    bfd_seek(abfd, obj_sym_filepos(abfd), SEEK_SET);
+
+    /* Read in the symbol table */
+    if ((native_symbols = get_normalized_symtab(abfd)) == NULL) {
+       return (false);
+    }                          /* on error */
+    force_indices_file_symbol_relative(abfd, native_symbols);
+
+    /* Allocate enough room for all the symbols in cached form */
+    cached_area =
+       (coff_symbol_type *)
+       malloc((size_t) (bfd_get_symcount(abfd) * sizeof(coff_symbol_type)));
+
+    if (cached_area == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    }                          /* on error */
+    table_ptr =
+       (unsigned int *)
+       malloc((size_t) (bfd_get_symcount(abfd) * sizeof(unsigned int)));
+
+    if (table_ptr == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    } {                                /* on error */
+       coff_symbol_type *dst = cached_area;
+       unsigned int    last_native_index = bfd_get_symcount(abfd);
+       unsigned int    this_index = 0;
+       while (this_index < last_native_index) {
+           SYMENT         *src = native_symbols + this_index;
+           table_ptr[this_index] = number_of_symbols;
+           dst->symbol.the_bfd = abfd;
+
+           dst->symbol.name = (char *) src->n_offset;  /* which was normalized
+                                                          to point to a null
+                                                          terminated string. */
+           /*
+              We use the native name field to point to the cached field
+           */
+           src->n_zeroes = (int) dst;
+           dst->symbol.section = section_from_bfd_index(abfd, src->n_scnum);
+
+           switch (src->n_sclass) {
+#ifdef I960
+           case C_LEAFEXT:
+#if 0
+               dst->symbol.value = src->n_value - dst->symbol.section->vma;
+               dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
+               dst->symbol.flags |= BSF_NOT_AT_END;
+#endif
+               /* Fall through to next case */
+
+#endif
+
+           case C_EXT:
+               if (src->n_scnum == 0) {
+                   if (src->n_value == 0) {
+                       dst->symbol.flags = BSF_UNDEFINED;
+                   }
+                   else {
+                       dst->symbol.flags = BSF_FORT_COMM;
+                       dst->symbol.value = src->n_value;
+                   }
+               }
+               else {
+                   /*
+                      Base the value as an index from the base of the
+                      section
+                   */
+                   if (dst->symbol.section == (asection *) NULL) {
+                       dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL | BSF_ABSOLUTE;
+                       dst->symbol.value = src->n_value;
+                   }
+                   else {
+                       dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
+                       dst->symbol.value = src->n_value - dst->symbol.section->vma;
+                   }
+                   if (ISFCN(src->n_type)) {
+                       /*
+                          A function ext does not go at the end of a file
+                       */
+                       dst->symbol.flags |= BSF_NOT_AT_END;
+                   }
+               }
+
+               break;
+           case C_STAT:        /* static                        */
+#ifdef I960
+           case C_LEAFSTAT:    /* static leaf procedure        */
+#endif
+           case C_LABEL:       /* label                         */
+               dst->symbol.flags = BSF_LOCAL;
+               /*
+                  Base the value as an index from the base of the section
+               */
+               dst->symbol.value = src->n_value - dst->symbol.section->vma;
+               break;
+
+           case C_MOS: /* member of structure   */
+           case C_EOS: /* end of structure              */
+           case C_REGPARM:     /* register parameter            */
+           case C_REG: /* register variable             */
+#ifdef C_AUTOARG
+           case C_AUTOARG:     /* 960-specific storage class */
+#endif
+           case C_TPDEF:       /* type definition               */
+
+           case C_ARG:
+           case C_AUTO:        /* automatic variable */
+           case C_FIELD:       /* bit field */
+           case C_ENTAG:       /* enumeration tag               */
+           case C_MOE: /* member of enumeration         */
+           case C_MOU: /* member of union               */
+           case C_UNTAG:       /* union tag                     */
+
+               dst->symbol.flags = BSF_DEBUGGING;
+               dst->symbol.value = src->n_value;
+               break;
+
+           case C_FILE:        /* file name                     */
+           case C_STRTAG:      /* structure tag                 */
+               dst->symbol.flags = BSF_DEBUGGING;
+               dst->symbol.value = src->n_value;
+
+               break;
+           case C_BLOCK:       /* ".bb" or ".eb"                */
+           case C_FCN: /* ".bf" or ".ef"                */
+               dst->symbol.flags = BSF_LOCAL;
+               /*
+                  Base the value as an index from the base of the section
+               */
+               dst->symbol.value = src->n_value - dst->symbol.section->vma;
+
+               break;
+           case C_EFCN:        /* physical end of function      */
+           case C_NULL:
+           case C_EXTDEF:      /* external definition           */
+           case C_ULABEL:      /* undefined label               */
+           case C_USTATIC:     /* undefined static              */
+           case C_LINE:        /* line # reformatted as symbol table entry */
+           case C_ALIAS:       /* duplicate tag                 */
+           case C_HIDDEN:      /* ext symbol in dmert public lib */
+
+           default:
+
+               printf("SICK%d\n", src->n_sclass);
+               abort();
+               dst->symbol.flags = BSF_DEBUGGING;
+               dst->symbol.value = src->n_value;
+
+               break;
+           }
+
+
+
+
+           BFD_ASSERT(dst->symbol.flags != 0);
+
+           dst->native = src;
+
+           dst->symbol.udata = 0;
+           dst->lineno = (alent *) NULL;
+           this_index += src->n_numaux + 1;
+           dst++;
+           number_of_symbols++;
+       }                       /* walk the native symtab */
+
+    }                          /* bfdize the native symtab */
+
+    obj_symbols(abfd) = cached_area;
+    obj_raw_syments(abfd) = native_symbols;
+
+    bfd_get_symcount(abfd) = number_of_symbols;
+    obj_convert(abfd) = table_ptr;
+    /* Slurp the line tables for each section too */
+    {
+       asection       *p;
+       p = abfd->sections;
+       while (p) {
+           coff_slurp_line_table(abfd, p);
+           p = p->next;
+       }
+    }
+    return true;
+}                              /* coff_slurp_symbol_table() */
+
+static unsigned int
+coff_get_symtab_upper_bound(abfd)
+    bfd            *abfd;
+{
+    if (!coff_slurp_symbol_table(abfd))
+       return 0;
+
+    return (bfd_get_symcount(abfd) + 1) * (sizeof(coff_symbol_type *));
+}
+
+
+static unsigned int
+coff_get_symtab(abfd, alocation)
+    bfd            *abfd;
+    asymbol       **alocation;
+{
+    unsigned int    counter = 0;
+    coff_symbol_type *symbase;
+    coff_symbol_type **location = (coff_symbol_type **) (alocation);
+    if (!coff_slurp_symbol_table(abfd))
+       return 0;
+
+    for (symbase = obj_symbols(abfd); counter++ < bfd_get_symcount(abfd);)
+       *(location++) = symbase++;
+    *location++ = 0;
+    return bfd_get_symcount(abfd);
+}
+
+static unsigned int
+coff_get_reloc_upper_bound(abfd, asect)
+    bfd            *abfd;
+    sec_ptr         asect;
+{
+    if (bfd_get_format(abfd) != bfd_object) {
+       bfd_error = invalid_operation;
+       return 0;
+    }
+    return (asect->reloc_count + 1) * sizeof(arelent *);
+}
+
+
+static          boolean
+coff_slurp_reloc_table(abfd, asect, symbols)
+    bfd            *abfd;
+    sec_ptr         asect;
+    asymbol       **symbols;
+{
+    struct reloc   *native_relocs;
+    arelent        *reloc_cache;
+    if (asect->relocation)
+       return true;
+    if (asect->reloc_count == 0)
+       return true;
+    if (!coff_slurp_symbol_table(abfd))
+       return false;
+    native_relocs =
+       (struct reloc *) buy_and_read(abfd,
+                                     asect->rel_filepos,
+                                     SEEK_SET,
+                                     (size_t) (sizeof(struct reloc) *
+                                               asect->reloc_count));
+    reloc_cache = (arelent *)
+       malloc((size_t) (asect->reloc_count * sizeof(arelent)));
+
+    if (reloc_cache == NULL) {
+       bfd_error = no_memory;
+       return (BFD_FAILURE);
+    } {                                /* on error */
+       arelent        *cache_ptr;
+       struct reloc   *src;
+       for (cache_ptr = reloc_cache,
+            src = native_relocs;
+            cache_ptr < reloc_cache + asect->reloc_count;
+            cache_ptr++,
+            src++) {
+           asymbol        *ptr;
+           swap_reloc(abfd, src);
+           src->r_symndx += obj_symbol_slew(abfd);
+           cache_ptr->sym_ptr_ptr = symbols + obj_convert(abfd)[src->r_symndx];
+
+           ptr = *(cache_ptr->sym_ptr_ptr);
+           cache_ptr->address = src->r_vaddr;
+           /*
+              The symbols definitions that we have read in have been
+              relocated as if their sections started at 0. But the offsets
+              refering to the symbols in the raw data have not been
+              modified, so we have to have a negative addend to compensate.
+           */
+
+           if (ptr->the_bfd == abfd && ptr->section != (asection *) NULL) {
+               cache_ptr->addend = -ptr->section->vma;
+           }
+           else {
+               cache_ptr->addend = 0;
+           }
+
+           cache_ptr->address -= asect->vma;
+
+           cache_ptr->section = (asection *) NULL;
+
+#if I960
+           cache_ptr->howto = howto_table + src->r_type;
+#endif
+#if M88
+           if (src->r_type >= R_PCR16L && src->r_type <= R_VRT32) {
+               cache_ptr->howto = howto_table + src->r_type - R_PCR16L;
+           }
+           else {
+               BFD_ASSERT(0);
+           }
+#endif
+#if M68
+           cache_ptr->howto = howto_table + src->r_type;
+#endif
+
+       }
+
+    }
+
+    free(native_relocs);
+    asect->relocation = reloc_cache;
+    return true;
+}
+
+
+/* This is stupid.  This function should be a boolean predicate */
+static unsigned int
+coff_canonicalize_reloc(abfd, section, relptr, symbols)
+    bfd            *abfd;
+    sec_ptr         section;
+    arelent       **relptr;
+    asymbol       **symbols;
+{
+    arelent        *tblptr = section->relocation;
+    unsigned int    count = 0;
+    if (!(tblptr || coff_slurp_reloc_table(abfd, section, symbols)))
+       return 0;
+    tblptr = section->relocation;
+    if (!tblptr)
+       return 0;
+
+    for (; count++ < section->reloc_count;)
+       *relptr++ = tblptr++;
+
+    *relptr = 0;
+
+    return section->reloc_count;
+}
+
+
+
+
+
+/*
+   provided a bfd, a section and an offset into the section, calculate and
+   return the name of the source file and the line nearest to the wanted
+   location.
+*/
+
+static          boolean
+coff_find_nearest_line(abfd,
+                      section,
+                      symbols,
+                      offset,
+                      filename_ptr,
+                      functionname_ptr,
+                      line_ptr)
+    bfd            *abfd;
+    asection       *section;
+    asymbol       **symbols;
+    bfd_vma         offset;
+    char          **filename_ptr;
+    char          **functionname_ptr;
+    unsigned int   *line_ptr;
+{
+    static bfd     *cache_abfd;
+    static asection *cache_section;
+    static bfd_vma  cache_offset;
+    static unsigned int cache_i;
+    static alent   *cache_l;
+
+    unsigned int    i = 0;
+    struct icofdata *cof = obj_icof(abfd);
+    /* Run through the raw syments if available */
+    SYMENT         *p = cof->raw_syments;
+    alent          *l;
+    unsigned int    line_base = 0;
+    *filename_ptr = 0;
+    *functionname_ptr = 0;
+    *line_ptr = 0;
+    /*
+       I don't know for sure what's right, but this isn't it. First off, an
+       object file may not have any C_FILE's in it.  After
+       get_normalized_symtab(), it should have at least 1, the one I put
+       there, but otherwise, all bets are off.  Point #2, the first C_FILE
+       isn't necessarily the right C_FILE because any given object may have
+       many.  I think you'll have to track sections as they coelesce in order
+       to find the C_STAT symbol for this section. Then you'll have to work
+       backwards to find the previous C_FILE, or choke if you get to a C_STAT
+       for the same kind of section.  That will mean that the original object
+       file didn't have a C_FILE. xoxorich.
+    */
+
+#ifdef WEREBEINGPEDANTIC
+    return false;
+#endif
+
+
+
+    for (i = 0; i < cof->raw_syment_count; i++) {
+       if (p->n_sclass == C_FILE) {
+           /* File name is embeded in auxent */
+           /*
+              This isn't right.  The fname should probably be normalized
+              during get_normalized_symtab().  In any case, what was here
+              wasn't right because a SYMENT.n_name isn't an
+              AUXENT.x_file.x_fname. xoxorich.
+           */
+
+           *filename_ptr = ((AUXENT *) (p + 1))->x_file.x_fname;
+           break;
+       }
+       p += 1 + p->n_numaux;
+    }
+    /* Now wander though the raw linenumbers of the section */
+
+
+
+
+    /*
+       If this is the same bfd as we were previously called with and this is
+       the same section, and the offset we want is further down then we can
+       prime the lookup loop
+    */
+    if (abfd == cache_abfd &&
+       section == cache_section &&
+       offset >= cache_offset) {
+       i = cache_i;
+       l = cache_l;
+    }
+    else {
+       i = 0;
+       l = section->lineno;
+    }
+
+    for (; i < section->lineno_count; i++) {
+       if (l->line_number == 0) {
+           /* Get the symbol this line number points at */
+           coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
+           *functionname_ptr = coff->symbol.name;
+           if (coff->native) {
+               struct syment  *s = coff->native;
+               s = s + 1 + s->n_numaux;
+               /*
+                  S should now point to the .bf of the function
+               */
+               if (s->n_numaux) {
+                   /*
+                      The linenumber is stored in the auxent
+                   */
+                   union auxent   *a = (union auxent *) (s + 1);
+                   line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
+               }
+           }
+       }
+       else {
+           if (l->u.offset > offset)
+               break;
+           *line_ptr = l->line_number + line_base + 1;
+       }
+       l++;
+    }
+
+    cache_abfd = abfd;
+    cache_section = section;
+    cache_offset = offset;
+    cache_i = i;
+    cache_l = l;
+    return true;
+}
diff --git a/bfd/coff-i960.c b/bfd/coff-i960.c
new file mode 100644 (file)
index 0000000..3b8e0d6
--- /dev/null
@@ -0,0 +1,270 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#define I960 1
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "libcoff.h"           /* to allow easier abstraction-breaking */
+
+
+
+#include "intel-coff.h"
+
+#define CALLS   0x66003800     /* Template for 'calls' instruction     */
+#define BAL     0x0b000000     /* Template for 'bal' instruction       */
+#define BAL_MASK 0x00ffffff
+
+static bfd_reloc_status_enum_type 
+optcall_callback(abfd, reloc_entry, symbol_in, data, ignore_input_section)
+bfd *abfd;
+arelent *reloc_entry;
+asymbol *symbol_in;
+unsigned char *data;
+asection *ignore_input_section;
+{
+  /* This item has already been relocated correctly, but we may be
+   * able to patch in yet better code - done by digging out the
+   * correct info on this symbol */
+  bfd_reloc_status_enum_type result;
+  coff_symbol_type *cs = coffsymbol(symbol_in);
+
+  /* So the target symbol has to be off coff type, and the symbol 
+     has to have the correct native information within it
+     */
+  if ((cs->symbol.the_bfd->xvec->flavour != bfd_target_coff_flavour_enum)
+      || (cs->native == (struct syment *)NULL)) {
+     /* This is interesting, consider the case where we're outputting */
+     /* coff from a mix n match input, linking from coff to a symbol */
+     /* defined in a bout file will cause this match to be true. Should */
+     /* I complain ? - This will only work if the bout symbol is non */
+     /* leaf. */
+     result = bfd_reloc_dangerous;
+
+  }
+  else  {
+    switch (cs->native->n_sclass) 
+      {
+      case C_LEAFSTAT:
+      case C_LEAFEXT:
+       /* This is a call to a leaf procedure, replace instruction with a bal
+        to the correct location */
+       {
+        union auxent *aux = (union auxent *)(cs->native+2);
+         int word = bfd_getlong(abfd, data + reloc_entry->address);
+         BFD_ASSERT(cs->native->n_numaux==2);
+         /* We replace the original call instruction with a bal to */
+         /* the bal entry point - the offset of which is described in the */
+         /* 2nd auxent of the original symbol. We keep the native sym and */
+         /* auxents untouched, so the delta between the two is the */
+         /* offset of the bal entry point */
+         word = ((word + (aux->x_bal.x_balntry - cs->native->n_value))
+                 & BAL_MASK) | BAL;
+         bfd_putlong(abfd, word,  data+reloc_entry->address);
+       }
+       result = bfd_reloc_ok;
+       break;
+      case C_SCALL:
+       {
+         /* This is a call to a system call, replace with a calls to # */
+         BFD_ASSERT(0);
+       }
+       break;
+      default:
+       result = bfd_reloc_ok;
+       break;
+      }
+  }
+  return result;
+}
+
+
+
+static reloc_howto_type howto_table[] = 
+{
+  {0},
+  {1},
+  {2},
+  {3},
+  {4},
+  {5},
+  {6},
+  {7},
+  {8},
+  {9},
+  {10},
+  {11},
+  {12},
+  {13},
+  {14},
+  {15},
+  {16},
+
+  { (unsigned int) R_RELLONG, 0, 2, 32,false, 0, true, true, 0,"rellong", true, 0xffffffff},
+  {18},
+  {19},
+  {20},
+  {21},
+  {22},
+  {23},
+  {24},
+
+  {  R_IPRMED, 0, 2, 24,true,0, true, true,0,"iprmed ", true, 0x00ffffff},
+  {26},
+  {  R_OPTCALL, 0,2,24,true,0, true, true, optcall_callback, "optcall", true, 0x00ffffff},
+
+};
+
+
+
+#define BADMAG(x) I960BADMAG(x)
+#include "coff-code.h"
+
+
+
+bfd_target icoff_big_vec =
+{
+  "coff-Intel-big",            /* name */
+  bfd_target_coff_flavour_enum,
+  false,                       /* data byte order is little */
+  true,                                /* header byte order is big */
+
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  '/',                         /* ar_pad_char */
+  15,                          /* ar_max_namelen */
+  coff_close_and_cleanup,      /* _close_and_cleanup */
+  coff_set_section_contents,   /* bfd_set_section_contents */
+  coff_get_section_contents,   /* bfd_get_section_contents */
+  coff_new_section_hook,       /* new_section_hook */
+  _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */
+  _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */
+  _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_coff_armap,                /* bfd_slurp_armap */
+  _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/
+#if 0                          /*  */
+  bfd_dont_truncate_arname,    /* bfd_truncate_arname */
+#else
+  bfd_bsd_truncate_arname,
+#endif
+
+  coff_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  coff_get_symtab,             /* canonicalize_symtab */
+  (void (*)())bfd_false,       /* bfd_reclaim_symbol_table */
+  coff_get_reloc_upper_bound,  /* get_reloc_upper_bound */
+  coff_canonicalize_reloc,     /* bfd_canonicalize_reloc */
+  (void (*)())bfd_false,       /* bfd_reclaim_reloc */
+
+  coff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  coff_get_first_symbol,       /* bfd_get_first_symbol */
+  coff_get_next_symbol,                /* bfd_get_next_symbol */
+  coff_classify_symbol,                /* bfd_classify_symbol */
+  coff_symbol_hasclass,                /* bfd_symbol_hasclass */
+  coff_symbol_name,            /* bfd_symbol_name */
+  coff_symbol_value,           /* bfd_symbol_value */
+
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, _bfd_dummy_target},
+  {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+     bfd_false},
+  coff_make_empty_symbol,
+  coff_print_symbol,
+  coff_get_lineno,
+  coff_set_arch_mach,
+  coff_write_armap,
+  bfd_generic_openr_next_archived_file,
+    coff_find_nearest_line,
+    bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
+
+
+bfd_target icoff_little_vec =
+{
+  "coff-Intel-little",         /* name */
+  bfd_target_coff_flavour_enum,
+  false,                       /* data byte order is little */
+  false,                       /* header byte order is little */
+
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  '/',                         /* ar_pad_char */
+  15,                          /* ar_max_namelen */
+  coff_close_and_cleanup,      /* _close_and_cleanup */
+  coff_set_section_contents,   /* bfd_set_section_contents */
+  coff_get_section_contents,   /* bfd_get_section_contents */
+  coff_new_section_hook,       /* new_section_hook */
+  _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */
+  _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */
+  _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_coff_armap,                /* bfd_slurp_armap */
+  _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/
+#if 0                          /*  */
+  bfd_dont_truncate_arname,    /* bfd_truncate_arname */
+#else
+  bfd_bsd_truncate_arname,
+#endif
+  coff_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  coff_get_symtab,             /* canonicalize_symtab */
+  (void (*)())bfd_false,       /* bfd_reclaim_symbol_table */
+  coff_get_reloc_upper_bound,  /* get_reloc_upper_bound */
+  coff_canonicalize_reloc,     /* bfd_canonicalize_reloc */
+  (void (*)())bfd_false,       /* bfd_reclaim_reloc */
+
+  coff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  coff_get_first_symbol,       /* bfd_get_first_symbol */
+  coff_get_next_symbol,                /* bfd_get_next_symbol */
+  coff_classify_symbol,                /* bfd_classify_symbol */
+  coff_symbol_hasclass,                /* bfd_symbol_hasclass */
+  coff_symbol_name,            /* bfd_symbol_name */
+  coff_symbol_value,           /* bfd_symbol_value */
+
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
+  _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */
+
+  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, _bfd_dummy_target},
+  {bfd_false, coff_mkobject,   /* bfd_set_format */
+     _bfd_generic_mkarchive, bfd_false},
+  coff_make_empty_symbol,
+  coff_print_symbol,
+  coff_get_lineno,
+  coff_set_arch_mach,
+  coff_write_armap,
+  bfd_generic_openr_next_archived_file,
+  coff_find_nearest_line,
+    bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+};
+
+
diff --git a/bfd/libaout.h b/bfd/libaout.h
new file mode 100644 (file)
index 0000000..febe2f4
--- /dev/null
@@ -0,0 +1,80 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/* BFD back-end data structures for a.out (and similar) files.
+
+   We try to encapsulate the differences in a few routines, and otherwise
+   share large masses of code.  This means we only have to fix bugs in
+   one place, most of the time.  */
+
+/** a.out files */
+
+#define exec_hdr(bfd) (((struct sunexdata *) ((bfd)->tdata))->hdr)
+/*#define obj_symbols(bfd) ((((struct sunexdata *) ((bfd)->tdata))->symbols))*/
+#define obj_textsec(bfd)  (((struct sunexdata *) ((bfd)->tdata))->textsec)
+#define obj_datasec(bfd)  (((struct sunexdata *) ((bfd)->tdata))->datasec)
+#define obj_bsssec(bfd)  (((struct sunexdata *) ((bfd)->tdata))->bsssec)
+#define        obj_sym_filepos(bfd) (((struct sunexdata *) ((bfd)->tdata))->sym_filepos)
+#define        obj_str_filepos(bfd) (((struct sunexdata *) ((bfd)->tdata))->str_filepos)
+
+
+
+typedef struct {
+  asymbol symbol;
+  short desc;
+char other;
+unsigned char type;
+} aout_symbol_type;
+
+
+struct sunexdata {
+  struct exec *hdr;               /* exec file header */
+  aout_symbol_type *symbols;           /* symtab for input bfd */
+
+  
+  /* For ease, we do this */
+  asection *textsec;
+  asection *datasec;
+  asection *bsssec;
+
+  /* We remember these offsets so that after check_file_format, we have
+     no dependencies on the particular format of the exec_hdr.  */
+  file_ptr sym_filepos;
+  file_ptr str_filepos;
+};
+
+
+#define obj_outsymbols(bfd) ((void *)(((struct sunexdata *) ((bfd)->tdata))->outsymbols))
+
+
+
+/* We case the address of the first element of a asymbol to ensure that the
+ * macro is only every applied to an asymbol
+ */
+#define aout_symbol(asymbol) ((aout_symbol_type *)(&(asymbol)->the_bfd))
+
+/*#define obj_symbols(bfd) ((((struct sunexdata *) ((bfd)->tdata))->symbols))*/
+#define obj_aout_symbols(bfd) ((((struct sunexdata *) (bfd)->tdata))->symbols)
+#define obj_arch_flags(bfd) ((((struct sunexdata *) (bfd)->tdata))->arch_flags)
+
+#define get_tdata(x)  ((struct sunexdata *)((x)->tdata))
+#define set_tdata(x,y)  ((x)->tdata = (void *) (y))
+
+
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
new file mode 100644 (file)
index 0000000..9998690
--- /dev/null
@@ -0,0 +1,332 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/*** libbfd.c -- random bfd support routines used internally only. */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+\f
+/** Dummies for targets that don't want or need to implement
+   certain operations */
+
+boolean
+_bfd_dummy_new_section_hook (ignore, ignore_newsect)
+     bfd *ignore;
+     asection *ignore_newsect;
+{
+  return true;
+}
+
+boolean
+bfd_false (ignore)
+     bfd *ignore;
+{
+  return false;
+}
+
+boolean
+bfd_true (ignore)
+     bfd *ignore;
+{
+  return true;
+}
+
+void *
+bfd_nullvoidptr(ignore)
+bfd *ignore;
+{
+  return (void *)NULL;
+}
+int 
+bfd_0(ignore)
+bfd *ignore;
+{
+  return 0;
+}
+unsigned int 
+bfd_0u(ignore)
+bfd *ignore;
+{
+   return 0;
+}
+
+void 
+bfd_void(ignore)
+bfd *ignore;
+{
+}
+
+boolean
+_bfd_dummy_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd)
+     bfd *ignore_core_bfd;
+bfd *ignore_exec_bfd;
+{
+  bfd_error = invalid_operation;
+  return false;
+}
+
+/* of course you can't initialize a function to be the same as another, grr */
+
+char *
+_bfd_dummy_core_file_failing_command (ignore_abfd)
+     bfd *ignore_abfd;
+{
+  return (char *)NULL;
+}
+
+int
+_bfd_dummy_core_file_failing_signal (ignore_abfd)
+     bfd *ignore_abfd;
+{
+  return 0;
+}
+
+bfd_target *
+_bfd_dummy_target (ignore_abfd)
+     bfd *ignore_abfd;
+{
+  return 0;
+}
+\f
+/** zalloc -- allocate and clear storage */
+
+
+#ifndef zalloc
+char *
+zalloc (size)
+     size_t size;
+{
+  char *ptr = malloc (size);
+
+  if ((ptr != NULL) && (size != 0))
+    bzero (ptr, size);
+
+  return ptr;
+}
+#endif
+\f
+/* Some IO code */
+
+
+/* Note that archive entries don't have streams; they share their parent's.
+   This allows someone to play with the iostream behind bfd's back.
+
+   Also, note that the origin pointer points to the beginning of a file's
+   contents (0 for non-archive elements).  For archive entries this is the
+   first octet in the file, NOT the beginning of the archive header. */
+
+size_t
+bfd_read (ptr, size, nitems, abfd)
+     void *ptr;
+     size_t size;
+     size_t nitems;
+     bfd *abfd;
+{
+  return fread (ptr, 1, size*nitems, bfd_cache_lookup(abfd));
+}
+
+size_t
+bfd_write (ptr, size, nitems, abfd)
+     void *ptr;
+     size_t size;
+     size_t nitems;
+     bfd *abfd;
+{
+  return  fwrite (ptr, 1, size*nitems, bfd_cache_lookup(abfd));
+}
+
+int
+bfd_seek (abfd, position, direction)
+bfd *abfd;
+file_ptr position;
+int direction;
+{
+       /* For the time being, a bfd may not seek to it's end.  The
+          problem is that we don't easily have a way to recognize
+          the end of an element in an archive. */
+
+       BFD_ASSERT(direction == SEEK_SET
+                  || direction == SEEK_CUR);
+       
+       if (direction == SEEK_SET && abfd->my_archive != NULL) 
+           {
+                   /* This is a set within an archive, so we need to
+                      add the base of the object within the archive */
+                   return(fseek(bfd_cache_lookup(abfd),
+                                position + abfd->origin,
+                                direction));
+           }
+       else 
+           {
+                   return(fseek(bfd_cache_lookup(abfd),  position, direction));
+           }   
+}
+
+long
+bfd_tell (abfd)
+     bfd *abfd;
+{
+       file_ptr ptr;
+
+       ptr = ftell (bfd_cache_lookup(abfd));
+
+       if (abfd->my_archive)
+           ptr -= abfd->origin;
+       return ptr;
+}
+\f
+/** Make a string table */
+
+/* Add string to table pointed to by table, at location starting with free_ptr.
+   resizes the table if necessary (if it's NULL, creates it, ignoring
+   table_length).  Updates free_ptr, table, table_length */
+
+boolean
+bfd_add_to_string_table (table, new_string, table_length, free_ptr)
+     char **table, **free_ptr;
+     char *new_string;
+     unsigned int *table_length;
+{
+  size_t string_length = strlen (new_string) + 1; /* include null here */
+  char *base = *table;
+  size_t space_length = *table_length;
+  unsigned int offset = (base ? *free_ptr - base : 0);
+
+  if (base == NULL) {
+    /* Avoid a useless regrow if we can (but of course we still
+       take it next time */
+    space_length = (string_length < DEFAULT_STRING_SPACE_SIZE ?
+                   DEFAULT_STRING_SPACE_SIZE : string_length+1);
+    base = zalloc (space_length);
+
+    if (base == NULL) {
+      bfd_error = no_memory;
+      return false;
+    }
+  }
+
+  if ((size_t)(offset + string_length) >= space_length) {
+    /* Make sure we will have enough space */
+    while ((size_t)(offset + string_length) >= space_length) 
+      space_length += space_length/2; /* grow by 50% */
+
+    base = (char *) realloc (base, space_length);
+    if (base == NULL) {
+      bfd_error = no_memory;
+      return false;
+    }
+
+  }
+
+  memcpy (base + offset, new_string, string_length);
+  *table = base;
+  *table_length = space_length;
+  *free_ptr = base + offset + string_length;
+  
+  return true;
+}
+\f
+/** The do-it-yourself (byte) sex-change kit */
+
+/* The middle letter e.g. get<b>short indicates Big or Little endian
+   target machine.  It doesn't matter what the byte order of the host
+   machine is; these routines work for either.  */
+
+/* FIXME: Should these take a count argument?
+   Answer (gnu@cygnus.com):  No, but perhaps they should be inline
+                            functions in swap.h #ifdef __GNUC__. 
+                            Gprof them later and find out.  */
+
+short
+_do_getbshort (addr)
+       register bfd_byte *addr;
+{
+       return (addr[0] << 8) | addr[1];
+}
+
+short
+_do_getlshort (addr)
+       register bfd_byte *addr;
+{
+       return (addr[1] << 8) | addr[0];
+}
+
+void
+_do_putbshort (data, addr)
+       int data;               /* Actually short, but ansi C sucks */
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte)(data >> 8);
+       addr[1] = (bfd_byte )data;
+}
+
+void
+_do_putlshort (data, addr)
+       int data;               /* Actually short, but ansi C sucks */
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte )data;
+       addr[1] = (bfd_byte)(data >> 8);
+}
+
+long
+_do_getblong (addr)
+       register bfd_byte *addr;
+{
+       return ((((addr[0] << 8) | addr[1]) << 8) | addr[2]) << 8 | addr[3];
+}
+
+long
+_do_getllong (addr)
+       register bfd_byte *addr;
+{
+       return ((((addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0];
+}
+
+void
+_do_putblong (data, addr)
+       unsigned long data;
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte)(data >> 24);
+       addr[1] = (bfd_byte)(data >> 16);
+       addr[2] = (bfd_byte)(data >>  8);
+       addr[3] = (bfd_byte)data;
+}
+
+void
+_do_putllong (data, addr)
+       unsigned long data;
+       register bfd_byte *addr;
+{
+       addr[0] = (bfd_byte)data;
+       addr[1] = (bfd_byte)(data >>  8);
+       addr[2] = (bfd_byte)(data >> 16);
+       addr[3] = (bfd_byte)(data >> 24);
+}
+
+
+
+
+
+
+
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
new file mode 100644 (file)
index 0000000..790d957
--- /dev/null
@@ -0,0 +1,160 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/*** libbfd.h -- Declarations used by bfd library implementation.
+   This include file is not for users of the library */
+
+
+
+
+
+/* If you want to read and write large blocks, you might want to do it
+   in quanta of this amount */
+#define DEFAULT_BUFFERSIZE 8192
+
+/* tdata for an archive.  For an input archive cache
+   needs to be free()'d.  For an output archive, symdefs do.
+*/
+
+struct artdata {
+  file_ptr first_file_filepos;
+  /* Speed up searching the armap */
+  struct ar_cache *cache;
+  bfd *archive_head;            /* Only interesting in output routines */
+  carsym *symdefs;             /* the symdef entries */
+  symindex symdef_count;             /* how many there are */
+  char *extended_names;                /* clever intel extension */
+};
+
+#define bfd_ardata(bfd) ((struct artdata *) ((bfd)->tdata))
+#define bfd_set_ardata(bfd, v) ((bfd)->tdata = (void *) (v))
+
+/* Goes in bfd's arelt_data slot */
+struct areltdata {
+  char * arch_header;                       /* it's actually a string */
+  unsigned int parsed_size;     /* octets of filesize not including ar_hdr */
+  char *filename;                           /* null-terminated */
+};
+
+#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
+
+/* FIXME -- a lot of my code allocates a large block and subdivides it.
+   This can't always work, because of alignment restrictions.  We should change
+   it before it becomes a problem -- Gumby */
+
+PROTO (char *, zalloc, (size_t size));
+PROTO (char *, realloc, (char * ptr, size_t size));
+PROTO (bfd_target *, bfd_find_target, (char *target_name));
+PROTO (size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd *abfd));
+PROTO (size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd *abfd));
+
+
+
+PROTO (FILE *, bfd_cache_lookup, (bfd *));
+PROTO (void, bfd_cache_close, (bfd *));
+PROTO (int, bfd_seek,(bfd*, file_ptr, int direction));
+PROTO (long, bfd_tell, (bfd *abfd));
+PROTO (bfd *, _bfd_create_empty_archive_element_shell, (bfd *obfd));
+PROTO (bfd *, look_for_bfd_in_cache, (bfd *arch_bfd, file_ptr index));
+PROTO (boolean, _bfd_generic_mkarchive, (bfd *abfd));
+PROTO (struct areltdata *, snarf_ar_hdr, (bfd *abfd));
+PROTO (bfd_target *, bfd_generic_archive_p, (bfd *abfd));
+PROTO (boolean, bfd_slurp_bsd_armap, (bfd *abfd));
+PROTO (boolean, bfd_slurp_coff_armap, (bfd *abfd));
+PROTO (boolean, _bfd_slurp_extended_name_table, (bfd *abfd));
+PROTO (boolean, _bfd_write_archive_contents, (bfd *abfd));
+PROTO (bfd *, new_bfd, ());
+
+#define DEFAULT_STRING_SPACE_SIZE 0x2000
+PROTO (boolean, bfd_add_to_string_table, (char **table, char *new_string,
+                                         unsigned int *table_length,
+                                         char **free_ptr));
+     
+PROTO (long, _do_getblong, (unsigned char *addr));
+PROTO (long, _do_getllong, (unsigned char *addr));
+PROTO (short, _do_getbshort, (unsigned char *addr));
+PROTO (short, _do_getlshort, (unsigned char *addr));
+PROTO (void, _do_putblong, (unsigned long data, unsigned char *addr));
+PROTO (void, _do_putllong, (unsigned long data, unsigned char *addr));
+PROTO (void, _do_putbshort, (int data, unsigned char *addr));
+PROTO (void, _do_putlshort, (int data, unsigned char *addr));
+
+PROTO (boolean, bfd_false, (bfd *ignore));
+PROTO (boolean, bfd_true, (bfd *ignore));
+PROTO (void *, bfd_nullvoidptr, (bfd *ignore));
+PROTO (int, bfd_0, (bfd *ignore));
+PROTO (unsigned int, bfd_0u, (bfd *ignore));
+PROTO (void, bfd_void, (bfd *ignore));
+
+
+PROTO (bfd *,new_bfd_contained_in,(bfd *));
+PROTO (boolean, _bfd_dummy_new_section_hook, (bfd *ignore, asection *newsect));
+PROTO (char *, _bfd_dummy_core_file_failing_command, (bfd *abfd));
+PROTO (int, _bfd_dummy_core_file_failing_signal, (bfd *abfd));
+PROTO (boolean, _bfd_dummy_core_file_matches_executable_p, (bfd *core_bfd,
+                                                           bfd *exec_bfd));
+PROTO (bfd_target *, _bfd_dummy_target, (bfd *abfd));
+
+PROTO (void, bfd_dont_truncate_arname, (bfd *abfd, char *filename, char *hdr));
+PROTO (void, bfd_bsd_truncate_arname, (bfd *abfd, char *filename, char *hdr));
+PROTO (void, bfd_gnu_truncate_arname, (bfd *abfd, char *filename, char *hdr));
+
+PROTO (boolean, bsd_write_armap, (bfd *arch, unsigned int elength,
+                                 struct orl *map, int orl_count, int stridx));
+
+PROTO (boolean, coff_write_armap, (bfd *arch, unsigned int elength,
+                                  struct orl *map, int orl_count, int stridx));
+
+PROTO ( bfd *,bfd_generic_openr_next_archived_file, (bfd *archive, bfd *last_file));
+
+PROTO(int, bfd_generic_stat_arch_elt, (bfd *, struct stat *));
+/* Macros to tell if bfds are read or write enabled.
+
+   Note that bfds open for read may be scribbled into if the fd passed
+   to bfd_fdopenr is actually open both for read and write
+   simultaneously.  However an output bfd will never be open for
+   read.  Therefore sometimes you want to check bfd_read_p or
+   !bfd_read_p, and only sometimes bfd_write_p.
+*/
+
+#define bfd_read_p(abfd) ((abfd)->direction == read_direction || (abfd)->direction == both_direction)
+#define bfd_write_p(abfd) ((abfd)->direction == write_direction || (abfd)->direction == both_direction)
+
+PROTO (void, bfd_assert,(char*,int));
+#define BFD_ASSERT(x) \
+{ if (!(x)) bfd_assert(__FILE__,__LINE__); }
+
+#define BFD_FAIL() \
+{ bfd_assert(__FILE__,__LINE__); }
+
+PROTO (FILE *, bfd_cache_lookup_worker, (bfd *));
+
+extern bfd *bfd_last_cache;
+#define bfd_cache_lookup(x) \
+     (x==bfd_last_cache?(FILE*)(bfd_last_cache->iostream):bfd_cache_lookup_worker(x))
+    
+/* Now Steve, what's the story here? */
+#ifdef lint
+#define itos(x) "l"
+#define stoi(x) 1
+#else
+#define itos(x) ((char*)(x))
+#define stoi(x) ((int)(x))
+#endif
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
new file mode 100644 (file)
index 0000000..46f5a78
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/* BFD COFF object file private structure.  */
+
+/* Object file tdata; access macros */
+
+#define obj_icof(bfd)          ((struct icofdata *) ((bfd)->tdata))
+#define exec_hdr(bfd)          (obj_icof(bfd)->hdr)
+#define obj_symbols(bfd)       (obj_icof(bfd)->symbols)
+#define        obj_sym_filepos(bfd)    (obj_icof(bfd)->sym_filepos)
+
+#define obj_relocbase(bfd)     (obj_icof(bfd)->relocbase)
+#define obj_raw_syments(bfd)   (obj_icof(bfd)->raw_syments)
+#define obj_convert(bfd)       (obj_icof(bfd)->conversion_table)
+#define obj_symbol_slew(bfd)   (obj_icof(bfd)->symbol_index_slew)
+#define obj_string_table(bfd)  (obj_icof(bfd)->string_table)
+
+typedef struct {
+  asymbol symbol;
+  struct syment *native;
+  struct lineno_cache_entry *lineno;
+} coff_symbol_type;
+
+struct icofdata {
+  struct aouthdr *hdr;         /* exec file header */
+  coff_symbol_type  *symbols;  /* symtab for input bfd */
+  unsigned int *conversion_table;
+  file_ptr sym_filepos;
+
+  long symbol_index_slew;      /* used during read to mark whether a
+                                  C_FILE symbol as been added. */
+
+  struct syment *raw_syments;
+  struct lineno *raw_linenos;
+  unsigned int raw_syment_count;
+  char *string_table;
+  /* These are only valid once writing has begun */
+  long int relocbase;
+
+};
+
+/* We cast the address of the first element of a asymbol to ensure that the
+ * macro is only ever applied to an asymbol.  */
+#define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd)))
diff --git a/bfd/misc.c b/bfd/misc.c
new file mode 100755 (executable)
index 0000000..041fcde
--- /dev/null
@@ -0,0 +1,98 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+#if 0
+ /* xoxorich.  coelesced from other binutils. */
+/* This crap should all be bundled with the binutils, or else be in its
+   own library, but for expediency we are doing it this way right now. */
+
+/*
+ * Last Mod Mon Feb 18 14:49:39 PST 1991, by rich@cygint.cygnus.com
+ */
+
+#include <stdio.h>
+#include "misc.h"
+#if __STDC__
+extern char *realloc (char * ptr, int size);
+extern char *malloc (int size);
+#else
+extern char *realloc ();
+extern char *malloc ();
+#endif
+
+/* Print the filename of the current file on 'outfile' (a stdio stream).  */
+
+/* Current file's name */
+
+char *input_name;
+
+/* Current member's name, or 0 if processing a non-library file.  */
+
+char *input_member;
+
+void print_file_name (outfile)
+     FILE *outfile;
+{
+  fprintf (outfile, "%s", input_name);
+  if (input_member)
+    fprintf (outfile, "(%s)", input_member);
+}
+\f
+/* process one input file */
+void scan_library ();
+
+char *program_name;
+
+/* Report a nonfatal error.
+   STRING is a format for printf, and ARG1 ... ARG3 are args for it.  */
+/*VARARGS*/
+void
+error (string, arg1, arg2, arg3)
+     char *string, *arg1, *arg2, *arg3;
+{
+  fprintf (stderr, "%s: ", program_name);
+  fprintf (stderr, string, arg1, arg2, arg3);
+  fprintf (stderr, "\n");
+}
+
+
+
+/* Report a nonfatal error.
+   STRING is printed, followed by the current file name.  */
+
+void
+error_with_file (string)
+     char *string;
+{
+  fprintf (stderr, "%s: ", program_name);
+  print_file_name (stderr);
+  fprintf (stderr, ": ");
+  fprintf (stderr, string);
+  fprintf (stderr, "\n");
+}
+
+/* Like malloc but get fatal error if memory is exhausted.  */
+
+
+/* Like realloc but get fatal error if memory is exhausted.  */
+
+
+/* end of misc.c */
+#endif
diff --git a/bfd/misc.h b/bfd/misc.h
new file mode 100755 (executable)
index 0000000..05935c2
--- /dev/null
@@ -0,0 +1,93 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/* xoxorich. coelesced from binutils.
+ *
+ * Last Mod Mon Feb 18 14:49:51 PST 1991, by rich@cygint.cygnus.com
+ */
+
+#ifndef MISC_H
+#define MISC_H 1
+
+#include "ranlib.h"
+
+#ifdef USG
+#include <string.h>
+#else
+#include <strings.h>
+#endif /* USG */
+
+#ifdef never
+#ifdef LOCKS
+#undef LOCKS
+#endif /* LOCKS */
+#endif /* never */
+
+ /* used for masking system io calls into stdio. */
+
+/* the name, ie, argv[0], of this program. */
+
+extern char *program_name;
+
+/* Current file's name */
+
+extern char *input_name;
+
+/* Current member's name, or 0 if processing a non-library file.  */
+
+extern char *input_member;
+
+/* Report an error using the message for the last failed system call,
+   followed by the string NAME.  */
+
+#define perror_name(name)      perror(concat(program_name, ": error on ", name))
+#define pfatal_with_name(name) {perror_name(name);exit(-1);}
+
+#ifdef __STDC__
+
+extern char *concat(char *a, char *b, char *c);
+extern void *xmalloc(unsigned int size);
+extern void * xrealloc(char *ptr, int size);
+extern void error(char *string, char *arg1, char *arg2, char *arg3);
+extern void error_with_file(char *string);
+extern void fatal(char *string, char*a1, char*a2, char*a3);
+extern void print_file_name(FILE *outfile);
+extern void swap_symdef_table(struct symdef *sym, int count);
+#else
+extern char *alloca();
+extern char *concat();
+extern void * xmalloc();
+extern void *xrealloc();
+extern void error();
+extern void error_with_file();
+extern void fatal();
+extern void print_file_name();
+extern void swap_symdef_table();
+#endif /* __STDC__ */
+
+#endif /* MISC_H */
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * End:
+ */
+
+/* end of misc.h */
diff --git a/bfd/opncls.c b/bfd/opncls.c
new file mode 100644 (file)
index 0000000..63e9c51
--- /dev/null
@@ -0,0 +1,281 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+/*** opncls.c -- open and close a bfd. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+extern void bfd_cache_init();
+FILE *bfd_open_file();
+
+/* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
+   if we do that we can't use fcntl.  */
+\f
+/** Locking 
+
+   Locking is loosely controlled by the preprocessor variable
+   BFD_LOCKS.  I say loosely because Unix barely understands locking
+   -- at least in BSD it doesn't affect programs which don't
+   explicitly use it!  That is to say it's practically useless, though
+   if everyone uses this library you'll be OK.
+
+   From among the many and varied lock facilities available, (none of
+   which, of course, knows about any other) we use the fcntl locks,
+   because they're Posix.
+
+   The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
+   exists is because of locking.  When we do output, we lock the
+   filename file for output, then open a temporary file which does not
+   actually get its correct filename until closing time.  This is
+   safest, but requires the asymmetry in read and write entry points.
+
+   Perhaps, since unix has so many different kinds of locking anyway,
+   we should use the emacs lock scheme?... */
+\f
+
+bfd *new_bfd()
+{
+  bfd *nbfd = (bfd *)zalloc(sizeof(bfd));
+
+  nbfd->direction = no_direction;
+  nbfd->iostream = NULL;
+  nbfd->where = 0;
+  nbfd->sections = (asection *)NULL;
+  nbfd->format = bfd_unknown;
+  nbfd->my_archive = (bfd *)NULL;
+  nbfd->origin = 0;                               
+  nbfd->opened_once = false;
+  nbfd->output_has_begun = false;
+  nbfd->section_count = 0;
+  nbfd->usrdata = (void *)NULL;
+  nbfd->sections = (asection *)NULL;
+  nbfd->cacheable = false;
+  nbfd->flags = NO_FLAGS;
+  return nbfd;
+}
+bfd *new_bfd_contained_in(obfd)
+bfd *obfd;
+{
+       bfd *nbfd = new_bfd(obfd);
+       nbfd->xvec = obfd->xvec;
+       nbfd->my_archive = obfd;
+       nbfd->direction = read_direction;
+       return nbfd;
+}
+
+/** bfd_openr, bfd_fdopenr -- open for reading.
+  Returns a pointer to a freshly-allocated bfd on success, or NULL. */
+
+bfd *
+bfd_openr (filename, target)
+     char *filename;
+     char *target;
+{
+  bfd *nbfd;
+  bfd_target *target_vec;
+
+  target_vec = bfd_find_target (target);
+  if (target_vec == NULL) {
+    bfd_error = invalid_target;
+    return NULL;
+  }
+
+  bfd_error = system_call_error;
+  nbfd = new_bfd();
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  nbfd->filename = filename;
+  nbfd->xvec = target_vec;
+  nbfd->direction = read_direction; 
+
+  if (bfd_open_file (nbfd) == NULL) {
+    bfd_error = system_call_error;     /* File didn't exist, or some such */
+    free (nbfd);
+    return NULL;
+  }
+  return nbfd;
+}
+
+
+/* Don't try to `optimize' this function:
+
+   o - We lock using stack space so that interrupting the locking
+       won't cause a storage leak.
+   o - We open the file stream last, since we don't want to have to
+       close it if anything goes wrong.  Closing the stream means closing
+       the file descriptor too, even though we didn't open it.
+ */
+
+bfd *
+bfd_fdopenr (filename, target, fd)
+     char *filename;
+     char *target;
+     int fd;
+{
+  bfd *nbfd;
+  bfd_target *target_vec;
+  int fdflags;
+#ifdef BFD_LOCKS
+  struct flock lock, *lockp = &lock;
+#endif
+
+  target_vec = bfd_find_target (target);
+  if (target_vec == NULL) {
+    bfd_error = invalid_target;
+    return NULL;
+  }
+
+  bfd_error = system_call_error;
+  
+  fdflags = fcntl (fd, F_GETFL);
+  if (fdflags == -1) return NULL;
+
+#ifdef BFD_LOCKS
+  lockp->l_type = F_RDLCK;
+  if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
+#endif
+
+  nbfd = new_bfd();
+
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+#ifdef BFD_LOCKS
+  nbfd->lock = (struct flock *) (nbfd + 1);
+#endif
+  /* if the fd were open for read only, this still would not hurt: */
+  nbfd->iostream = (char *) fdopen (fd, "r+"); 
+  if (nbfd->iostream == NULL) {
+    free (nbfd);
+    return NULL;
+  }
+  
+  /* OK, put everything where it belongs */
+
+  nbfd->filename = filename;
+  nbfd->xvec = target_vec;
+
+  /* As a special case we allow a FD open for read/write to
+     be written through, although doing so requires that we end
+     the previous clause with a preposition.  */
+  switch (fdflags & O_ACCMODE) {
+  case O_RDONLY: nbfd->direction = read_direction; break;
+  case O_WRONLY: nbfd->direction = write_direction; break;  
+  case O_RDWR: nbfd->direction = both_direction; break;
+  default: abort ();
+  }
+                                  
+#ifdef BFD_LOCKS
+  memcpy (nbfd->lock, lockp, sizeof (struct flock))
+#endif
+
+    bfd_cache_init (nbfd);
+
+  return nbfd;
+}
+\f
+/** bfd_openw -- open for writing.
+  Returns a pointer to a freshly-allocated bfd on success, or NULL.
+
+  See comment by bfd_fdopenr before you try to modify this function. */
+
+bfd *
+bfd_openw (filename, target)
+     char *filename;
+     char *target;
+{
+  bfd *nbfd;
+  bfd_target *target_vec;
+  
+  target_vec = bfd_find_target (target);
+  if (target_vec == NULL) return NULL;
+
+  bfd_error = system_call_error;
+
+  /* nbfd has to point to head of malloc'ed block so that bfd_close may
+     reclaim it correctly. */
+
+  nbfd = new_bfd();
+  if (nbfd == NULL) {
+    bfd_error = no_memory;
+    return NULL;
+  }
+
+  nbfd->filename = filename;
+  nbfd->xvec = target_vec;
+  nbfd->direction = write_direction;
+
+  if (bfd_open_file (nbfd) == NULL) {
+    bfd_error = system_call_error;     /* File not writeable, etc */
+    free (nbfd);
+    return NULL;
+  }
+  return nbfd;
+}
+
+
+\f
+/** Close up shop, get your deposit back. */
+boolean
+bfd_close (abfd)
+     bfd *abfd;
+{
+  if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
+
+  bfd_cache_close(abfd);
+/* If the file was open for writing and is now executable
+  make it so */
+  if (abfd->direction == write_direction 
+      && abfd->flags & EXEC_P) {
+    struct stat buf;
+    stat(abfd->filename, &buf);
+    chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
+  }
+  free (abfd);
+  return true;
+}
+/* 
+ called to create a bfd with no ascociated file or target 
+ */
+bfd *
+bfd_create(filename, template)
+char *filename;
+bfd *template;
+{
+  bfd *nbfd = new_bfd();
+  if (nbfd == (bfd *)NULL) {
+    bfd_error = no_memory;
+    return (bfd *)NULL;
+  }
+  nbfd->filename = filename;
+  nbfd->xvec = template->xvec;
+  nbfd->direction = no_direction;
+  return nbfd;
+
+
+
+}
diff --git a/bfd/srec.c b/bfd/srec.c
new file mode 100644 (file)
index 0000000..3ac8e59
--- /dev/null
@@ -0,0 +1,464 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+
+ bfd backend for srecord objects.
+
+ Srecords cannot hold anything but addresses and data, so that's all
+ that we impliment.
+ The only interesting thing is that srecords may come out of order and
+ there is no header, so an initial scan is required to discover the
+ minimum and maximum addresses used to create the vma and size of the
+ only section we create. We arbitarily call this section ".text".
+
+ When bfd_get_section_contents is called the file is read again, and
+ this time the data is placed into a malloced area.
+
+ Any number of sections may be created for output, we just output them
+ in the order provided to bfd_set_section_contents.
+
+
+ Steve Chamberlain steve@cygnus.com
+
+ */
+
+
+/* $Id$
+ * $Log$
+ * Revision 1.1  1991/03/21 21:11:20  gumby
+ * Initial revision
+ *
+ * Revision 1.1  1991/03/13  00:22:29  chrisb
+ * Initial revision
+ *
+ * Revision 1.3  1991/03/10  19:11:40  rich
+ *  Modified Files:
+ *     bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
+ *
+ * Working bugs out of coff support.
+ *
+ * Revision 1.2  1991/03/07  02:26:18  sac
+ * Tidied up xfer table
+ *
+ * Revision 1.1  1991/03/05  16:28:12  sac
+ * Initial revision
+ *
+ */
+
+#include "libbfd.h"
+
+
+static char digs[] = "0123456789ABCDEF";
+
+/* Macros for converting between hex and binary */
+
+#define NIBBLE(x) ((x >= '0' && x <= '9') ? (x - '0') : (x - 'A' + 10))
+#define HEX(buffer) ((NIBBLE((buffer)->high) <<4) + NIBBLE((buffer)->low))
+#define TOHEX(d,x) \
+  ((d)->low = digs[(x) & 0xf], (d)->high = digs[((x)>>4)&0xf], x)
+
+typedef struct {
+  char high;
+  char low;
+} byte_as_two_char_type;
+
+/* The maximum number of bytes on a line is FF */
+#define MAXCHUNK 0xff 
+/* The number of bytes we fit onto a line on output */
+#define CHUNK 16 
+
+/* The shape of an srecord .. */
+typedef struct 
+{
+  char S;
+  char type;
+  byte_as_two_char_type size;
+  union {
+    struct {
+      byte_as_two_char_type address[4];
+      byte_as_two_char_type data[MAXCHUNK];
+      /* If there isn't MAXCHUNK bytes of data then the checksum will 
+        appear earlier */
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_3;
+    struct {
+      byte_as_two_char_type address[4];
+      byte_as_two_char_type data[MAXCHUNK];
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_6;
+
+    struct {
+      byte_as_two_char_type address[3];
+      byte_as_two_char_type data[MAXCHUNK];
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_2;
+
+    struct {
+      byte_as_two_char_type address[2];
+      byte_as_two_char_type data[MAXCHUNK];
+      byte_as_two_char_type checksum;
+      char nl;
+    } type_1;
+    byte_as_two_char_type data[MAXCHUNK];
+  } u;
+} srec_type;
+
+
+/* 
+   called once per input srecord, used to work out vma and size of data.
+ */
+
+static void
+size_srec(abfd, section, address, raw, length)
+bfd *abfd;
+asection *section;
+bfd_vma address;
+byte_as_two_char_type *raw;
+unsigned int length;
+{
+  if (address < section->vma)
+    section->vma = address;
+
+  if (address + length  > section->vma + section->size)
+    section->size = (address+length) -  section->vma;
+}
+
+/*
+ called once per input srecord, copies data from input into malloced area
+ */
+
+static void
+fillup(abfd, section, address, raw, length)
+bfd *abfd;
+asection *section;
+bfd_vma address;
+byte_as_two_char_type *raw;
+unsigned int length;
+{
+  unsigned int i;
+  bfd_byte *dst = (bfd_byte *)(section->used_by_bfd) +  address - section->vma;
+  for (i = 0; i < length; i++) {
+    *dst = HEX(raw);
+    dst++;
+    raw++;
+  }
+}
+
+/*
+ pass over an srecord file calling one of the above functions on each
+ record
+ */
+static void
+pass_over(abfd, func, section)
+bfd *abfd;
+void (*func)();
+asection *section;
+{
+  unsigned int bytes_on_line;
+  boolean eof = false;
+  bfd_vma address;
+  /* To the front of the file */
+  bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+  while (eof == false)
+    {
+      srec_type buffer;
+
+      /* Find first 'S' */
+      eof =  bfd_read(&buffer.S, 1, 1, abfd) != 1;
+      while (buffer.S != 'S' && !eof) {
+       eof =  bfd_read(&buffer.S, 1, 1, abfd) != 1;
+      }
+      if (eof) break;
+
+      bfd_read(&buffer.type, 1, 3, abfd);
+
+      bytes_on_line = HEX(&buffer.size);
+    
+      bfd_read(buffer.u.data, 1 , bytes_on_line * 2, abfd);
+
+      switch (buffer.type) {
+      case '6':
+       /* Prologue - ignore */
+       break;
+      case '3':
+       address = (HEX(buffer.u.type_3.address+0) << 24)
+         + (HEX(buffer.u.type_3.address+1) << 16)
+           + (HEX(buffer.u.type_3.address+2) << 8) 
+             + (HEX(buffer.u.type_3.address+3));
+        func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
+
+       break;
+
+      case '2':
+       address = (HEX(buffer.u.type_2.address+0) << 16)+
+         (HEX(buffer.u.type_2.address+1) << 8) +
+       (HEX(buffer.u.type_2.address+2));
+        func(abfd,section, address, buffer.u.type_2.data, bytes_on_line -1);
+
+       break;
+      case '1':
+       address =
+         (HEX(buffer.u.type_1.address+0) << 8) 
+           + (HEX(buffer.u.type_1.address+1));
+        func(abfd, section, address, buffer.u.type_1.data, bytes_on_line -1);
+       break;
+
+      }
+    }
+}
+
+
+bfd_target *
+srec_object_p (abfd)
+bfd *abfd;
+{
+  char b;
+  asection *section;
+  bfd_seek(abfd, (file_ptr)0, SEEK_SET);
+  bfd_read(&b, 1,1,abfd);
+  if (b != 'S') return (bfd_target*)NULL;
+
+  /* 
+     We create one section called data for all the contents, 
+     and allocate enough room for the entire file
+     */
+
+
+  section =  bfd_make_section(abfd, ".text");
+  section->size = 0;
+  section->vma = 0xffffffff;
+  pass_over(abfd, size_srec, section);
+
+  return abfd->xvec;
+}
+
+
+
+
+
+
+
+
+static boolean
+srec_get_section_contents (abfd, section, location, offset, count)
+bfd *abfd;
+sec_ptr section;
+void  *location;
+file_ptr offset;
+unsigned      int count;
+{
+  if (section->used_by_bfd == (bfd_byte *)NULL) {
+    section->used_by_bfd = (bfd_byte *)malloc(section->size);
+    pass_over(abfd, fillup, section);
+  }
+  (void) memcpy(location, (bfd_byte *)(section->used_by_bfd) + offset, count);
+  return true;
+}
+      
+
+
+boolean
+srec_set_arch_mach (abfd, arch, machine)
+bfd *abfd;
+enum bfd_architecture arch;
+unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  return true;
+}
+
+
+
+boolean
+srec_set_section_contents (abfd, section, location, offset, bytes_to_do)
+bfd *abfd;
+sec_ptr section;
+unsigned char *location;
+file_ptr offset;
+int bytes_to_do;
+{
+  bfd_vma address;
+  int bytes_written;
+
+  int type;
+  unsigned int i;
+  srec_type buffer;
+  bytes_written = 0;
+  if (section->size <= 0xffff) 
+    type = 1;
+  else if (section->size <= 0xffffff) 
+    type = 2;
+  else
+    type = 3;
+
+  buffer.S = 'S';
+  buffer.type = '0' + type;
+
+  while (bytes_written < bytes_to_do) {
+    unsigned int size;
+    unsigned int check_sum;
+    byte_as_two_char_type *data; 
+    int bytes_this_chunk = bytes_to_do - bytes_written;
+
+    if (bytes_this_chunk > CHUNK) {
+      bytes_this_chunk = CHUNK;
+    }
+
+    address = section->vma + offset + bytes_written;
+
+    switch (type) {
+    case 3:
+      check_sum = TOHEX(buffer.u.type_3.address, address >> 24);
+      check_sum += TOHEX(buffer.u.type_3.address+1, address >> 16);
+      check_sum += TOHEX(buffer.u.type_3.address+2, address >> 8);
+      check_sum += TOHEX(buffer.u.type_3.address+3, address >> 0);
+      size = bytes_this_chunk + 5;
+      data = buffer.u.type_3.data;
+
+    case 2:
+      check_sum = TOHEX(buffer.u.type_3.address, address >> 16);
+      check_sum += TOHEX(buffer.u.type_3.address+1, address >> 8);
+      check_sum += TOHEX(buffer.u.type_3.address+2, address >> 0);
+      size = bytes_this_chunk + 4;
+      data = buffer.u.type_2.data;
+      break;
+
+    case 1:
+      check_sum = TOHEX(buffer.u.type_3.address+0, address >> 8);
+      check_sum += TOHEX(buffer.u.type_3.address+1, address >> 0);
+      size = bytes_this_chunk + 3;
+      data = buffer.u.type_1.data;
+    }
+
+    for (i = 0; i < bytes_this_chunk; i++) {
+      check_sum += TOHEX(data, (location[i]));
+      data++;
+    }
+
+    check_sum += TOHEX(&(buffer.size), size );
+    (void) TOHEX(data, ~check_sum);
+    data++;
+
+    * ( (char *)(data)) = '\n';
+    bfd_write(&buffer, 1, (char *)data - (char *)&buffer + 1 , abfd);
+
+    bytes_written += bytes_this_chunk;
+    location += bytes_this_chunk;
+  }
+
+
+  return true;
+}
+
+
+boolean
+srec_close_and_cleanup (abfd)
+bfd *abfd;
+{
+  asection *s;
+  if (bfd_read_p (abfd) == false) {
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) {
+       return false;
+      }
+      break;
+    case bfd_object:
+      bfd_write("S9030000FC\n", 1,11,abfd);
+      break;
+    default:
+      bfd_error = invalid_operation;
+      return false;
+    }
+  }
+  for (s = abfd->sections; s != (asection *)NULL;s = s->next) {
+    if (s->used_by_bfd != (void *)NULL) {
+      free(s->used_by_bfd);
+    }
+  }
+  return true;
+}
+
+/*SUPPRESS 460 */
+bfd_target srec_vec =
+{
+  "srec",                      /* name */
+  bfd_target_srec_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_CODE|SEC_DATA|SEC_ROM
+   |SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  srec_close_and_cleanup,      /* _close_and_cleanup */
+  srec_set_section_contents,    /* bfd_set_section_contents */
+  srec_get_section_contents,
+  bfd_true,                    /*   new_section_hook */
+  0,                           /* _core_file_failing_command */
+  0,                           /* _core_file_failing_signal */
+  0,                           /* _core_file_matches_ex...p */
+
+  bfd_false,                   /* bfd_slurp_armap */
+  bfd_false,                   /* bfd_slurp_extended_name_table */
+  bfd_void,                    /* bfd_truncate_arname */
+  bfd_0u,                      /* get_symtab_upper_bound */
+  bfd_0u,                      /* canonicalize_symtab */
+  bfd_void,                    /* bfd_reclaim_symbol_table */
+  bfd_0u,                      /* get_reloc_upper_bound */
+  bfd_0u,                      /* bfd_canonicalize_reloc */
+  bfd_void,                    /* bfd_reclaim_reloc */
+  bfd_0,                       /* bfd_get_symcount_upper_bound */
+  (symindex (*)())bfd_0,       /* bfd_get_first_symbol */
+  (symindex (*)())bfd_0,       /* bfd_get_next_symbol */
+  bfd_false,                   /* bfd_classify_symbol */
+  bfd_false,                   /* bfd_symbol_hasclass */
+  (char* (*)())bfd_0,          /* bfd_symbol_name */
+  bfd_0,                       /* bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target,
+     srec_object_p,            /* bfd_check_format */
+     (struct bfd_target *(*)()) bfd_nullvoidptr,
+     (struct bfd_target *(*)())     bfd_nullvoidptr,
+   },
+  {
+    bfd_false,
+    bfd_true,                  /* mkobject */
+    _bfd_generic_mkarchive,
+    bfd_false,
+  },
+  (asymbol * (*)())  bfd_nullvoidptr, /* bfd_make_empty_symbol */
+  bfd_void,                    /* bfd_prit_symbol */
+  (alent *(*)())bfd_nullvoidptr, /* srec_get_lineno,*/
+  srec_set_arch_mach,          /* bfd_set_arch_mach,*/
+  bfd_false,                   /* write_armap*/
+  (bfd *(*)())bfd_nullvoidptr, /* openr_next_archived_file */
+  bfd_false,                   /* bfd_find_nearest_line */
+};
diff --git a/bfd/sunos.c b/bfd/sunos.c
new file mode 100644 (file)
index 0000000..f857897
--- /dev/null
@@ -0,0 +1,1904 @@
+/*** bfd backend for sunos binaries */
+
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$
+ * $Log$
+ * Revision 1.1  1991/03/21 21:11:23  gumby
+ * Initial revision
+ *
+ * Revision 1.2  1991/03/15  18:16:52  rich
+ * *** empty log message ***
+ *
+ * Revision 1.12  1991/03/10  19:11:41  rich
+ *  Modified Files:
+ *     bfd.c coff-code.h libbfd.c libbfd.h srec.c sunos.c
+ *
+ * Working bugs out of coff support.
+ *
+ * Revision 1.11  1991/03/09  03:40:04  rich
+ *  Modified Files:
+ *     Makefile b.out.c liba.out.h libbfd.c sunos.c sysdep.h
+ *
+ * Changes dictated by porting binutils.
+ *
+ * Revision 1.10  1991/03/08  07:52:02  sac
+ * Reinstalled things which went away after latest merge from Intel.
+ *
+ * Fixed a couple of problems in symbol handling too.
+ *
+ * Revision 1.9  1991/03/08  04:18:16  rich
+ * *** empty log message ***
+ *
+ * Revision 1.8  1991/03/07  21:57:26  sac
+ * Moved type info out of the asymbol into the private space.
+ * Cleaned up C++ stuff
+ *
+ * Revision 1.7  1991/03/06  21:49:02  sac
+ * Modified bfd_find_filename to return name of function too.
+ *
+ * Revision 1.6  1991/03/06  02:19:36  sac
+ * Moved howto table, added support for constructor sections and provided
+ * sunos4_find_nearest_line
+ *
+ * Revision 1.5  1991/03/05  16:25:44  sac
+ * Modified howto vector to include inplace and mask fields.
+ *
+ */
+
+#define TARGET_BYTE_ORDER_BIG_P 1
+#define TARGET TARGET_SPARC
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include <stdio.h>
+
+
+/*SUPPRESS558*/
+/*SUPPRESS529*/
+
+
+
+
+typedef void generic_symbol_type;
+/* These values are correct for the SPARC.  I dunno about anything else */
+#define PAGE_SIZE 0x02000
+#define SEGMENT_SIZE PAGE_SIZE
+#define TEXT_START_ADDR PAGE_SIZE
+#include "a.out.gnu.h"
+#include "stab.gnu.h"
+#include "ar.h"
+#include "liba.out.h"           /* BFD a.out internal data structures */
+
+#include "a.out.sun4.h"
+
+#define CTOR_TABLE_RELOC_IDX 2
+static  reloc_howto_type howto_table[] = 
+{
+  /* type                   rs   size bsz  pcrel bitpos  abs ovrf sf name partial inplace mask*/
+{ (unsigned int) RELOC_8,      0,  0,          8,  false, 0, true,  true,0,"8",        false, 0x000000ff},
+{ (unsigned int) RELOC_16,     0,  1,  16, false, 0, true,  true,0,"16",       false, 0x0000ffff},
+{ (unsigned int) RELOC_32,     0,  2,  32, false, 0, true,  true,0,"32",       false,  0xffffffff},
+{ (unsigned int) RELOC_DISP8,  0,  0,  8,  true,  0, false, true,0,"DISP8",    false, 0x000000ff},
+{ (unsigned int) RELOC_DISP16, 0,  1,  16, true,  0, false, true,0,"DISP16",   false, 0x0000ffff},
+{ (unsigned int) RELOC_DISP32, 0,  2,  32, true,  0, false, true,0,"DISP32",   false, 0xffffffff},
+{ (unsigned int) RELOC_WDISP30,2,  2,  30, true,  0, false, true,0,"WDISP30",  false, 0x3fffffff},
+{ (unsigned int) RELOC_WDISP22,2,  2,  22, true,  0, false, true,0,"WDISP22",  false, 0x003fffff},
+{ (unsigned int) RELOC_HI22,   10, 2,  22, false, 0, false, true,0,"HI22",     false, 0x003fffff},
+{ (unsigned int) RELOC_22,      0, 2,  22, false, 0, false, true,0,"22",       false, 0x003fffff},
+{ (unsigned int) RELOC_13,     0, 2,   13, false, 0, false, true,0,"13",       false, 0x00001fff},
+{ (unsigned int) RELOC_LO10,   0, 2,   10, false, 0, false, true,0,"LO10",     false, 0x000003ff},
+{ (unsigned int) RELOC_SFA_BASE,0, 2,  32, false, 0, false, true,0,"SFA_BASE", false, 0xffffffff},
+{ (unsigned int) RELOC_SFA_OFF13,0,2,  32, false, 0, false, true,0,"SFA_OFF13",false, 0xffffffff},
+{ (unsigned int) RELOC_BASE10, 0,  2,  16, false, 0, false, true,0,"BASE10",   false, 0x0000ffff},
+{ (unsigned int) RELOC_BASE13, 0,  2,  13, false, 0, false, true,0,"BASE13",   false, 0x00001fff},
+{ (unsigned int) RELOC_BASE22, 0,  2,  0,  false, 0, false, true,0,"BASE22",   false, 0x00000000},
+{ (unsigned int) RELOC_PC10,   0,  2,  10, false, 0, false, true,0,"PC10",     false, 0x000003ff},
+{ (unsigned int) RELOC_PC22,   0,  2,  22, false, 0, false, true,0,"PC22",     false, 0x003fffff},
+{ (unsigned int) RELOC_JMP_TBL,0,  2,  32, false, 0, false, true,0,"JMP_TBL",  false, 0xffffffff},
+{ (unsigned int) RELOC_SEGOFF16,0, 2,  0,  false, 0, false, true,0,"SEGOFF16", false, 0x00000000},
+{ (unsigned int) RELOC_GLOB_DAT,0, 2,  0,  false, 0, false, true,0,"GLOB_DAT", false, 0x00000000},
+{ (unsigned int) RELOC_JMP_SLOT,0, 2,  0,  false, 0, false, true,0,"JMP_SLOT", false, 0x00000000},
+{ (unsigned int) RELOC_RELATIVE,0, 2,  0,  false, 0, false, true,0,"RELATIVE", false, 0x00000000},
+{ (unsigned int) RELOC_JUMPTARG,2, 13, 16, true,  0, false, true,0,"JUMPTARG", false, 0x0000ffff},
+{ (unsigned int) RELOC_CONST,  0, 13,  16, false, 0, false, true,0,"CONST",    false, 0x0000ffff},
+{ (unsigned int) RELOC_CONSTH, 16, 13, 16, false, 0, false, true,0,"CONSTH",   false, 0x0000ffff},
+};
+
+/** a.out files */
+
+PROTO (static void, swap_exec_header, (bfd *abfd, struct exec *execp));
+PROTO (void , sunos4_write_syms, ());
+PROTO (static boolean,sunos4_squirt_out_relocs,(bfd *abfd, asection *section));
+
+/* Steve wants some way to frob this stuff from Saber while he's debugging
+   ld, so we have these funny shadow functions */
+/* ZMAGIC's start at 0 (making the exec part of the text section),
+  other formats start after the exec
+*/
+unsigned int n_txtoff(ptr)
+struct exec *ptr;
+{return N_MAGIC(*ptr)== ZMAGIC ? 0: sizeof(struct exec);}
+
+unsigned int n_datoff(ptr)
+struct exec *ptr;
+{return n_txtoff(ptr) + ptr->a_text;}
+
+unsigned int n_treloff(ptr)
+struct exec *ptr;
+{return n_datoff(ptr) + ptr->a_data;}
+
+unsigned int n_dreloff(ptr)
+struct exec *ptr;
+{return n_treloff(ptr) + ptr->a_trsize;}
+
+unsigned int n_symoff(ptr)
+struct exec *ptr;
+{return n_dreloff(ptr) + ptr->a_drsize;}
+
+unsigned int n_stroff(ptr)
+struct exec *ptr;
+{return n_symoff(ptr) + ptr->a_syms;}
+
+unsigned int n_badmag(ptr)
+     struct exec *ptr;
+{
+  switch (N_MAGIC(*ptr)) {
+  case OMAGIC: case NMAGIC: case ZMAGIC: return 0;
+  default: return 1;
+  }
+}
+
+
+bfd_target *
+sunos4_object_p (abfd)
+     bfd *abfd;
+{
+  unsigned long magic;
+  struct exec anexec;           /* save consing when you don't have to. */
+  struct exec *execp = &anexec;
+  void *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)&magic, 1, sizeof (magic), abfd) != sizeof (magic))
+    return 0;
+  magic = bfd_h_getlong (abfd, &magic);
+
+  /* Baroque syntax to mask deficiencies of the Sun compiler */
+  /* if (N_BADMAG (*((struct exec *) &magic))) return 0; */
+  if (n_badmag ((struct exec *) &magic)) return 0;
+
+  if (bfd_seek (abfd, 0L, SEEK_SET) < 0) return 0;
+
+  if (bfd_read ((void *) execp, 1, sizeof (struct exec), abfd)
+      != sizeof (struct exec)) {
+    bfd_error = wrong_format;
+    return 0;
+  }
+
+  /* Use an intermediate variable for clarity */
+  rawptr = (void *) zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  abfd->tdata =(void *)( (struct sunexdata *) rawptr);
+  exec_hdr (abfd) =
+    (struct exec *) ((char *)rawptr + sizeof (struct sunexdata));
+
+  swap_exec_header (abfd, execp);
+  memcpy (exec_hdr (abfd), execp, sizeof (struct exec));
+
+  /* Set the file flags */
+  abfd->flags = NO_FLAGS;
+  if (execp->a_drsize || execp->a_trsize)
+    abfd->flags |= HAS_RELOC;
+  if (execp->a_entry) 
+    abfd->flags |= EXEC_P;
+  if (execp->a_syms) 
+    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+
+  if (N_MAGIC (anexec) == ZMAGIC) abfd->flags |= D_PAGED;
+  if (N_MAGIC (anexec) == NMAGIC) abfd->flags |= WP_TEXT;
+
+  /* Determine the architecture and machine type of the object file.  */
+  abfd->obj_arch = bfd_arch_unknown;   /* Default values */
+  abfd->obj_machine = 0;
+  switch (N_MACHTYPE (anexec)) {
+
+  case M_UNKNOWN:
+       break;
+
+  case M_68010:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68010;
+       break;
+
+  case M_68020:
+       abfd->obj_arch = bfd_arch_m68k;
+       abfd->obj_machine = 68020;
+       break;
+
+  case M_SPARC:
+       abfd->obj_arch = bfd_arch_sparc;
+       break;
+
+  case M_386:
+       abfd->obj_arch = bfd_arch_i386;
+       break;
+
+  case M_29K:
+       abfd->obj_arch = bfd_arch_a29k;
+       break;
+
+  default:
+       abfd->obj_arch = bfd_arch_obscure;
+       break;
+  }
+
+  bfd_get_start_address (abfd) = execp->a_entry;
+
+  /* Remember the positions of the string table and symbol table.  */
+  obj_str_filepos (abfd) = n_stroff (&anexec);
+  obj_sym_filepos (abfd) = n_symoff (&anexec);
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  obj_aout_symbols(abfd) = (aout_symbol_type *)NULL;
+  (void)bfd_make_section(abfd, ".text");
+  (void)bfd_make_section(abfd, ".data");
+  (void)bfd_make_section(abfd, ".bss");
+
+  obj_datasec (abfd)->size = execp->a_data;
+  obj_bsssec (abfd)->size = execp->a_bss;
+  obj_textsec (abfd)->size = execp->a_text;
+  obj_datasec (abfd)->vma = N_DATADDR(anexec);
+  obj_bsssec (abfd)->vma = N_BSSADDR(anexec);
+  obj_textsec (abfd)->vma = N_TXTADDR(anexec);
+
+  obj_textsec (abfd)->filepos = n_txtoff(&anexec);
+  obj_datasec (abfd)->filepos = n_datoff(&anexec);
+
+  obj_textsec (abfd)->rel_filepos = n_treloff(&anexec);
+  obj_datasec (abfd)->rel_filepos = n_dreloff(&anexec);
+
+  obj_textsec (abfd)->flags =
+    (execp->a_trsize != 0 ?
+                 (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
+                 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
+  obj_datasec (abfd)->flags =
+    (execp->a_drsize != 0 ?
+                               (SEC_ALLOC | SEC_LOAD | SEC_RELOC  | SEC_HAS_CONTENTS) :
+                               (SEC_ALLOC | SEC_LOAD  | SEC_HAS_CONTENTS));
+  obj_bsssec (abfd)->flags = SEC_ALLOC;
+
+  abfd->sections = obj_textsec (abfd);
+  obj_textsec (abfd)->next = obj_datasec (abfd);
+  obj_datasec (abfd)->next = obj_bsssec (abfd);
+  return abfd->xvec;
+}
+
+
+boolean
+sunos4_mkobject (abfd)
+     bfd *abfd;
+{
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  /* Use an intermediate variable for clarity */
+  rawptr =  zalloc (sizeof (struct sunexdata) + sizeof (struct exec));
+
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  abfd->tdata = (void *)((struct sunexdata *) rawptr);
+  exec_hdr (abfd) = (struct exec *) (rawptr + sizeof (struct sunexdata));
+
+  /* For simplicity's sake we just make all the sections right here. */
+
+  obj_textsec (abfd) = (asection *)NULL;
+  obj_datasec (abfd) = (asection *)NULL;
+  obj_bsssec (abfd) = (asection *)NULL;
+  bfd_make_section (abfd, ".text");
+  bfd_make_section (abfd, ".data");
+  bfd_make_section (abfd, ".bss");
+
+  return true;
+}
+
+/* Keep track of machine architecture and machine type for a.out's.
+   Return the machine_type for a particular arch&machine, or M_UNKNOWN
+   if that exact arch&machine can't be represented in a.out format.
+
+   If the architecture is understood, machine type 0 (default) should
+   always be understood.  */
+
+static enum machine_type
+aout_machine_type (arch, machine)
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  enum machine_type arch_flags;
+
+  arch_flags = M_UNKNOWN;
+
+  switch (arch) {
+  case bfd_arch_sparc:
+       if (machine == 0)       arch_flags = M_SPARC;
+       break;
+
+  case bfd_arch_m68k:
+       switch (machine) {
+       case 0:                 arch_flags = M_UNKNOWN; break;
+       case 68000:             arch_flags = M_UNKNOWN; break;
+       case 68010:             arch_flags = M_68010; break;
+       case 68020:             arch_flags = M_68020; break;
+       default:                arch_flags = M_UNKNOWN; break;
+       }
+       break;
+
+  case bfd_arch_i386:
+       if (machine == 0)       arch_flags = M_386;
+       break;
+
+  case bfd_arch_a29k:
+       if (machine == 0)       arch_flags = M_29K;
+       break;
+
+  default:
+       arch_flags = M_UNKNOWN;
+       break;
+  }
+  return arch_flags;
+}
+
+boolean
+sunos4_set_arch_mach (abfd, arch, machine)
+     bfd *abfd;
+     enum bfd_architecture arch;
+     unsigned long machine;
+{
+  abfd->obj_arch = arch;
+  abfd->obj_machine = machine;
+  if (arch != bfd_arch_unknown &&
+      aout_machine_type (arch, machine) == M_UNKNOWN)
+    return false;              /* We can't represent this type */
+  return true;                 /* We're easy ... */
+}
+
+boolean
+sunos4_write_object_contents (abfd)
+     bfd *abfd;
+{
+  int data_pad = 0;
+  struct exec *execp = exec_hdr (abfd);
+
+
+
+  /* Magic number, maestro, please!  */
+  switch (bfd_get_architecture(abfd)) {
+  case bfd_arch_m68k:
+    switch (bfd_get_machine(abfd)) {
+    case 68010:
+      N_SET_MACHTYPE(*execp, M_68010);
+      break;
+    default:
+    case 68020:
+      N_SET_MACHTYPE(*execp, M_68020);
+      break;
+    }
+    break;
+  case bfd_arch_sparc:
+    N_SET_MACHTYPE(*execp, M_SPARC);
+    break;
+  case bfd_arch_i386:
+    N_SET_MACHTYPE(*execp, M_386);
+    break;
+  case bfd_arch_a29k:
+    N_SET_MACHTYPE(*execp, M_29K);
+    break;
+  default:
+    N_SET_MACHTYPE(*execp, M_UNKNOWN);
+  }
+  execp->a_text = obj_textsec (abfd)->size;
+  N_SET_MAGIC (*execp, OMAGIC);
+  if (abfd->flags & D_PAGED) {
+    execp->a_text = obj_textsec (abfd)->size + sizeof(struct exec);
+    N_SET_MAGIC (*execp, ZMAGIC);
+  } else if (abfd->flags & WP_TEXT) {
+    N_SET_MAGIC (*execp, NMAGIC);
+  }
+  N_SET_FLAGS (*execp, 0x1);   /* copied from ld.c; who the hell knows? */
+
+  if (abfd->flags & D_PAGED) 
+    {
+      data_pad = ((obj_datasec(abfd)->size + PAGE_SIZE -1)
+                 & (- PAGE_SIZE)) - obj_datasec(abfd)->size;
+
+      if (data_pad > obj_bsssec(abfd)->size)
+       execp->a_bss = 0;
+      else 
+       execp->a_bss = obj_bsssec(abfd)->size - data_pad;
+      execp->a_data = obj_datasec(abfd)->size + data_pad;
+
+    }
+  else {
+    execp->a_data = obj_datasec (abfd)->size;
+    execp->a_bss = obj_bsssec (abfd)->size;
+  }
+
+  execp->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
+  execp->a_entry = bfd_get_start_address (abfd);
+  execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+                    sizeof (struct reloc_info_extended));
+  execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+                    sizeof (struct reloc_info_extended));;
+
+  swap_exec_header (abfd, execp);
+
+  bfd_seek (abfd, 0L, SEEK_SET);
+  bfd_write ((void *) execp, 1, sizeof (struct exec), abfd);
+
+  /* Now write out reloc info, followed by syms and strings */
+
+  if (bfd_get_symcount (abfd) != 0) 
+    {
+      bfd_seek (abfd,
+               (long)(N_SYMOFF(*execp)), SEEK_SET);
+
+      sunos4_write_syms (abfd);
+
+      bfd_seek (abfd,  (long)(N_TROFF(*execp)), SEEK_SET);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
+      bfd_seek (abfd, (long)(N_DROFF(*execp)), SEEK_SET);
+
+      if (!sunos4_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
+    }
+  return true;
+}
+
+static void
+swap_exec_header (abfd, execp)
+bfd *abfd;
+     struct exec *execp;
+{
+  if (bfd_header_twiddle_required(abfd)) {
+    /* execp->a_info = bfd_h_getlong (abfd, &execp->a_info); */
+    *(unsigned long *) execp =
+                     bfd_h_getlong (abfd, (unsigned long *) execp);
+    execp->a_text   = bfd_h_getlong (abfd, &execp->a_text);
+    execp->a_data   = bfd_h_getlong (abfd, &execp->a_data);
+    execp->a_bss    = bfd_h_getlong (abfd, &execp->a_bss);
+    execp->a_syms   = bfd_h_getlong (abfd, &execp->a_syms);
+    execp->a_entry  = bfd_h_getlong (abfd, &execp->a_entry);
+    execp->a_trsize = bfd_h_getlong (abfd, &execp->a_trsize);
+    execp->a_drsize = bfd_h_getlong (abfd, &execp->a_drsize);
+  }
+} /* swap_exec_header() */
+\f
+/** core files */
+
+#define CORE_MAGIC 0x080456
+#define CORE_NAMELEN 16
+
+/* The core structure is taken from the Sun documentation.
+   Unfortunately, they don't document the FPA structure, or at least I
+   can't find it easily.  Fortunately the core header contains its own
+   length.  So this shouldn't cause problems, except for c_ucode, which
+   so far we don't use but is easy to find with a little arithmetic. */
+
+/* But the reg structure can be gotten from the SPARC processor handbook.
+   This really should be in a GNU include file though so that gdb can use
+   the same info. */
+struct regs {
+  int r_psr;
+  int r_pc;
+  int r_npc;
+  int r_y;
+  int r_g1;
+  int r_g2;
+  int r_g3;
+  int r_g4;
+  int r_g5;
+  int r_g6;
+  int r_g7;
+  int r_o0;
+  int r_o1;
+  int r_o2;
+  int r_o3;
+  int r_o4;
+  int r_o5;
+  int r_o6;
+  int r_o7;
+};
+
+/* Taken from Sun documentation: */
+
+struct core {
+  int c_magic;                 /* Corefile magic number */
+  int c_len;                   /* Sizeof (struct core) */
+  struct regs c_regs;          /* General purpose registers */
+  struct exec c_aouthdr;       /* A.out header */
+  int c_signo;                 /* Killing signal, if any */
+  int c_tsize;                 /* Text size (bytes) */
+  int c_dsize;                 /* Data size (bytes) */
+  int c_ssize;                 /* Stack size (bytes) */
+  char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+  double fp_stuff[1];          /* external FPU state (size unknown by us) */
+                       /* The type "double" is critical here, for alignment.
+                          SunOS declares a struct here, but the struct's
+                          alignment is double since it contains doubles. */
+  int c_ucode;                 /* Exception no. from u_code */
+                       /* (this member not accessible by name since we don't
+                          portably know the size of fp_stuff.) */
+};
+
+/* Supposedly the user stack grows downward from the bottom of kernel memory.
+   Presuming that this remains true, this definition will work. */
+#define USRSTACK (-(128*1024*1024))
+
+PROTO (static void, swapcore, (bfd *abfd, struct core *core));
+
+/* need this cast b/c ptr is really void * */
+#define core_hdr(bfd) (((struct suncordata *) (bfd->tdata))->hdr)
+#define core_datasec(bfd) (((struct suncordata *) ((bfd)->tdata))->data_section)
+#define core_stacksec(bfd) (((struct suncordata*)((bfd)->tdata))->stack_section)
+#define core_regsec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg_section)
+#define core_regsec2(bfd) (((struct suncordata *) ((bfd)->tdata))->reg2_section)
+
+/* These are stored in the bfd's tdata */
+struct suncordata {
+  struct core *hdr;             /* core file header */
+  asection *data_section;
+  asection *stack_section;
+  asection *reg_section;
+  asection *reg2_section;
+};
+
+bfd_target *
+sunos4_core_file_p (abfd)
+     bfd *abfd;
+{
+  /* includes redundent variables for code clarity */
+  int core_size;
+  int core_mag;
+  struct core *core;
+  char *rawptr;
+
+  bfd_error = system_call_error;
+
+  if (bfd_read ((void *)&core_mag, 1, sizeof (int), abfd) != sizeof (int))
+    return 0;
+  core_mag = bfd_h_getlong(abfd, &core_mag);
+
+  if (core_mag != CORE_MAGIC) return 0;
+
+  /* SunOS core headers can vary in length; second word is size; */
+  if (bfd_read ((void *)&core_size, 1, sizeof (int), abfd) != sizeof (int))
+    return 0;
+  core_size = bfd_h_getlong(abfd, &core_size);
+
+  if (bfd_seek (abfd, 0L, SEEK_SET) < 0) return 0;
+
+  rawptr = zalloc (core_size + sizeof (struct suncordata));
+  if (rawptr == NULL) {
+    bfd_error = no_memory;
+    return 0;
+  }
+
+  core = (struct core *) (rawptr + sizeof (struct suncordata));
+
+  if ((bfd_read ((void *) core, 1, core_size, abfd)) != core_size) {
+    bfd_error = system_call_error;
+    free ((void *)rawptr);
+    return 0;
+  }
+
+  swapcore (abfd, core);
+  abfd->tdata = (void *)((struct suncordata *) rawptr);
+  core_hdr (abfd) = core;
+
+  /* create the sections.  This is raunchy, but bfd_close wants to reclaim
+     them */
+  core_stacksec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_stacksec (abfd) == NULL) {
+  loser:
+    bfd_error = no_memory;
+    free ((void *)rawptr);
+    return 0;
+  }
+  core_datasec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_datasec (abfd) == NULL) {
+  loser1:
+    free ((void *)core_stacksec (abfd));
+    goto loser;
+  }
+  core_regsec (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_regsec (abfd) == NULL) {
+  loser2:
+    free ((void *)core_datasec (abfd));
+    goto loser1;
+  }
+  core_regsec2 (abfd) = (asection *) zalloc (sizeof (asection));
+  if (core_regsec2 (abfd) == NULL) {
+    free ((void *)core_regsec (abfd));
+    goto loser2;
+  }
+
+  core_stacksec (abfd)->name = ".stack";
+  core_datasec (abfd)->name = ".data";
+  core_regsec (abfd)->name = ".reg";
+  core_regsec2 (abfd)->name = ".reg2";
+
+  core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
+  core_regsec (abfd)->flags = SEC_ALLOC;
+  core_regsec2 (abfd)->flags = SEC_ALLOC;
+
+  core_stacksec (abfd)->size = core->c_ssize;
+  core_datasec (abfd)->size = core->c_dsize;
+  core_regsec (abfd)->size = (sizeof core->c_regs);
+  /* Float regs take up end of struct, except c_ucode. */
+  core_regsec2 (abfd)->size = core_size - (sizeof core->c_ucode) - 
+                               (file_ptr)(((struct core *)0)->fp_stuff);
+
+  core_stacksec (abfd)->vma = (USRSTACK - core->c_ssize);
+  core_datasec (abfd)->vma = N_DATADDR(core->c_aouthdr);
+  core_regsec (abfd)->vma = -1;
+  core_regsec2 (abfd)->vma = -1;
+
+  core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
+  core_datasec (abfd)->filepos = core->c_len;
+                        /* In file header: */
+  core_regsec (abfd)->filepos = (file_ptr)(&((struct core *)0)->c_regs);
+  core_regsec2 (abfd)->filepos = (file_ptr)(((struct core *)0)->fp_stuff);
+
+  /* Align to word at least */
+  core_stacksec (abfd)->alignment_power = 2;
+  core_datasec (abfd)->alignment_power = 2;
+  core_regsec (abfd)->alignment_power = 2;
+  core_regsec2 (abfd)->alignment_power = 2;
+
+  abfd->sections = core_stacksec (abfd);
+  core_stacksec (abfd)->next = core_datasec (abfd);
+  core_datasec (abfd)->next = core_regsec (abfd);
+  core_regsec (abfd)->next = core_regsec2 (abfd);
+
+  abfd->section_count = 4;
+
+  return abfd->xvec;
+}
+
+char *
+sunos4_core_file_failing_command (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_cmdname;
+}
+
+int
+sunos4_core_file_failing_signal (abfd)
+     bfd *abfd;
+{
+  return core_hdr (abfd)->c_signo;
+}
+
+boolean
+sunos4_core_file_matches_executable_p  (core_bfd, exec_bfd)
+     bfd *core_bfd, *exec_bfd;
+{
+  if (core_bfd->xvec != exec_bfd->xvec) {
+    bfd_error = system_call_error;
+    return false;
+  }
+
+  return (bcmp (&core_hdr (core_bfd), &exec_hdr (exec_bfd),
+                sizeof (struct exec)) == 0) ? true : false;
+}
+
+/* byte-swap core structure */
+static void
+swapcore (abfd, core)
+bfd *abfd;
+     struct core *core;
+{
+  if (bfd_header_twiddle_required(abfd)) {
+    core->c_magic = bfd_h_getlong (abfd, &core->c_magic);
+    core->c_len   = bfd_h_getlong (abfd, &core->c_len);
+    /* regs */
+    swap_exec_header (abfd, &(core->c_aouthdr));
+    core->c_signo = bfd_h_getlong (abfd, &core->c_signo);
+    core->c_tsize = bfd_h_getlong (abfd, &core->c_tsize);
+    core->c_dsize = bfd_h_getlong (abfd, &core->c_dsize);
+    core->c_ssize = bfd_h_getlong (abfd, &core->c_ssize);
+    core->c_ucode = bfd_h_getlong (abfd, &core->c_ucode);
+    /* I don't understand how to swap an FP register */
+  }
+}
+\f
+/** exec and core file sections */
+
+boolean
+sunos4_new_section_hook (abfd, newsect)
+     bfd *abfd;
+     asection *newsect;
+{
+  /* align to double at least */
+  newsect->alignment_power = 3;
+
+  if (bfd_get_format (abfd) == bfd_object) {
+    if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
+      obj_textsec(abfd)= newsect;
+      return true;
+    }
+
+    if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
+      obj_datasec(abfd) = newsect;
+      return true;
+    }
+
+    if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
+      obj_bsssec(abfd) = newsect;
+      return true;
+    }
+  }
+
+#if 0                          /* FIXME -- this is temporary for steve */
+  bfd_error = invalid_operation;
+
+  return false;
+#endif
+
+  /* We allow more than three sections internally */
+  return true;
+}
+
+boolean
+sunos4_set_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     unsigned char *location;
+     file_ptr offset;
+      int count;
+{
+  if (abfd->output_has_begun == false)
+    {                          /* set by bfd.c handler */
+      if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)
+         
+         /*||
+           (obj_textsec (abfd)->size == 0) || (obj_datasec (abfd)->size=
+           0)*/
+         ) 
+       {
+         bfd_error = invalid_operation;
+         return false;
+       }
+
+
+#if 0
+      if (abfd->flags & D_PAGED)
+       {
+         obj_textsec (abfd)->filepos = sizeof(struct exec);
+         obj_datasec(abfd)->filepos =  obj_textsec (abfd)->size;
+       }
+      else 
+#endif
+{
+       obj_textsec (abfd)->filepos = sizeof(struct exec);
+       obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos  + obj_textsec (abfd)->size;
+
+      }
+    }
+  /* regardless, once we know what we're doing, we might as well get going */
+
+  bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+  if (count) {
+    return (bfd_write ((void *)location, 1, count, abfd) == count) ? true : false;
+  }
+  return false;
+}
+boolean
+sunos4_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     sec_ptr section;
+     void  *location;
+     file_ptr offset;
+     int count;
+{
+  if (count) {
+    if (offset >= section->size) return false;
+
+    bfd_seek (abfd, section->filepos + offset, SEEK_SET);
+
+    return (bfd_read (location, 1, count, abfd) == count) ? true:false;
+  }
+  else return true;
+}
+
+\f
+/* Classify stabs symbols */
+
+
+#define sym_in_text_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
+
+#define sym_in_data_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
+
+#define sym_in_bss_section(sym) \
+     (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
+
+/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
+   zero in the "value" field.  Nonzeroes there are fortrancommon
+   symbols.  */
+#define sym_is_undefined(sym) \
+        ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
+
+/* Symbol is a global definition if N_EXT is on and if it has
+   a nonzero type field.  */
+#define sym_is_global_defn(sym) \
+        (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
+
+/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
+   are on.  */
+#define sym_is_debugger_info(sym) \
+        ((sym)->n_type & ~(N_EXT | N_TYPE))
+
+#define sym_is_fortrancommon(sym)       \
+        (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
+
+/* Symbol is absolute if it has N_ABS set */
+#define sym_is_absolute(sym) \
+              (((sym)->n_type  & N_TYPE)== N_ABS)
+
+
+#define sym_is_indirect(sym) \
+              (((sym)->n_type  & N_ABS)== N_ABS)
+
+/* Only in their own functions for ease of debugging; when sym flags have
+   stabilised these should be inlined into their (single) caller */
+
+static void
+translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
+     struct nlist *sym_pointer;
+     aout_symbol_type *cache_ptr;
+     bfd *abfd;
+{
+  switch (cache_ptr->type & N_TYPE) {
+  case N_SETA:
+  case N_SETT:
+  case N_SETD:
+  case N_SETB:
+    {
+      asection *section = bfd_make_section(abfd,
+                                          cache_ptr->symbol.name);
+      arelent_chain *reloc = (arelent_chain *)malloc(sizeof(arelent_chain));
+
+      switch ( (cache_ptr->type  & N_TYPE) ) {
+      case N_SETA:
+       reloc->relent.section =  (asection *)NULL;
+       cache_ptr->symbol.section = (asection *)NULL;
+       break;
+      case N_SETT:
+       reloc->relent.section = (asection *)obj_textsec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETD:
+       reloc->relent.section = (asection *)obj_datasec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      case N_SETB:
+       reloc->relent.section = (asection *)obj_bsssec(abfd);
+       cache_ptr->symbol.value -= reloc->relent.section->vma;
+       break;
+      }
+      cache_ptr->symbol.section = reloc->relent.section;
+      reloc->relent.addend = cache_ptr->symbol.value ;
+      /* 
+        We modify the symbol to belong to a section depending upon the
+        name of the symbol - probably __CTOR__ or __DTOR__ but we don't
+        really care, and add to the size of the section to contain a
+        pointer to the symbol. Build a reloc entry to relocate to this
+        symbol attached to this section.
+        */
+
+
+      section->flags = SEC_CONSTRUCTOR;
+      section->reloc_count++;
+      section->alignment_power = 2;
+      reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
+      reloc->next = section->constructor_chain;
+      section->constructor_chain = reloc;
+      reloc->relent.address = section->size;
+      section->size += sizeof(int *);
+
+      reloc->relent.howto = howto_table +CTOR_TABLE_RELOC_IDX;
+      cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
+      }
+    break;
+  default:
+
+    if (sym_is_debugger_info (sym_pointer)) {
+      cache_ptr->symbol.flags = BSF_DEBUGGING ;
+      /* Work out the section correct for this symbol */
+      switch (sym_pointer->n_type & N_TYPE) 
+       {
+       case N_TEXT:
+       case N_FN:
+         cache_ptr->symbol.section = obj_textsec (abfd);
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         break;
+       case N_DATA:
+         cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+         break;
+       case N_BSS :
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+         break;
+       case N_ABS:
+       default:
+         cache_ptr->symbol.section = 0;
+         break;
+       }
+    }
+    else {
+      if (sym_is_fortrancommon (sym_pointer))
+       {
+         cache_ptr->symbol.flags = BSF_FORT_COMM;
+         cache_ptr->symbol.section = (asection *)NULL;
+       }
+      else {
+       if (sym_is_undefined (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_UNDEFINED;
+       }
+       else if (sym_is_global_defn (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+       }
+
+       else if (sym_is_absolute (sym_pointer)) {
+         cache_ptr->symbol.flags = BSF_ABSOLUTE;
+       }
+       else {
+         cache_ptr->symbol.flags = BSF_LOCAL;
+       }
+
+       /* In a.out, the value of a symbol is always relative to the 
+        * start of the file, if this is a data symbol we'll subtract
+        * the size of the text section to get the section relative
+        * value. If this is a bss symbol (which would be strange)
+        * we'll subtract the size of the previous two sections
+        * to find the section relative address.
+        */
+
+       if (sym_in_text_section (sym_pointer))   {
+         cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
+         cache_ptr->symbol.section = obj_textsec (abfd);
+       }
+       else if (sym_in_data_section (sym_pointer)){
+         cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
+         cache_ptr->symbol.section = obj_datasec (abfd);
+       }
+       else if (sym_in_bss_section(sym_pointer)) {
+         cache_ptr->symbol.section = obj_bsssec (abfd);
+         cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
+       }
+       else {
+         cache_ptr->symbol.section = (asection *)NULL;
+         cache_ptr->symbol.flags |= BSF_ABSOLUTE;
+       }
+      }
+    }
+  }
+}
+void
+translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
+     struct nlist *sym_pointer;
+     generic_symbol_type *cache_ptr_g;
+     bfd *abfd;
+{
+  asymbol *cache_ptr = (asymbol *)cache_ptr_g;
+
+  /* FIXME check for wrigin bss */
+  if (bfd_get_section(cache_ptr)) {
+    if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
+      sym_pointer->n_type |= N_BSS;
+    }
+    else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
+      sym_pointer->n_type |= N_DATA;
+    }
+    else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
+      sym_pointer->n_type |= N_TEXT;
+    }
+    else {
+      BFD_ASSERT(0);
+    }
+    /* Turn the symbol from section relative to absolute again */
+    sym_pointer->n_value +=
+      cache_ptr->section->output_section->vma 
+       + cache_ptr->section->output_offset ;
+  }
+  else {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
+    sym_pointer->n_type = (N_UNDF | N_EXT);
+    return;
+  }
+
+  if (cache_ptr->flags & BSF_ABSOLUTE) {
+    sym_pointer->n_type |= N_ABS;
+  }
+
+  if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
+    sym_pointer->n_type |= N_EXT;
+  }
+  if (cache_ptr->flags & BSF_DEBUGGING) {
+    sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
+  }
+  
+}
+\f
+/* Native-level interface to symbols. */
+
+/* We read the symbols into a buffer, which is discarded when this
+   function exits.  We read the strings into a buffer large enough to
+   hold them all plus all the cached symbol entries. */
+
+asymbol *
+sunos4_make_empty_symbol (abfd)
+bfd *abfd;
+{
+  aout_symbol_type  *new =
+    (aout_symbol_type *)zalloc (sizeof (aout_symbol_type));
+  new->symbol.the_bfd = abfd;
+
+  return &new->symbol;
+}
+
+boolean
+sunos4_slurp_symbol_table (abfd)
+     bfd *abfd;
+{
+  unsigned int symbol_count;
+  size_t symbol_size;
+  size_t string_size;
+  struct nlist *syms;
+  char *strings;
+  aout_symbol_type *cached;
+
+  /* If there's no work to be done, don't do any */
+  if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
+  symbol_size = exec_hdr(abfd)->a_syms;
+  if (symbol_size == 0) {
+    bfd_error = no_symbols;
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)&string_size, 4, 1, abfd) != 4)
+    return false;
+  string_size = bfd_h_getlong (abfd, (unsigned char *)&string_size);
+
+  symbol_count = symbol_size / sizeof (struct nlist);
+
+  /* Malloc (should alloca) space for native symbols, and
+     malloc space for string table and symbol cache. */
+
+  syms = (struct nlist *) zalloc (symbol_size);
+  if (syms == NULL) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  cached = (aout_symbol_type *) zalloc ((size_t)(string_size + 1 +
+                               (symbol_count * sizeof (aout_symbol_type))));
+  if (cached == NULL) {
+    bfd_error = no_memory;
+    free ((void *)syms);
+    return false;
+  }
+
+  strings = ((char *) cached) + (symbol_count * sizeof (aout_symbol_type));
+
+  bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)syms, 1, symbol_size, abfd) != symbol_size) {
+  bailout:
+    free ((void *)cached);
+    free ((void*)syms);
+    return false;
+  }
+
+  bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
+  if (bfd_read ((void *)strings, 1, string_size, abfd) != string_size) {
+    goto bailout;
+  }
+
+  /* OK, now walk the new symtable, cacheing symbol properties */
+  {
+    register struct nlist *sym_pointer;
+    register struct nlist *sym_end = syms + symbol_count;
+    register aout_symbol_type *cache_ptr = cached;
+
+    if (bfd_header_twiddle_required (abfd) == true) {
+      /* run through the table and byte swap if needed */
+      for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
+        sym_pointer->n_un.n_strx =
+         bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
+        sym_pointer->n_desc =
+         bfd_h_get_x (abfd, &sym_pointer->n_desc);
+        sym_pointer->n_value =
+         bfd_h_get_x (abfd, &sym_pointer->n_value);
+       sym_pointer->n_other = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_other);
+       sym_pointer->n_type = (char)
+         bfd_h_get_x(abfd, &sym_pointer->n_type);
+
+      }
+    }
+    /* Run through table and copy values */
+    for (sym_pointer = syms, cache_ptr = cached;
+        sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
+      {
+       cache_ptr->symbol.the_bfd = abfd;
+       if (sym_pointer->n_un.n_strx)
+         cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
+       else
+         cache_ptr->symbol.name = (char *)NULL;
+       cache_ptr->symbol.value = sym_pointer->n_value;
+       cache_ptr->desc = sym_pointer->n_desc;
+       cache_ptr->other = sym_pointer->n_other;
+       cache_ptr->type = sym_pointer->n_type;
+       cache_ptr->symbol.udata = 0;
+       translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
+
+      }
+  }
+
+  obj_aout_symbols (abfd) =  cached;
+  bfd_get_symcount (abfd) = symbol_count;
+  free ((void *)syms);
+
+  return true;
+}
+
+\f
+void
+sunos4_write_syms (abfd)
+     bfd *abfd;
+{
+  unsigned int count ;
+  asymbol **generic = bfd_get_outsymbols (abfd);
+
+  unsigned int stindex = sizeof(stindex); /* initial string length */
+
+  for (count = 0; count < bfd_get_symcount (abfd); count++) {
+    asymbol *g = generic[count];
+    struct nlist nsp;
+
+    if (g->name) {
+      unsigned int length = strlen(g->name) +1;
+      bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
+      stindex += length;
+    }
+    else {
+      bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
+    }
+
+    if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
+      {
+       nsp.n_desc = aout_symbol( g)->desc;
+       nsp.n_other = aout_symbol(g)->other;
+       nsp.n_type = aout_symbol(g)->type;
+      }
+    else
+      {
+       nsp.n_desc = 0;
+       nsp.n_other = 0;
+       nsp.n_type = 0;
+      }
+
+
+    nsp.n_value = g->value;
+    translate_to_native_sym_flags (&nsp, (generic_symbol_type *)g, abfd);
+
+
+    bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
+    bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
+    bfd_write((void *)&nsp,1, sizeof(nsp), abfd);
+  }
+
+
+  /* Now output the strings.  Be sure to put string length into correct
+   * byte ordering before writing it.
+   */
+  bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
+
+  bfd_write((void *)&stindex, 1, sizeof(stindex), abfd);
+  
+  generic = bfd_get_outsymbols(abfd);
+  for (count = 0; count < bfd_get_symcount(abfd); count++) 
+    {
+      asymbol *g = *(generic++);
+
+      if (g->name != (char *)NULL) 
+       {
+         size_t length = strlen(g->name)+1;
+         bfd_write((void *)g->name, 1, length, abfd);
+       }
+      if ((g->flags & BSF_FAKE)==0) {
+       g->name = itos(count);  /* smash the generic symbol */
+      }
+    }
+}
+
+\f
+void
+sunos4_reclaim_symbol_table (abfd)
+     bfd *abfd;
+{
+  asection *section;
+
+  if (!bfd_get_symcount (abfd)) return;
+
+  for (section = abfd->sections;
+       section != (asection *) NULL;
+       section = section->next)
+    if (section->relocation) {
+      free ((void *)section->relocation);
+      section->relocation = NULL;
+      section->reloc_count = 0;
+    }
+
+  bfd_get_symcount (abfd) = 0;
+  free ((void *)obj_aout_symbols (abfd));
+  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+}
+\f
+unsigned int
+sunos4_get_symtab_upper_bound (abfd)
+     bfd *abfd;
+{
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
+}
+
+unsigned int
+sunos4_get_symtab (abfd, location)
+     bfd *abfd;
+     asymbol **location;
+{
+  unsigned int counter = 0;
+  aout_symbol_type *symbase;
+
+  if (!sunos4_slurp_symbol_table (abfd)) return 0;
+
+  for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
+    *(location++) = (asymbol *)( symbase++);
+  *location++ =0;
+  return bfd_get_symcount(abfd);
+}
+
+\f
+/* Obsolete procedural interface; better to look at the cache directly */
+
+/* User should have checked the file flags; perhaps we should return
+   BFD_NO_MORE_SYMBOLS if there are none? */
+
+int
+sunos4_get_symcount_upper_bound (abfd)
+     bfd *abfd;
+{
+  /* In case we're doing an output file or something...?  */
+  if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
+
+  return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
+}
+
+symindex
+sunos4_get_first_symbol (ignore_abfd)
+     bfd * ignore_abfd;
+{
+  return 0;
+}
+
+symindex
+sunos4_get_next_symbol (abfd, oidx)
+     bfd *abfd;
+     symindex oidx;
+{
+  if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
+  return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
+}
+
+char *
+sunos4_symbol_name (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.name;
+}
+
+long
+sunos4_symbol_value (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  return (obj_aout_symbols (abfd) + idx)->symbol.value;
+}
+
+symclass
+sunos4_classify_symbol (abfd, idx)
+     bfd *abfd;
+     symindex idx;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+
+  if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
+  if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
+  if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
+  if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
+
+  return bfd_symclass_unknown;
+}
+
+boolean
+sunos4_symbol_hasclass (abfd, idx, class)
+     bfd *abfd;
+     symindex idx;
+     symclass class;
+{
+  aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
+  switch (class) {
+  case bfd_symclass_fcommon:
+    return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
+  case bfd_symclass_global:
+    return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
+  case bfd_symclass_debugger:
+    return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
+  case bfd_symclass_undefined:
+    return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
+  default: return false;
+  }
+}
+\f
+/** Some reloc hackery */
+
+
+boolean
+sunos4_slurp_reloc_table (abfd, asect, symbols)
+     bfd *abfd;
+     sec_ptr asect;
+     asymbol **symbols;
+{
+  unsigned int count;
+  size_t reloc_size;
+  struct reloc_info_extended *relocs;
+  arelent *reloc_cache;
+
+  if (asect->relocation) return true;
+
+  if (asect->flags & SEC_CONSTRUCTOR) return true;
+
+  if (asect == obj_datasec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_drsize;
+    goto doit;
+  }
+
+  if (asect == obj_textsec (abfd)) {
+    reloc_size = exec_hdr(abfd)->a_trsize;
+    goto doit;
+  }
+
+  bfd_error = invalid_operation;
+  return false;
+
+ doit:
+  bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
+  count = reloc_size / sizeof (struct reloc_info_extended);
+
+  relocs = (struct reloc_info_extended *) malloc (reloc_size);
+  if (!relocs) {
+    bfd_error = no_memory;
+    return false;
+  }
+  reloc_cache = (arelent *) zalloc ((size_t)(count * sizeof (arelent)));
+  if (reloc_cache == (arelent *)NULL) {
+    free ((void *)relocs);
+    bfd_error = no_memory;
+    return false;
+  }
+
+  if (bfd_read ((void*) relocs, 1, reloc_size, abfd) != reloc_size) {
+    bfd_error = system_call_error;
+    free (reloc_cache);
+    free (relocs);
+    return false;
+  }
+
+  {
+    register struct reloc_info_extended *rptr = relocs;
+    unsigned int counter = 0;
+    arelent *cache_ptr = reloc_cache;
+
+    for (; counter < count; counter++, rptr++, cache_ptr++) {
+      /* john's old swap_reloc was a hell of a lot hairier... */
+      /* FIXME, it needs to be!!! */
+      rptr->r_address = bfd_h_getlong (abfd, &rptr->r_address);
+      /* FIXME NOW!
+       *  The following can't be done because r_index is a bit field:
+       *
+       * rptr->r_index   = bfd_h_getlong (abfd, &rptr->r_index);
+       */
+      rptr->r_addend  = bfd_h_getlong (abfd, &rptr->r_addend);
+      if (rptr->r_extern) {
+       /* If this bit is set then the r_index is a index into the symbol table
+        * if the bit is not set then r_index contains a section map.
+        * We either fill in the sym entry with a pointer to the symbol,
+        * or point to the correct section
+        */
+       
+       cache_ptr->sym_ptr_ptr = symbols + rptr->r_index;
+       cache_ptr->addend =  rptr->r_addend;
+       cache_ptr->section = (asection *)NULL;
+      }
+      else 
+       {
+         /* Remember that in a.out symbols are relative to the
+        beginning of the file rather than sections ? (look in
+        translate_from_native_sym_flags) The reloc entry addend
+        has added to it the offset into the  file of the data, so
+        subtract the base to make the reloc section relative */
+
+         cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
+         switch (rptr->r_index) {
+         case N_TEXT:
+         case N_TEXT | N_EXT:
+           cache_ptr->section = obj_textsec(abfd);
+           cache_ptr->addend = rptr->r_addend -  obj_textsec(abfd)->vma  ;
+           break;
+         case N_DATA:
+         case N_DATA | N_EXT:
+           cache_ptr->section = obj_datasec(abfd);
+           cache_ptr->addend = rptr->r_addend -  obj_datasec(abfd)->vma  ;
+           break;
+         case N_BSS:
+         case N_BSS | N_EXT:
+           cache_ptr->section = obj_bsssec(abfd);
+           cache_ptr->addend = rptr->r_addend - obj_bsssec(abfd)->vma;
+           break;
+         case N_ABS:
+         case N_ABS | N_EXT:
+           BFD_ASSERT(1);
+           break;
+         default:
+           BFD_ASSERT(1);
+           break;
+         }
+       
+       }
+
+      cache_ptr->address = rptr->r_address;
+      cache_ptr->howto =  howto_table + (unsigned int)( rptr->r_type);
+    }
+  }
+
+  free (relocs);
+  asect->relocation = reloc_cache;
+  asect->reloc_count = count;
+  return true;
+}
+
+static boolean
+sunos4_squirt_out_relocs (abfd, section)
+     bfd *abfd;
+     asection *section;
+{
+  arelent **generic;
+
+  unsigned int count = section->reloc_count;
+  struct reloc_info_extended *native, *natptr;
+  size_t natsize = count * sizeof (struct reloc_info_extended);
+
+  if (count == 0) return true;
+  generic   = section->orelocation;
+  native = ((struct reloc_info_extended *) zalloc (natsize));
+  if (!native) {
+    bfd_error = no_memory;
+    return false;
+  }
+
+  for (natptr = native; count != 0; --count, ++natptr, ++generic) 
+    {
+      arelent *g = *generic;
+
+      natptr->r_address = g->address;
+      /* Find a type in the output format which matches the input howto - 
+       * at the moment we assume input format == output format FIXME!!
+       */
+      natptr->r_type = (enum reloc_type) g->howto->type;
+      /* name clobbered by sunos4_write_syms to be symbol index*/
+
+      if (g->sym_ptr_ptr != (asymbol **)NULL) 
+       {
+         if ((*(g->sym_ptr_ptr))->section) {
+           /* replace the section offset into the addent */
+           g->addend += (*(g->sym_ptr_ptr))->section->vma;
+         }
+
+         natptr->r_index = stoi((*(g->sym_ptr_ptr))->name);
+       BFD_ASSERT(natptr->r_index < 0xfff);
+         natptr->r_extern = 1;
+         natptr->r_addend = g->addend;
+       }
+      else {
+       natptr->r_extern = 0;
+       if (g->section == (asection *)NULL) {
+         BFD_ASSERT(0);
+         natptr->r_index = N_ABS | N_EXT;
+         natptr->r_addend = g->addend;
+       }
+       else  if(g->section->output_section == obj_textsec(abfd)) {
+         natptr->r_index = N_TEXT | N_EXT;
+         natptr->r_addend = g->addend + obj_textsec(abfd)->vma;
+       }
+       else if (g->section->output_section == obj_datasec(abfd)) {
+         natptr->r_index = N_DATA | N_EXT;
+         natptr->r_addend = g->addend + obj_datasec(abfd)->vma;
+       }
+       else if (g->section->output_section == obj_bsssec(abfd)) {
+         natptr->r_index = N_BSS | N_EXT ;
+         natptr->r_addend = g->addend + obj_bsssec(abfd)->vma;
+
+       }
+       else {
+         BFD_ASSERT(0);
+       }
+      }
+  
+      if ( bfd_header_twiddle_required(abfd) ){
+        bfd_h_putlong ( abfd, natptr->r_address, &natptr->r_address );
+
+        /* FIXME -- NOW!
+        *
+         * I came through here as part of my campaign to make compile-time
+         * definition of host and target byte orders unnecessary. The new
+        * code won't even compile because but r_index is a bit field.
+        * But the simple-minded byte swap that was here before wasn't going
+        * to work on a bit field anyway.
+        *
+         * The old code used to be #ifdef'd on 
+         *             TARGET_BYTE_ORDER_BIG_P != HOST_BYTE_ORDER_BIG_P
+         * Apparently, it was never tested in such a condition: the
+         * macro invocations here (of swapoutlong) had the wrong number
+         * of arguments and would never have compiled.
+         *                     Chris
+        bfd_h_putlong ( abfd, natptr->r_index, &natptr->r_index );
+         */
+
+        bfd_h_putlong ( abfd, natptr->r_addend, &natptr->r_addend );
+      }
+
+    }
+
+  if ( bfd_write ((void *) native, 1, natsize, abfd) != natsize) {
+    free(native);
+    return false;
+  }
+  free (native);
+
+  return true;
+}
+
+/* This is stupid.  This function should be a boolean predicate */
+unsigned int
+sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
+     bfd *abfd;
+     sec_ptr section;
+     arelent **relptr;
+     asymbol **symbols;
+{
+  arelent *tblptr = section->relocation;
+  unsigned int count;
+
+  if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
+    return 0;
+
+  if (section->flags & SEC_CONSTRUCTOR) {
+    arelent_chain *chain = section->constructor_chain;
+    for (count = 0; count < section->reloc_count; count ++) {
+      *relptr ++ = &chain->relent;
+      chain = chain->next;
+    }
+  }
+  else {
+    tblptr = section->relocation;
+    if (!tblptr) return 0;
+
+    for (count = 0; count++ < section->reloc_count;) 
+      {
+       *relptr++ = tblptr++;
+      }
+  }
+  *relptr = 0;
+
+  return section->reloc_count;
+}
+
+unsigned int
+sunos4_get_reloc_upper_bound (abfd, asect)
+     bfd *abfd;
+     sec_ptr asect;
+{
+  if (bfd_get_format (abfd) != bfd_object) {
+    bfd_error = invalid_operation;
+    return 0;
+  }
+  if (asect->flags & SEC_CONSTRUCTOR) {
+    return (sizeof (arelent *) * (asect->reloc_count+1));
+  }
+
+  if (asect == obj_datasec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_drsize / sizeof (struct reloc_info_extended))
+             +1));
+
+  if (asect == obj_textsec (abfd))
+    return (sizeof (arelent *) *
+            ((exec_hdr(abfd)->a_trsize / sizeof (struct reloc_info_extended))
+             +1));
+
+  bfd_error = invalid_operation;
+  return 0;
+}
+
+void
+sunos4_reclaim_reloc (ignore_abfd, section)
+     bfd *ignore_abfd;
+     sec_ptr section;
+{
+  if (section->relocation) {
+    free (section->relocation);
+    section->relocation = NULL;
+    section->reloc_count = 0;
+    }
+}
+\f
+
+alent *
+sunos4_get_lineno(ignore_abfd, ignore_symbol)
+bfd *ignore_abfd;
+generic_symbol_type *ignore_symbol;
+{
+return (alent *)NULL;
+}
+
+void 
+sunos4_print_symbol(ignore_abfd, file,  symbol, how)
+bfd *ignore_abfd;
+FILE *file;
+asymbol *symbol;
+bfd_print_symbol_enum_type how;
+{
+  switch (how) {
+  case bfd_print_symbol_name_enum:
+    fprintf(file,"%s", symbol->name);
+    break;
+  case bfd_print_symbol_type_enum:
+    fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
+           (unsigned)(   aout_symbol(symbol)->other  & 0xff),
+           (unsigned)(aout_symbol(symbol)->type));
+    break;
+  case bfd_print_symbol_all_enum:
+    {
+      char *section_name = symbol->section == (asection *)NULL ?
+       "*abs" : symbol->section->name;
+
+      bfd_print_symbol_vandf((void *)file,symbol);
+
+      fprintf(file," %-5s %04x %02x %02x %s",
+             section_name,
+             (unsigned)(aout_symbol(symbol)->desc & 0xffff),
+             (unsigned)(aout_symbol(symbol)->other  & 0xff),
+             (unsigned)(aout_symbol(symbol)->type  & 0xff),
+             symbol->name);
+    }
+    break;
+  }
+}
+/* Once we know all the stuff that could be consed, we know how to clean
+   it up.  So why don't we? */
+
+boolean
+sunos4_close_and_cleanup (abfd)
+     bfd *abfd;
+{
+  if (!bfd_read_p (abfd))
+    switch (abfd->format) {
+    case bfd_archive:
+      if (!_bfd_write_archive_contents (abfd)) return false; break;
+    case bfd_object:
+      if (!sunos4_write_object_contents (abfd))  return false; break;
+    default: bfd_error = invalid_operation; return false;
+    }
+
+#define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
+  cleaner (tdata);
+
+  if (abfd->my_archive)
+    cleaner (filename);
+
+#undef cleaner
+  return true;
+}
+
+/* 
+ provided a bfd, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location.
+*/
+boolean
+sunos4_find_nearest_line(abfd,
+                        section,
+                        symbols,
+                        offset,
+                        filename_ptr,
+                        functionname_ptr,
+                        line_ptr)
+bfd *abfd;
+asection *section;
+asymbol **symbols;
+bfd_vma offset;
+char **filename_ptr;
+char **functionname_ptr;
+unsigned int *line_ptr;
+{
+  /* Run down the file looking for the filename, function and linenumber */
+  asymbol **p;
+  static  char buffer[100];
+  bfd_vma high_line_vma = ~0;
+  bfd_vma low_func_vma = 0;
+  asymbol *func = 0;
+  *filename_ptr = abfd->filename;
+  *functionname_ptr = 0;
+  *line_ptr = 0;
+  if (symbols != (asymbol **)NULL) {
+    for (p = symbols; *p; p++) {
+      aout_symbol_type  *q = (aout_symbol_type *)(*p);
+      switch (q->type){
+      case N_SO:
+       *filename_ptr = q->symbol.name;
+       if (obj_textsec(abfd) != section) {
+         return true;
+       }
+       break;
+      case N_SLINE:
+
+      case N_DSLINE:
+      case N_BSLINE:
+       /* We'll keep this if it resolves nearer than the one we have already */
+       if (q->symbol.value >= offset &&
+           q->symbol.value < high_line_vma) {
+         *line_ptr = q->desc;
+         high_line_vma = q->symbol.value;
+       }
+       break;
+      case N_FUN:
+       {
+         /* We'll keep this if it is nearer than the one we have already */
+         if (q->symbol.value >= low_func_vma &&
+             q->symbol.value <= offset) {
+           low_func_vma = q->symbol.value;
+           func = (asymbol *)q;
+         }
+         if (*line_ptr && func) {
+           char *function = func->name;
+           char *p;
+           strncpy(buffer, function, sizeof(buffer)-1);
+           buffer[sizeof(buffer)-1] = 0;
+           /* Have to remove : stuff */
+           p = strchr(buffer,':');
+           if (p != NULL) {*p = NULL; }
+           *functionname_ptr = buffer;
+           return true;
+
+         }
+       }
+       break;
+      }
+    }
+  }
+  
+  return true;
+
+}
+
+bfd_target aoutvec =
+{
+  "a.out-generic-big",         /* name */
+  bfd_target_aout_flavour_enum,
+  true,                                /* target byte order */
+  true,                                /* target headers byte order */
+  (HAS_RELOC | EXEC_P |                /* object flags */
+   HAS_LINENO | HAS_DEBUG |
+   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+  0,                           /* valid reloc types */
+  ' ',                         /* ar_pad_char */
+  16,                          /* ar_max_namelen */
+  sunos4_close_and_cleanup,    /* _close_and_cleanup */
+  sunos4_set_section_contents, /* bfd_set_section_contents */
+  sunos4_get_section_contents, /* bfd_get_section_contents */
+  sunos4_new_section_hook,     /* new_section_hook */
+  sunos4_core_file_failing_command, /* _core_file_failing_command */
+  sunos4_core_file_failing_signal, /* _core_file_failing_signal */
+  sunos4_core_file_matches_executable_p, /* _core_file_matches_ex...p */
+
+  bfd_slurp_bsd_armap,         /* bfd_slurp_armap */
+  bfd_true,                    /* bfd_slurp_extended_name_table */
+  bfd_bsd_truncate_arname,     /* bfd_truncate_arname */
+
+  sunos4_get_symtab_upper_bound, /* get_symtab_upper_bound */
+  sunos4_get_symtab,           /* canonicalize_symtab */
+  sunos4_reclaim_symbol_table, /* bfd_reclaim_symbol_table */
+  sunos4_get_reloc_upper_bound,        /* get_reloc_upper_bound */
+  sunos4_canonicalize_reloc,   /* bfd_canonicalize_reloc */
+  sunos4_reclaim_reloc,                /* bfd_reclaim_reloc */
+  sunos4_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
+  sunos4_get_first_symbol,     /* bfd_get_first_symbol */
+  sunos4_get_next_symbol,      /* bfd_get_next_symbol */
+  sunos4_classify_symbol,      /* bfd_classify_symbol */
+  sunos4_symbol_hasclass,      /* bfd_symbol_hasclass */
+  sunos4_symbol_name,          /* bfd_symbol_name */
+  sunos4_symbol_value,         /* bfd_symbol_value */
+
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
+  _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
+
+  {_bfd_dummy_target, sunos4_object_p, /* bfd_check_format */
+     bfd_generic_archive_p, sunos4_core_file_p},
+  {bfd_false, sunos4_mkobject, /* bfd_zxset_format */
+     _bfd_generic_mkarchive, bfd_false},
+  sunos4_make_empty_symbol,
+  sunos4_print_symbol,
+  sunos4_get_lineno,
+  sunos4_set_arch_mach,
+  bsd_write_armap,
+  bfd_generic_openr_next_archived_file,
+  sunos4_find_nearest_line,    /* bfd_find_nearest_line */
+  bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
+  };
+
diff --git a/bfd/targets.c b/bfd/targets.c
new file mode 100644 (file)
index 0000000..77fabb6
--- /dev/null
@@ -0,0 +1,50 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD 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 1, or (at your option)
+any later version.
+
+BFD 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 BFD; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* $Id$ */
+
+
+/* This -*- C -*- source file will someday be machine-generated */
+
+/*** Defines the target vector through which operations dispatch */
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+extern bfd_target aoutvec;
+extern bfd_target srec_vec;
+extern bfd_target b_out_vec_little_host;
+extern bfd_target b_out_vec_big_host;
+extern bfd_target icoff_little_vec;
+extern bfd_target icoff_big_vec;
+
+
+bfd_target *target_vector[] = 
+  {
+#ifndef INTEL960VERSION
+    &aoutvec,
+    &srec_vec,
+
+#endif /* INTEL960VERSION */
+    &icoff_big_vec,
+    &icoff_little_vec,
+    &b_out_vec_big_host,
+    &b_out_vec_little_host,
+
+    NULL
+    };