aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:11:25 +0000
committerDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:11:25 +0000
commit4a81b56152631cda9dc351cb4d2f61f395ee4414 (patch)
tree562bc9b14bcf414b6c301b769d4ce528c51d4703 /bfd
parent907621824e31daf6504860009535f03676afee4d (diff)
downloadgdb-4a81b56152631cda9dc351cb4d2f61f395ee4414.zip
gdb-4a81b56152631cda9dc351cb4d2f61f395ee4414.tar.gz
gdb-4a81b56152631cda9dc351cb4d2f61f395ee4414.tar.bz2
Initial revision
Diffstat (limited to 'bfd')
-rw-r--r--bfd/COPYING249
-rw-r--r--bfd/ChangeLog314
-rwxr-xr-xbfd/Makefile158
-rw-r--r--bfd/TODO49
-rwxr-xr-xbfd/aout.c1904
-rw-r--r--bfd/archive.c1223
-rw-r--r--bfd/archures.c368
-rwxr-xr-xbfd/archures.h41
-rw-r--r--bfd/bfd.c882
-rw-r--r--bfd/cache.c200
-rwxr-xr-xbfd/coff-code.h2561
-rw-r--r--bfd/coff-i960.c270
-rw-r--r--bfd/libaout.h80
-rw-r--r--bfd/libbfd.c332
-rw-r--r--bfd/libbfd.h160
-rw-r--r--bfd/libcoff.h62
-rwxr-xr-xbfd/misc.c98
-rwxr-xr-xbfd/misc.h93
-rw-r--r--bfd/opncls.c281
-rw-r--r--bfd/srec.c464
-rw-r--r--bfd/sunos.c1904
-rw-r--r--bfd/targets.c50
22 files changed, 11743 insertions, 0 deletions
diff --git a/bfd/COPYING b/bfd/COPYING
new file mode 100644
index 0000000..9a17037
--- /dev/null
+++ b/bfd/COPYING
@@ -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.
+
+ 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.
+
+ 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.
+
+ 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
+
+ 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
index 0000000..e9d10f6
--- /dev/null
+++ b/bfd/ChangeLog
@@ -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
index 0000000..54dfd90
--- /dev/null
+++ b/bfd/Makefile
@@ -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 'Specify "make make HOST=???"'; \
+ exit 1; \
+ fi ; \
+ grep -s "^#The next line was generated by 'make make'" Makefile; \
+ if test $$? = 0 ; then \
+ echo "Makefile has already been processed with 'make make'";\
+ exit 1; \
+ fi ; \
+ mv -f Makefile Makefile.old; \
+ echo "#The next line was generated by 'make make'" >Makefile ; \
+ echo "HOST=$(HOST)" >>Makefile ; \
+ echo >>Makefile ; \
+ sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile
+
+Makefile: ../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
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.
+
+
+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
index 0000000..f857897
--- /dev/null
+++ b/bfd/aout.c
@@ -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() */
+
+/** 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 */
+ }
+}
+
+/** 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;
+}
+
+
+/* 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;
+ }
+
+}
+
+/* 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;
+}
+
+
+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 */
+ }
+ }
+}
+
+
+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;
+}
+
+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);
+}
+
+
+/* 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;
+ }
+}
+
+/** 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;
+ }
+}
+
+
+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
index 0000000..53cd0bd
--- /dev/null
+++ b/bfd/archive.c
@@ -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))
+
+
+
+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;
+}
+
+
+
+/* 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;
+}
+
+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);
+}
+
+
+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;
+}
+
+
+/** 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;
+}
+
+/** 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);
+}
+
+
+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;
+}
+
+/* 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;
+}
+
+
+ /* 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;
+}
+
+
+/* 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
index 0000000..b7fdaf9
--- /dev/null
+++ b/bfd/archures.c
@@ -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;
+}
+
+/* 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;
+}
+
+
+
+/* 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
index 0000000..b1f5594
--- /dev/null
+++ b/bfd/archures.h
@@ -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
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.)
+ */
+
+
+
+
+/** 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";
+ }
+}
+
+/** 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;
+}
+
+/** 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;
+}
+
+/* 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)));
+ }
+}
+
+
+/** 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));
+}
+
+/** 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
index 0000000..39ffc7a
--- /dev/null
+++ b/bfd/cache.c
@@ -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;
+
+
+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;
+}
+
+
+/* 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);
+ }
+}
+
+/* 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
index 0000000..8ec6ec2
--- /dev/null
+++ b/bfd/coff-code.h
@@ -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
index 0000000..3b8e0d6
--- /dev/null
+++ b/bfd/coff-i960.c
@@ -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
index 0000000..febe2f4
--- /dev/null
+++ b/bfd/libaout.h
@@ -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
index 0000000..9998690
--- /dev/null
+++ b/bfd/libbfd.c
@@ -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"
+
+
+
+/** 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;
+}
+
+/** 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
+
+/* 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;
+}
+
+/** 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;
+}
+
+/** 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
index 0000000..790d957
--- /dev/null
+++ b/bfd/libbfd.h
@@ -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
index 0000000..46f5a78
--- /dev/null
+++ b/bfd/libcoff.h
@@ -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
index 0000000..041fcde
--- /dev/null
+++ b/bfd/misc.c
@@ -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);
+}
+
+/* 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
index 0000000..05935c2
--- /dev/null
+++ b/bfd/misc.h
@@ -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
index 0000000..63e9c51
--- /dev/null
+++ b/bfd/opncls.c
@@ -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. */
+
+/** 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?... */
+
+
+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;
+}
+
+/** 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;
+}
+
+
+
+/** 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
index 0000000..3ac8e59
--- /dev/null
+++ b/bfd/srec.c
@@ -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
index 0000000..f857897
--- /dev/null
+++ b/bfd/sunos.c
@@ -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() */
+
+/** 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 */
+ }
+}
+
+/** 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;
+}
+
+
+/* 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;
+ }
+
+}
+
+/* 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;
+}
+
+
+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 */
+ }
+ }
+}
+
+
+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;
+}
+
+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);
+}
+
+
+/* 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;
+ }
+}
+
+/** 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;
+ }
+}
+
+
+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
index 0000000..77fabb6
--- /dev/null
+++ b/bfd/targets.c
@@ -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
+ };