Back to index

cell-binutils  2.17cvs20070401
aoutx.h
Go to the documentation of this file.
00001 /* BFD semi-generic back-end for a.out binaries.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2004, 2005, 2006
00004    Free Software Foundation, Inc.
00005    Written by Cygnus Support.
00006 
00007    This file is part of BFD, the Binary File Descriptor library.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 /*
00024 SECTION
00025        a.out backends
00026 
00027 DESCRIPTION
00028 
00029        BFD supports a number of different flavours of a.out format,
00030        though the major differences are only the sizes of the
00031        structures on disk, and the shape of the relocation
00032        information.
00033 
00034        The support is split into a basic support file @file{aoutx.h}
00035        and other files which derive functions from the base. One
00036        derivation file is @file{aoutf1.h} (for a.out flavour 1), and
00037        adds to the basic a.out functions support for sun3, sun4, 386
00038        and 29k a.out files, to create a target jump vector for a
00039        specific target.
00040 
00041        This information is further split out into more specific files
00042        for each machine, including @file{sunos.c} for sun3 and sun4,
00043        @file{newsos3.c} for the Sony NEWS, and @file{demo64.c} for a
00044        demonstration of a 64 bit a.out format.
00045 
00046        The base file @file{aoutx.h} defines general mechanisms for
00047        reading and writing records to and from disk and various
00048        other methods which BFD requires. It is included by
00049        @file{aout32.c} and @file{aout64.c} to form the names
00050        <<aout_32_swap_exec_header_in>>, <<aout_64_swap_exec_header_in>>, etc.
00051 
00052        As an example, this is what goes on to make the back end for a
00053        sun4, from @file{aout32.c}:
00054 
00055 |      #define ARCH_SIZE 32
00056 |      #include "aoutx.h"
00057 
00058        Which exports names:
00059 
00060 |      ...
00061 |      aout_32_canonicalize_reloc
00062 |      aout_32_find_nearest_line
00063 |      aout_32_get_lineno
00064 |      aout_32_get_reloc_upper_bound
00065 |      ...
00066 
00067        from @file{sunos.c}:
00068 
00069 |      #define TARGET_NAME "a.out-sunos-big"
00070 |      #define VECNAME    sunos_big_vec
00071 |      #include "aoutf1.h"
00072 
00073        requires all the names from @file{aout32.c}, and produces the jump vector
00074 
00075 |      sunos_big_vec
00076 
00077        The file @file{host-aout.c} is a special case.  It is for a large set
00078        of hosts that use ``more or less standard'' a.out files, and
00079        for which cross-debugging is not interesting.  It uses the
00080        standard 32-bit a.out support routines, but determines the
00081        file offsets and addresses of the text, data, and BSS
00082        sections, the machine architecture and machine type, and the
00083        entry point address, in a host-dependent manner.  Once these
00084        values have been determined, generic code is used to handle
00085        the  object file.
00086 
00087        When porting it to run on a new system, you must supply:
00088 
00089 |        HOST_PAGE_SIZE
00090 |        HOST_SEGMENT_SIZE
00091 |        HOST_MACHINE_ARCH       (optional)
00092 |        HOST_MACHINE_MACHINE    (optional)
00093 |        HOST_TEXT_START_ADDR
00094 |        HOST_STACK_END_ADDR
00095 
00096        in the file @file{../include/sys/h-@var{XXX}.h} (for your host).  These
00097        values, plus the structures and macros defined in @file{a.out.h} on
00098        your host system, will produce a BFD target that will access
00099        ordinary a.out files on your host. To configure a new machine
00100        to use @file{host-aout.c}, specify:
00101 
00102 |      TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
00103 |      TDEPFILES= host-aout.o trad-core.o
00104 
00105        in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in}
00106        to use the
00107        @file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your
00108        configuration is selected.  */
00109 
00110 /* Some assumptions:
00111    * Any BFD with D_PAGED set is ZMAGIC, and vice versa.
00112      Doesn't matter what the setting of WP_TEXT is on output, but it'll
00113      get set on input.
00114    * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC.
00115    * Any BFD with both flags clear is OMAGIC.
00116    (Just want to make these explicit, so the conditions tested in this
00117    file make sense if you're more familiar with a.out than with BFD.)  */
00118 
00119 #define KEEPIT udata.i
00120 
00121 #include "bfd.h"
00122 #include "sysdep.h"
00123 #include "safe-ctype.h"
00124 #include "bfdlink.h"
00125 
00126 #include "libaout.h"
00127 #include "libbfd.h"
00128 #include "aout/aout64.h"
00129 #include "aout/stab_gnu.h"
00130 #include "aout/ar.h"
00131 
00132 /*
00133 SUBSECTION
00134        Relocations
00135 
00136 DESCRIPTION
00137        The file @file{aoutx.h} provides for both the @emph{standard}
00138        and @emph{extended} forms of a.out relocation records.
00139 
00140        The standard records contain only an
00141        address, a symbol index, and a type field. The extended records
00142        (used on 29ks and sparcs) also have a full integer for an
00143        addend.  */
00144 
00145 #ifndef CTOR_TABLE_RELOC_HOWTO
00146 #define CTOR_TABLE_RELOC_IDX 2
00147 #define CTOR_TABLE_RELOC_HOWTO(BFD)                                   \
00148   ((obj_reloc_entry_size (BFD) == RELOC_EXT_SIZE               \
00149     ? howto_table_ext : howto_table_std)                       \
00150    + CTOR_TABLE_RELOC_IDX)
00151 #endif
00152 
00153 #ifndef MY_swap_std_reloc_in
00154 #define MY_swap_std_reloc_in NAME (aout, swap_std_reloc_in)
00155 #endif
00156 
00157 #ifndef MY_swap_ext_reloc_in
00158 #define MY_swap_ext_reloc_in NAME (aout, swap_ext_reloc_in)
00159 #endif
00160 
00161 #ifndef MY_swap_std_reloc_out
00162 #define MY_swap_std_reloc_out NAME (aout, swap_std_reloc_out)
00163 #endif
00164 
00165 #ifndef MY_swap_ext_reloc_out
00166 #define MY_swap_ext_reloc_out NAME (aout, swap_ext_reloc_out)
00167 #endif
00168 
00169 #ifndef MY_final_link_relocate
00170 #define MY_final_link_relocate _bfd_final_link_relocate
00171 #endif
00172 
00173 #ifndef MY_relocate_contents
00174 #define MY_relocate_contents _bfd_relocate_contents
00175 #endif
00176 
00177 #define howto_table_ext NAME (aout, ext_howto_table)
00178 #define howto_table_std NAME (aout, std_howto_table)
00179 
00180 reloc_howto_type howto_table_ext[] =
00181 {
00182   /*     Type         rs   size bsz  pcrel bitpos ovrf                  sf name          part_inpl readmask setmask pcdone.  */
00183   HOWTO (RELOC_8,       0,  0,  8,  FALSE, 0, complain_overflow_bitfield, 0, "8",           FALSE, 0, 0x000000ff, FALSE),
00184   HOWTO (RELOC_16,      0,  1,     16, FALSE, 0, complain_overflow_bitfield, 0, "16",          FALSE, 0, 0x0000ffff, FALSE),
00185   HOWTO (RELOC_32,      0,  2,     32, FALSE, 0, complain_overflow_bitfield, 0, "32",          FALSE, 0, 0xffffffff, FALSE),
00186   HOWTO (RELOC_DISP8,   0,  0,     8,  TRUE,  0, complain_overflow_signed,   0, "DISP8",       FALSE, 0, 0x000000ff, FALSE),
00187   HOWTO (RELOC_DISP16,  0,  1,     16, TRUE,  0, complain_overflow_signed,   0, "DISP16",      FALSE, 0, 0x0000ffff, FALSE),
00188   HOWTO (RELOC_DISP32,  0,  2,     32, TRUE,  0, complain_overflow_signed,   0, "DISP32",      FALSE, 0, 0xffffffff, FALSE),
00189   HOWTO (RELOC_WDISP30, 2,  2,     30, TRUE,  0, complain_overflow_signed,   0, "WDISP30",     FALSE, 0, 0x3fffffff, FALSE),
00190   HOWTO (RELOC_WDISP22, 2,  2,     22, TRUE,  0, complain_overflow_signed,   0, "WDISP22",     FALSE, 0, 0x003fffff, FALSE),
00191   HOWTO (RELOC_HI22,   10,  2,     22, FALSE, 0, complain_overflow_bitfield, 0, "HI22",        FALSE, 0, 0x003fffff, FALSE),
00192   HOWTO (RELOC_22,      0,  2,     22, FALSE, 0, complain_overflow_bitfield, 0, "22",          FALSE, 0, 0x003fffff, FALSE),
00193   HOWTO (RELOC_13,      0,  2,     13, FALSE, 0, complain_overflow_bitfield, 0, "13",          FALSE, 0, 0x00001fff, FALSE),
00194   HOWTO (RELOC_LO10,    0,  2,     10, FALSE, 0, complain_overflow_dont,     0, "LO10",        FALSE, 0, 0x000003ff, FALSE),
00195   HOWTO (RELOC_SFA_BASE,0,  2,     32, FALSE, 0, complain_overflow_bitfield, 0, "SFA_BASE",    FALSE, 0, 0xffffffff, FALSE),
00196   HOWTO (RELOC_SFA_OFF13,0, 2,     32, FALSE, 0, complain_overflow_bitfield, 0, "SFA_OFF13",   FALSE, 0, 0xffffffff, FALSE),
00197   HOWTO (RELOC_BASE10,  0,  2,     10, FALSE, 0, complain_overflow_dont,     0, "BASE10",      FALSE, 0, 0x000003ff, FALSE),
00198   HOWTO (RELOC_BASE13,  0,  2,     13, FALSE, 0, complain_overflow_signed,   0, "BASE13",      FALSE, 0, 0x00001fff, FALSE),
00199   HOWTO (RELOC_BASE22, 10,  2,     22, FALSE, 0, complain_overflow_bitfield, 0, "BASE22",      FALSE, 0, 0x003fffff, FALSE),
00200   HOWTO (RELOC_PC10,    0,  2,     10, TRUE,  0, complain_overflow_dont,     0, "PC10",        FALSE, 0, 0x000003ff, TRUE),
00201   HOWTO (RELOC_PC22,   10,  2,     22, TRUE,  0, complain_overflow_signed,   0, "PC22",        FALSE, 0, 0x003fffff, TRUE),
00202   HOWTO (RELOC_JMP_TBL, 2,  2,     30, TRUE,  0, complain_overflow_signed,   0, "JMP_TBL",     FALSE, 0, 0x3fffffff, FALSE),
00203   HOWTO (RELOC_SEGOFF16,0,  2,     0,  FALSE, 0, complain_overflow_bitfield, 0, "SEGOFF16",    FALSE, 0, 0x00000000, FALSE),
00204   HOWTO (RELOC_GLOB_DAT,0,  2,     0,  FALSE, 0, complain_overflow_bitfield, 0, "GLOB_DAT",    FALSE, 0, 0x00000000, FALSE),
00205   HOWTO (RELOC_JMP_SLOT,0,  2,     0,  FALSE, 0, complain_overflow_bitfield, 0, "JMP_SLOT",    FALSE, 0, 0x00000000, FALSE),
00206   HOWTO (RELOC_RELATIVE,0,  2,     0,  FALSE, 0, complain_overflow_bitfield, 0, "RELATIVE",    FALSE, 0, 0x00000000, FALSE),
00207   HOWTO (0,             0,  0,  0,  FALSE, 0, complain_overflow_dont,     0, "R_SPARC_NONE",FALSE, 0, 0x00000000, TRUE),
00208   HOWTO (0,             0,  0,  0,  FALSE, 0, complain_overflow_dont,     0, "R_SPARC_NONE",FALSE, 0, 0x00000000, TRUE),
00209 #define RELOC_SPARC_REV32 RELOC_WDISP19
00210   HOWTO (RELOC_SPARC_REV32, 0, 2, 32, FALSE, 0, complain_overflow_dont,   0,"R_SPARC_REV32",FALSE, 0, 0xffffffff, FALSE),
00211 };
00212 
00213 /* Convert standard reloc records to "arelent" format (incl byte swap).  */
00214 
00215 reloc_howto_type howto_table_std[] =
00216 {
00217   /* type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone.  */
00218 HOWTO ( 0,           0,  0,        8,  FALSE, 0, complain_overflow_bitfield,0,"8",         TRUE, 0x000000ff,0x000000ff, FALSE),
00219 HOWTO ( 1,           0,  1,        16, FALSE, 0, complain_overflow_bitfield,0,"16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
00220 HOWTO ( 2,           0,  2,        32, FALSE, 0, complain_overflow_bitfield,0,"32", TRUE, 0xffffffff,0xffffffff, FALSE),
00221 HOWTO ( 3,           0,  4,        64, FALSE, 0, complain_overflow_bitfield,0,"64", TRUE, 0xdeaddead,0xdeaddead, FALSE),
00222 HOWTO ( 4,           0,  0,        8,  TRUE,  0, complain_overflow_signed,  0,"DISP8",     TRUE, 0x000000ff,0x000000ff, FALSE),
00223 HOWTO ( 5,           0,  1,        16, TRUE,  0, complain_overflow_signed,  0,"DISP16",    TRUE, 0x0000ffff,0x0000ffff, FALSE),
00224 HOWTO ( 6,           0,  2,        32, TRUE,  0, complain_overflow_signed,  0,"DISP32",    TRUE, 0xffffffff,0xffffffff, FALSE),
00225 HOWTO ( 7,           0,  4,        64, TRUE,  0, complain_overflow_signed,  0,"DISP64",    TRUE, 0xfeedface,0xfeedface, FALSE),
00226 HOWTO ( 8,           0,  2,    0, FALSE, 0, complain_overflow_bitfield,0,"GOT_REL", FALSE,         0,0x00000000, FALSE),
00227 HOWTO ( 9,           0,  1,   16, FALSE, 0, complain_overflow_bitfield,0,"BASE16",  FALSE,0xffffffff,0xffffffff, FALSE),
00228 HOWTO (10,           0,  2,   32, FALSE, 0, complain_overflow_bitfield,0,"BASE32",  FALSE,0xffffffff,0xffffffff, FALSE),
00229 EMPTY_HOWTO (-1),
00230 EMPTY_HOWTO (-1),
00231 EMPTY_HOWTO (-1),
00232 EMPTY_HOWTO (-1),
00233 EMPTY_HOWTO (-1),
00234   HOWTO (16,         0,  2,  0, FALSE, 0, complain_overflow_bitfield,0,"JMP_TABLE", FALSE,         0,0x00000000, FALSE),
00235 EMPTY_HOWTO (-1),
00236 EMPTY_HOWTO (-1),
00237 EMPTY_HOWTO (-1),
00238 EMPTY_HOWTO (-1),
00239 EMPTY_HOWTO (-1),
00240 EMPTY_HOWTO (-1),
00241 EMPTY_HOWTO (-1),
00242 EMPTY_HOWTO (-1),
00243 EMPTY_HOWTO (-1),
00244 EMPTY_HOWTO (-1),
00245 EMPTY_HOWTO (-1),
00246 EMPTY_HOWTO (-1),
00247 EMPTY_HOWTO (-1),
00248 EMPTY_HOWTO (-1),
00249 EMPTY_HOWTO (-1),
00250   HOWTO (32,         0,  2,  0, FALSE, 0, complain_overflow_bitfield,0,"RELATIVE",  FALSE,         0,0x00000000, FALSE),
00251 EMPTY_HOWTO (-1),
00252 EMPTY_HOWTO (-1),
00253 EMPTY_HOWTO (-1),
00254 EMPTY_HOWTO (-1),
00255 EMPTY_HOWTO (-1),
00256 EMPTY_HOWTO (-1),
00257 EMPTY_HOWTO (-1),
00258   HOWTO (40,         0,  2,  0, FALSE, 0, complain_overflow_bitfield,0,"BASEREL",   FALSE,         0,0x00000000, FALSE),
00259 };
00260 
00261 #define TABLE_SIZE(TABLE)   (sizeof (TABLE) / sizeof (TABLE[0]))
00262 
00263 reloc_howto_type *
00264 NAME (aout, reloc_type_lookup) (bfd *abfd, bfd_reloc_code_real_type code)
00265 {
00266 #define EXT(i, j)    case i: return & howto_table_ext [j]
00267 #define STD(i, j)    case i: return & howto_table_std [j]
00268   int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
00269 
00270   if (code == BFD_RELOC_CTOR)
00271     switch (bfd_get_arch_info (abfd)->bits_per_address)
00272       {
00273       case 32:
00274        code = BFD_RELOC_32;
00275        break;
00276       case 64:
00277        code = BFD_RELOC_64;
00278        break;
00279       }
00280 
00281   if (ext)
00282     switch (code)
00283       {
00284        EXT (BFD_RELOC_8, 0);
00285        EXT (BFD_RELOC_16, 1);
00286        EXT (BFD_RELOC_32, 2);
00287        EXT (BFD_RELOC_HI22, 8);
00288        EXT (BFD_RELOC_LO10, 11);
00289        EXT (BFD_RELOC_32_PCREL_S2, 6);
00290        EXT (BFD_RELOC_SPARC_WDISP22, 7);
00291        EXT (BFD_RELOC_SPARC13, 10);
00292        EXT (BFD_RELOC_SPARC_GOT10, 14);
00293        EXT (BFD_RELOC_SPARC_BASE13, 15);
00294        EXT (BFD_RELOC_SPARC_GOT13, 15);
00295        EXT (BFD_RELOC_SPARC_GOT22, 16);
00296        EXT (BFD_RELOC_SPARC_PC10, 17);
00297        EXT (BFD_RELOC_SPARC_PC22, 18);
00298        EXT (BFD_RELOC_SPARC_WPLT30, 19);
00299        EXT (BFD_RELOC_SPARC_REV32, 26);
00300       default:
00301        return NULL;
00302       }
00303   else
00304     /* std relocs.  */
00305     switch (code)
00306       {
00307        STD (BFD_RELOC_8, 0);
00308        STD (BFD_RELOC_16, 1);
00309        STD (BFD_RELOC_32, 2);
00310        STD (BFD_RELOC_8_PCREL, 4);
00311        STD (BFD_RELOC_16_PCREL, 5);
00312        STD (BFD_RELOC_32_PCREL, 6);
00313        STD (BFD_RELOC_16_BASEREL, 9);
00314        STD (BFD_RELOC_32_BASEREL, 10);
00315       default:
00316        return NULL;
00317       }
00318 }
00319 
00320 reloc_howto_type *
00321 NAME (aout, reloc_name_lookup) (bfd *abfd, const char *r_name)
00322 {
00323   unsigned int i, size;
00324   reloc_howto_type *howto_table;
00325 
00326   if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
00327     {
00328       howto_table = howto_table_ext;
00329       size = sizeof (howto_table_ext) / sizeof (howto_table_ext[0]);
00330     }
00331   else
00332     {
00333       howto_table = howto_table_std;
00334       size = sizeof (howto_table_std) / sizeof (howto_table_std[0]);
00335     }
00336 
00337   for (i = 0; i < size; i++)
00338     if (howto_table[i].name != NULL
00339        && strcasecmp (howto_table[i].name, r_name) == 0)
00340       return &howto_table[i];
00341 
00342   return NULL;
00343 }
00344 
00345 /*
00346 SUBSECTION
00347        Internal entry points
00348 
00349 DESCRIPTION
00350        @file{aoutx.h} exports several routines for accessing the
00351        contents of an a.out file, which are gathered and exported in
00352        turn by various format specific files (eg sunos.c).
00353 */
00354 
00355 /*
00356 FUNCTION
00357         aout_@var{size}_swap_exec_header_in
00358 
00359 SYNOPSIS
00360        void aout_@var{size}_swap_exec_header_in,
00361            (bfd *abfd,
00362             struct external_exec *bytes,
00363             struct internal_exec *execp);
00364 
00365 DESCRIPTION
00366        Swap the information in an executable header @var{raw_bytes} taken
00367        from a raw byte stream memory image into the internal exec header
00368        structure @var{execp}.
00369 */
00370 
00371 #ifndef NAME_swap_exec_header_in
00372 void
00373 NAME (aout, swap_exec_header_in) (bfd *abfd,
00374                               struct external_exec *bytes,
00375                               struct internal_exec *execp)
00376 {
00377   /* The internal_exec structure has some fields that are unused in this
00378      configuration (IE for i960), so ensure that all such uninitialized
00379      fields are zero'd out.  There are places where two of these structs
00380      are memcmp'd, and thus the contents do matter.  */
00381   memset ((void *) execp, 0, sizeof (struct internal_exec));
00382   /* Now fill in fields in the execp, from the bytes in the raw data.  */
00383   execp->a_info   = H_GET_32 (abfd, bytes->e_info);
00384   execp->a_text   = GET_WORD (abfd, bytes->e_text);
00385   execp->a_data   = GET_WORD (abfd, bytes->e_data);
00386   execp->a_bss    = GET_WORD (abfd, bytes->e_bss);
00387   execp->a_syms   = GET_WORD (abfd, bytes->e_syms);
00388   execp->a_entry  = GET_WORD (abfd, bytes->e_entry);
00389   execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
00390   execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
00391 }
00392 #define NAME_swap_exec_header_in NAME (aout, swap_exec_header_in)
00393 #endif
00394 
00395 /*
00396 FUNCTION
00397        aout_@var{size}_swap_exec_header_out
00398 
00399 SYNOPSIS
00400        void aout_@var{size}_swap_exec_header_out
00401          (bfd *abfd,
00402           struct internal_exec *execp,
00403           struct external_exec *raw_bytes);
00404 
00405 DESCRIPTION
00406        Swap the information in an internal exec header structure
00407        @var{execp} into the buffer @var{raw_bytes} ready for writing to disk.
00408 */
00409 void
00410 NAME (aout, swap_exec_header_out) (bfd *abfd,
00411                                struct internal_exec *execp,
00412                                struct external_exec *bytes)
00413 {
00414   /* Now fill in fields in the raw data, from the fields in the exec struct.  */
00415   H_PUT_32 (abfd, execp->a_info  , bytes->e_info);
00416   PUT_WORD (abfd, execp->a_text  , bytes->e_text);
00417   PUT_WORD (abfd, execp->a_data  , bytes->e_data);
00418   PUT_WORD (abfd, execp->a_bss   , bytes->e_bss);
00419   PUT_WORD (abfd, execp->a_syms  , bytes->e_syms);
00420   PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
00421   PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
00422   PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
00423 }
00424 
00425 /* Make all the section for an a.out file.  */
00426 
00427 bfd_boolean
00428 NAME (aout, make_sections) (bfd *abfd)
00429 {
00430   if (obj_textsec (abfd) == NULL && bfd_make_section (abfd, ".text") == NULL)
00431     return FALSE;
00432   if (obj_datasec (abfd) == NULL && bfd_make_section (abfd, ".data") == NULL)
00433     return FALSE;
00434   if (obj_bsssec (abfd) == NULL && bfd_make_section (abfd, ".bss") == NULL)
00435     return FALSE;
00436   return TRUE;
00437 }
00438 
00439 /*
00440 FUNCTION
00441        aout_@var{size}_some_aout_object_p
00442 
00443 SYNOPSIS
00444        const bfd_target *aout_@var{size}_some_aout_object_p
00445         (bfd *abfd,
00446           struct internal_exec *execp,
00447          const bfd_target *(*callback_to_real_object_p) (bfd *));
00448 
00449 DESCRIPTION
00450        Some a.out variant thinks that the file open in @var{abfd}
00451        checking is an a.out file.  Do some more checking, and set up
00452        for access if it really is.  Call back to the calling
00453        environment's "finish up" function just before returning, to
00454        handle any last-minute setup.
00455 */
00456 
00457 const bfd_target *
00458 NAME (aout, some_aout_object_p) (bfd *abfd,
00459                              struct internal_exec *execp,
00460                              const bfd_target *(*callback_to_real_object_p) (bfd *))
00461 {
00462   struct aout_data_struct *rawptr, *oldrawptr;
00463   const bfd_target *result;
00464   bfd_size_type amt = sizeof (* rawptr);
00465 
00466   rawptr = bfd_zalloc (abfd, amt);
00467   if (rawptr == NULL)
00468     return NULL;
00469 
00470   oldrawptr = abfd->tdata.aout_data;
00471   abfd->tdata.aout_data = rawptr;
00472 
00473   /* Copy the contents of the old tdata struct.
00474      In particular, we want the subformat, since for hpux it was set in
00475      hp300hpux.c:swap_exec_header_in and will be used in
00476      hp300hpux.c:callback.  */
00477   if (oldrawptr != NULL)
00478     *abfd->tdata.aout_data = *oldrawptr;
00479 
00480   abfd->tdata.aout_data->a.hdr = &rawptr->e;
00481   /* Copy in the internal_exec struct.  */
00482   *(abfd->tdata.aout_data->a.hdr) = *execp;
00483   execp = abfd->tdata.aout_data->a.hdr;
00484 
00485   /* Set the file flags.  */
00486   abfd->flags = BFD_NO_FLAGS;
00487   if (execp->a_drsize || execp->a_trsize)
00488     abfd->flags |= HAS_RELOC;
00489   /* Setting of EXEC_P has been deferred to the bottom of this function.  */
00490   if (execp->a_syms)
00491     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
00492   if (N_DYNAMIC (*execp))
00493     abfd->flags |= DYNAMIC;
00494 
00495   if (N_MAGIC (*execp) == ZMAGIC)
00496     {
00497       abfd->flags |= D_PAGED | WP_TEXT;
00498       adata (abfd).magic = z_magic;
00499     }
00500   else if (N_MAGIC (*execp) == QMAGIC)
00501     {
00502       abfd->flags |= D_PAGED | WP_TEXT;
00503       adata (abfd).magic = z_magic;
00504       adata (abfd).subformat = q_magic_format;
00505     }
00506   else if (N_MAGIC (*execp) == NMAGIC)
00507     {
00508       abfd->flags |= WP_TEXT;
00509       adata (abfd).magic = n_magic;
00510     }
00511   else if (N_MAGIC (*execp) == OMAGIC
00512           || N_MAGIC (*execp) == BMAGIC)
00513     adata (abfd).magic = o_magic;
00514   else
00515     /* Should have been checked with N_BADMAG before this routine
00516        was called.  */
00517     abort ();
00518 
00519   bfd_get_start_address (abfd) = execp->a_entry;
00520 
00521   obj_aout_symbols (abfd) = NULL;
00522   bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
00523 
00524   /* The default relocation entry size is that of traditional V7 Unix.  */
00525   obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00526 
00527   /* The default symbol entry size is that of traditional Unix.  */
00528   obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
00529 
00530 #ifdef USE_MMAP
00531   bfd_init_window (&obj_aout_sym_window (abfd));
00532   bfd_init_window (&obj_aout_string_window (abfd));
00533 #endif
00534   obj_aout_external_syms (abfd) = NULL;
00535   obj_aout_external_strings (abfd) = NULL;
00536   obj_aout_sym_hashes (abfd) = NULL;
00537 
00538   if (! NAME (aout, make_sections) (abfd))
00539     goto error_ret;
00540 
00541   obj_datasec (abfd)->size = execp->a_data;
00542   obj_bsssec (abfd)->size = execp->a_bss;
00543 
00544   obj_textsec (abfd)->flags =
00545     (execp->a_trsize != 0
00546      ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
00547      : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
00548   obj_datasec (abfd)->flags =
00549     (execp->a_drsize != 0
00550      ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
00551      : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
00552   obj_bsssec (abfd)->flags = SEC_ALLOC;
00553 
00554 #ifdef THIS_IS_ONLY_DOCUMENTATION
00555   /* The common code can't fill in these things because they depend
00556      on either the start address of the text segment, the rounding
00557      up of virtual addresses between segments, or the starting file
00558      position of the text segment -- all of which varies among different
00559      versions of a.out.  */
00560 
00561   /* Call back to the format-dependent code to fill in the rest of the
00562      fields and do any further cleanup.  Things that should be filled
00563      in by the callback:  */
00564 
00565   struct exec *execp = exec_hdr (abfd);
00566 
00567   obj_textsec (abfd)->size = N_TXTSIZE (*execp);
00568   /* Data and bss are already filled in since they're so standard.  */
00569 
00570   /* The virtual memory addresses of the sections.  */
00571   obj_textsec (abfd)->vma = N_TXTADDR (*execp);
00572   obj_datasec (abfd)->vma = N_DATADDR (*execp);
00573   obj_bsssec  (abfd)->vma = N_BSSADDR (*execp);
00574 
00575   /* The file offsets of the sections.  */
00576   obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
00577   obj_datasec (abfd)->filepos = N_DATOFF (*execp);
00578 
00579   /* The file offsets of the relocation info.  */
00580   obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
00581   obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);
00582 
00583   /* The file offsets of the string table and symbol table.  */
00584   obj_str_filepos (abfd) = N_STROFF (*execp);
00585   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
00586 
00587   /* Determine the architecture and machine type of the object file.  */
00588   switch (N_MACHTYPE (*exec_hdr (abfd)))
00589     {
00590     default:
00591       abfd->obj_arch = bfd_arch_obscure;
00592       break;
00593     }
00594 
00595   adata (abfd)->page_size = TARGET_PAGE_SIZE;
00596   adata (abfd)->segment_size = SEGMENT_SIZE;
00597   adata (abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
00598 
00599   return abfd->xvec;
00600 
00601   /* The architecture is encoded in various ways in various a.out variants,
00602      or is not encoded at all in some of them.  The relocation size depends
00603      on the architecture and the a.out variant.  Finally, the return value
00604      is the bfd_target vector in use.  If an error occurs, return zero and
00605      set bfd_error to the appropriate error code.
00606 
00607      Formats such as b.out, which have additional fields in the a.out
00608      header, should cope with them in this callback as well.  */
00609 #endif                      /* DOCUMENTATION */
00610 
00611   result = (*callback_to_real_object_p) (abfd);
00612 
00613   /* Now that the segment addresses have been worked out, take a better
00614      guess at whether the file is executable.  If the entry point
00615      is within the text segment, assume it is.  (This makes files
00616      executable even if their entry point address is 0, as long as
00617      their text starts at zero.).
00618 
00619      This test had to be changed to deal with systems where the text segment
00620      runs at a different location than the default.  The problem is that the
00621      entry address can appear to be outside the text segment, thus causing an
00622      erroneous conclusion that the file isn't executable.
00623 
00624      To fix this, we now accept any non-zero entry point as an indication of
00625      executability.  This will work most of the time, since only the linker
00626      sets the entry point, and that is likely to be non-zero for most systems.  */
00627 
00628   if (execp->a_entry != 0
00629       || (execp->a_entry >= obj_textsec (abfd)->vma
00630          && execp->a_entry < (obj_textsec (abfd)->vma
00631                             + obj_textsec (abfd)->size)))
00632     abfd->flags |= EXEC_P;
00633 #ifdef STAT_FOR_EXEC
00634   else
00635     {
00636       struct stat stat_buf;
00637 
00638       /* The original heuristic doesn't work in some important cases.
00639         The a.out file has no information about the text start
00640         address.  For files (like kernels) linked to non-standard
00641         addresses (ld -Ttext nnn) the entry point may not be between
00642         the default text start (obj_textsec(abfd)->vma) and
00643         (obj_textsec(abfd)->vma) + text size.  This is not just a mach
00644         issue.  Many kernels are loaded at non standard addresses.  */
00645       if (abfd->iostream != NULL
00646          && (abfd->flags & BFD_IN_MEMORY) == 0
00647          && (fstat (fileno ((FILE *) (abfd->iostream)), &stat_buf) == 0)
00648          && ((stat_buf.st_mode & 0111) != 0))
00649        abfd->flags |= EXEC_P;
00650     }
00651 #endif /* STAT_FOR_EXEC */
00652 
00653   if (result)
00654     return result;
00655 
00656  error_ret:
00657   bfd_release (abfd, rawptr);
00658   abfd->tdata.aout_data = oldrawptr;
00659   return NULL;
00660 }
00661 
00662 /*
00663 FUNCTION
00664        aout_@var{size}_mkobject
00665 
00666 SYNOPSIS
00667        bfd_boolean aout_@var{size}_mkobject, (bfd *abfd);
00668 
00669 DESCRIPTION
00670        Initialize BFD @var{abfd} for use with a.out files.
00671 */
00672 
00673 bfd_boolean
00674 NAME (aout, mkobject) (bfd *abfd)
00675 {
00676   struct aout_data_struct *rawptr;
00677   bfd_size_type amt = sizeof (* rawptr);
00678 
00679   bfd_set_error (bfd_error_system_call);
00680 
00681   rawptr = bfd_zalloc (abfd, amt);
00682   if (rawptr == NULL)
00683     return FALSE;
00684 
00685   abfd->tdata.aout_data = rawptr;
00686   exec_hdr (abfd) = &(rawptr->e);
00687 
00688   obj_textsec (abfd) = NULL;
00689   obj_datasec (abfd) = NULL;
00690   obj_bsssec (abfd) = NULL;
00691 
00692   return TRUE;
00693 }
00694 
00695 /*
00696 FUNCTION
00697        aout_@var{size}_machine_type
00698 
00699 SYNOPSIS
00700        enum machine_type  aout_@var{size}_machine_type
00701         (enum bfd_architecture arch,
00702          unsigned long machine,
00703           bfd_boolean *unknown);
00704 
00705 DESCRIPTION
00706        Keep track of machine architecture and machine type for
00707        a.out's. Return the <<machine_type>> for a particular
00708        architecture and machine, or <<M_UNKNOWN>> if that exact architecture
00709        and machine can't be represented in a.out format.
00710 
00711        If the architecture is understood, machine type 0 (default)
00712        is always understood.
00713 */
00714 
00715 enum machine_type
00716 NAME (aout, machine_type) (enum bfd_architecture arch,
00717                         unsigned long machine,
00718                         bfd_boolean *unknown)
00719 {
00720   enum machine_type arch_flags;
00721 
00722   arch_flags = M_UNKNOWN;
00723   *unknown = TRUE;
00724 
00725   switch (arch)
00726     {
00727     case bfd_arch_sparc:
00728       if (machine == 0
00729          || machine == bfd_mach_sparc
00730          || machine == bfd_mach_sparc_sparclite
00731          || machine == bfd_mach_sparc_sparclite_le
00732          || machine == bfd_mach_sparc_v8plus
00733          || machine == bfd_mach_sparc_v8plusa
00734          || machine == bfd_mach_sparc_v8plusb
00735          || machine == bfd_mach_sparc_v9
00736          || machine == bfd_mach_sparc_v9a
00737          || machine == bfd_mach_sparc_v9b)
00738        arch_flags = M_SPARC;
00739       else if (machine == bfd_mach_sparc_sparclet)
00740        arch_flags = M_SPARCLET;
00741       break;
00742 
00743     case bfd_arch_m68k:
00744       switch (machine)
00745        {
00746        case 0:                    arch_flags = M_68010; break;
00747        case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = FALSE; break;
00748        case bfd_mach_m68010: arch_flags = M_68010; break;
00749        case bfd_mach_m68020: arch_flags = M_68020; break;
00750        default:            arch_flags = M_UNKNOWN; break;
00751        }
00752       break;
00753 
00754     case bfd_arch_i386:
00755       if (machine == 0
00756          || machine == bfd_mach_i386_i386
00757          || machine == bfd_mach_i386_i386_intel_syntax)
00758        arch_flags = M_386;
00759       break;
00760 
00761     case bfd_arch_arm:
00762       if (machine == 0)
00763        arch_flags = M_ARM;
00764       break;
00765 
00766     case bfd_arch_mips:
00767       switch (machine)
00768        {
00769        case 0:
00770        case bfd_mach_mips3000:
00771        case bfd_mach_mips3900:
00772          arch_flags = M_MIPS1;
00773          break;
00774        case bfd_mach_mips6000:
00775          arch_flags = M_MIPS2;
00776          break;
00777        case bfd_mach_mips4000:
00778        case bfd_mach_mips4010:
00779        case bfd_mach_mips4100:
00780        case bfd_mach_mips4300:
00781        case bfd_mach_mips4400:
00782        case bfd_mach_mips4600:
00783        case bfd_mach_mips4650:
00784        case bfd_mach_mips8000:
00785        case bfd_mach_mips9000:
00786        case bfd_mach_mips10000:
00787        case bfd_mach_mips12000:
00788        case bfd_mach_mips16:
00789        case bfd_mach_mipsisa32:
00790        case bfd_mach_mipsisa32r2:
00791        case bfd_mach_mips5:
00792        case bfd_mach_mipsisa64:
00793        case bfd_mach_mipsisa64r2:
00794        case bfd_mach_mips_sb1:
00795          /* FIXME: These should be MIPS3, MIPS4, MIPS16, MIPS32, etc.  */
00796          arch_flags = M_MIPS2;
00797          break;
00798        default:
00799          arch_flags = M_UNKNOWN;
00800          break;
00801        }
00802       break;
00803 
00804     case bfd_arch_ns32k:
00805       switch (machine)
00806        {
00807        case 0:       arch_flags = M_NS32532; break;
00808        case 32032:   arch_flags = M_NS32032; break;
00809        case 32532:   arch_flags = M_NS32532; break;
00810        default:      arch_flags = M_UNKNOWN; break;
00811        }
00812       break;
00813 
00814     case bfd_arch_vax:
00815       *unknown = FALSE;
00816       break;
00817 
00818     case bfd_arch_cris:
00819       if (machine == 0 || machine == 255)
00820        arch_flags = M_CRIS;
00821       break;
00822 
00823     case bfd_arch_m88k:
00824       *unknown = FALSE;
00825       break;
00826 
00827     default:
00828       arch_flags = M_UNKNOWN;
00829     }
00830 
00831   if (arch_flags != M_UNKNOWN)
00832     *unknown = FALSE;
00833 
00834   return arch_flags;
00835 }
00836 
00837 /*
00838 FUNCTION
00839        aout_@var{size}_set_arch_mach
00840 
00841 SYNOPSIS
00842        bfd_boolean aout_@var{size}_set_arch_mach,
00843         (bfd *,
00844          enum bfd_architecture arch,
00845          unsigned long machine);
00846 
00847 DESCRIPTION
00848        Set the architecture and the machine of the BFD @var{abfd} to the
00849        values @var{arch} and @var{machine}.  Verify that @var{abfd}'s format
00850        can support the architecture required.
00851 */
00852 
00853 bfd_boolean
00854 NAME (aout, set_arch_mach) (bfd *abfd,
00855                          enum bfd_architecture arch,
00856                          unsigned long machine)
00857 {
00858   if (! bfd_default_set_arch_mach (abfd, arch, machine))
00859     return FALSE;
00860 
00861   if (arch != bfd_arch_unknown)
00862     {
00863       bfd_boolean unknown;
00864 
00865       NAME (aout, machine_type) (arch, machine, &unknown);
00866       if (unknown)
00867        return FALSE;
00868     }
00869 
00870   /* Determine the size of a relocation entry.  */
00871   switch (arch)
00872     {
00873     case bfd_arch_sparc:
00874     case bfd_arch_mips:
00875       obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
00876       break;
00877     default:
00878       obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
00879       break;
00880     }
00881 
00882   return (*aout_backend_info (abfd)->set_sizes) (abfd);
00883 }
00884 
00885 static void
00886 adjust_o_magic (bfd *abfd, struct internal_exec *execp)
00887 {
00888   file_ptr pos = adata (abfd).exec_bytes_size;
00889   bfd_vma vma = 0;
00890   int pad = 0;
00891 
00892   /* Text.  */
00893   obj_textsec (abfd)->filepos = pos;
00894   if (!obj_textsec (abfd)->user_set_vma)
00895     obj_textsec (abfd)->vma = vma;
00896   else
00897     vma = obj_textsec (abfd)->vma;
00898 
00899   pos += obj_textsec (abfd)->size;
00900   vma += obj_textsec (abfd)->size;
00901 
00902   /* Data.  */
00903   if (!obj_datasec (abfd)->user_set_vma)
00904     {
00905       obj_textsec (abfd)->size += pad;
00906       pos += pad;
00907       vma += pad;
00908       obj_datasec (abfd)->vma = vma;
00909     }
00910   else
00911     vma = obj_datasec (abfd)->vma;
00912   obj_datasec (abfd)->filepos = pos;
00913   pos += obj_datasec (abfd)->size;
00914   vma += obj_datasec (abfd)->size;
00915 
00916   /* BSS.  */
00917   if (!obj_bsssec (abfd)->user_set_vma)
00918     {
00919       obj_datasec (abfd)->size += pad;
00920       pos += pad;
00921       vma += pad;
00922       obj_bsssec (abfd)->vma = vma;
00923     }
00924   else
00925     {
00926       /* The VMA of the .bss section is set by the VMA of the
00927          .data section plus the size of the .data section.  We may
00928          need to add padding bytes to make this true.  */
00929       pad = obj_bsssec (abfd)->vma - vma;
00930       if (pad > 0)
00931        {
00932          obj_datasec (abfd)->size += pad;
00933          pos += pad;
00934        }
00935     }
00936   obj_bsssec (abfd)->filepos = pos;
00937 
00938   /* Fix up the exec header.  */
00939   execp->a_text = obj_textsec (abfd)->size;
00940   execp->a_data = obj_datasec (abfd)->size;
00941   execp->a_bss = obj_bsssec (abfd)->size;
00942   N_SET_MAGIC (*execp, OMAGIC);
00943 }
00944 
00945 static void
00946 adjust_z_magic (bfd *abfd, struct internal_exec *execp)
00947 {
00948   bfd_size_type data_pad, text_pad;
00949   file_ptr text_end;
00950   const struct aout_backend_data *abdp;
00951   /* TRUE if text includes exec header.  */
00952   bfd_boolean ztih;
00953 
00954   abdp = aout_backend_info (abfd);
00955 
00956   /* Text.  */
00957   ztih = (abdp != NULL
00958          && (abdp->text_includes_header
00959              || obj_aout_subformat (abfd) == q_magic_format));
00960   obj_textsec (abfd)->filepos = (ztih
00961                              ? adata (abfd).exec_bytes_size
00962                              : adata (abfd).zmagic_disk_block_size);
00963   if (! obj_textsec (abfd)->user_set_vma)
00964     {
00965       /* ?? Do we really need to check for relocs here?  */
00966       obj_textsec (abfd)->vma = ((abfd->flags & HAS_RELOC)
00967                              ? 0
00968                              : (ztih
00969                                 ? (abdp->default_text_vma
00970                                    + adata (abfd).exec_bytes_size)
00971                                 : abdp->default_text_vma));
00972       text_pad = 0;
00973     }
00974   else
00975     {
00976       /* The .text section is being loaded at an unusual address.  We
00977          may need to pad it such that the .data section starts at a page
00978          boundary.  */
00979       if (ztih)
00980        text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma)
00981                   & (adata (abfd).page_size - 1));
00982       else
00983        text_pad = ((- obj_textsec (abfd)->vma)
00984                   & (adata (abfd).page_size - 1));
00985     }
00986 
00987   /* Find start of data.  */
00988   if (ztih)
00989     {
00990       text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->size;
00991       text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
00992     }
00993   else
00994     {
00995       /* Note that if page_size == zmagic_disk_block_size, then
00996         filepos == page_size, and this case is the same as the ztih
00997         case.  */
00998       text_end = obj_textsec (abfd)->size;
00999       text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
01000       text_end += obj_textsec (abfd)->filepos;
01001     }
01002   obj_textsec (abfd)->size += text_pad;
01003   text_end += text_pad;
01004 
01005   /* Data.  */
01006   if (!obj_datasec (abfd)->user_set_vma)
01007     {
01008       bfd_vma vma;
01009       vma = obj_textsec (abfd)->vma + obj_textsec (abfd)->size;
01010       obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size);
01011     }
01012   if (abdp && abdp->zmagic_mapped_contiguous)
01013     {
01014       asection * text = obj_textsec (abfd);
01015       asection * data = obj_datasec (abfd);
01016 
01017       text_pad = data->vma - (text->vma + text->size);
01018       /* Only pad the text section if the data
01019         section is going to be placed after it.  */
01020       if (text_pad > 0)
01021        text->size += text_pad;
01022     }
01023   obj_datasec (abfd)->filepos = (obj_textsec (abfd)->filepos
01024                              + obj_textsec (abfd)->size);
01025 
01026   /* Fix up exec header while we're at it.  */
01027   execp->a_text = obj_textsec (abfd)->size;
01028   if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
01029     execp->a_text += adata (abfd).exec_bytes_size;
01030   if (obj_aout_subformat (abfd) == q_magic_format)
01031     N_SET_MAGIC (*execp, QMAGIC);
01032   else
01033     N_SET_MAGIC (*execp, ZMAGIC);
01034 
01035   /* Spec says data section should be rounded up to page boundary.  */
01036   obj_datasec (abfd)->size
01037     = align_power (obj_datasec (abfd)->size,
01038                  obj_bsssec (abfd)->alignment_power);
01039   execp->a_data = BFD_ALIGN (obj_datasec (abfd)->size,
01040                           adata (abfd).page_size);
01041   data_pad = execp->a_data - obj_datasec (abfd)->size;
01042 
01043   /* BSS.  */
01044   if (!obj_bsssec (abfd)->user_set_vma)
01045     obj_bsssec (abfd)->vma = (obj_datasec (abfd)->vma
01046                            + obj_datasec (abfd)->size);
01047   /* If the BSS immediately follows the data section and extra space
01048      in the page is left after the data section, fudge data
01049      in the header so that the bss section looks smaller by that
01050      amount.  We'll start the bss section there, and lie to the OS.
01051      (Note that a linker script, as well as the above assignment,
01052      could have explicitly set the BSS vma to immediately follow
01053      the data section.)  */
01054   if (align_power (obj_bsssec (abfd)->vma, obj_bsssec (abfd)->alignment_power)
01055       == obj_datasec (abfd)->vma + obj_datasec (abfd)->size)
01056     execp->a_bss = (data_pad > obj_bsssec (abfd)->size
01057                   ? 0 : obj_bsssec (abfd)->size - data_pad);
01058   else
01059     execp->a_bss = obj_bsssec (abfd)->size;
01060 }
01061 
01062 static void
01063 adjust_n_magic (bfd *abfd, struct internal_exec *execp)
01064 {
01065   file_ptr pos = adata (abfd).exec_bytes_size;
01066   bfd_vma vma = 0;
01067   int pad;
01068 
01069   /* Text.  */
01070   obj_textsec (abfd)->filepos = pos;
01071   if (!obj_textsec (abfd)->user_set_vma)
01072     obj_textsec (abfd)->vma = vma;
01073   else
01074     vma = obj_textsec (abfd)->vma;
01075   pos += obj_textsec (abfd)->size;
01076   vma += obj_textsec (abfd)->size;
01077 
01078   /* Data.  */
01079   obj_datasec (abfd)->filepos = pos;
01080   if (!obj_datasec (abfd)->user_set_vma)
01081     obj_datasec (abfd)->vma = BFD_ALIGN (vma, adata (abfd).segment_size);
01082   vma = obj_datasec (abfd)->vma;
01083 
01084   /* Since BSS follows data immediately, see if it needs alignment.  */
01085   vma += obj_datasec (abfd)->size;
01086   pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma;
01087   obj_datasec (abfd)->size += pad;
01088   pos += obj_datasec (abfd)->size;
01089 
01090   /* BSS.  */
01091   if (!obj_bsssec (abfd)->user_set_vma)
01092     obj_bsssec (abfd)->vma = vma;
01093   else
01094     vma = obj_bsssec (abfd)->vma;
01095 
01096   /* Fix up exec header.  */
01097   execp->a_text = obj_textsec (abfd)->size;
01098   execp->a_data = obj_datasec (abfd)->size;
01099   execp->a_bss = obj_bsssec (abfd)->size;
01100   N_SET_MAGIC (*execp, NMAGIC);
01101 }
01102 
01103 bfd_boolean
01104 NAME (aout, adjust_sizes_and_vmas) (bfd *abfd,
01105                                 bfd_size_type *text_size,
01106                                 file_ptr *text_end ATTRIBUTE_UNUSED)
01107 {
01108   struct internal_exec *execp = exec_hdr (abfd);
01109 
01110   if (! NAME (aout, make_sections) (abfd))
01111     return FALSE;
01112 
01113   if (adata (abfd).magic != undecided_magic)
01114     return TRUE;
01115 
01116   obj_textsec (abfd)->size =
01117     align_power (obj_textsec (abfd)->size,
01118                obj_textsec (abfd)->alignment_power);
01119 
01120   *text_size = obj_textsec (abfd)->size;
01121   /* Rule (heuristic) for when to pad to a new page.  Note that there
01122      are (at least) two ways demand-paged (ZMAGIC) files have been
01123      handled.  Most Berkeley-based systems start the text segment at
01124      (TARGET_PAGE_SIZE).  However, newer versions of SUNOS start the text
01125      segment right after the exec header; the latter is counted in the
01126      text segment size, and is paged in by the kernel with the rest of
01127      the text.  */
01128 
01129   /* This perhaps isn't the right way to do this, but made it simpler for me
01130      to understand enough to implement it.  Better would probably be to go
01131      right from BFD flags to alignment/positioning characteristics.  But the
01132      old code was sloppy enough about handling the flags, and had enough
01133      other magic, that it was a little hard for me to understand.  I think
01134      I understand it better now, but I haven't time to do the cleanup this
01135      minute.  */
01136 
01137   if (abfd->flags & D_PAGED)
01138     /* Whether or not WP_TEXT is set -- let D_PAGED override.  */
01139     adata (abfd).magic = z_magic;
01140   else if (abfd->flags & WP_TEXT)
01141     adata (abfd).magic = n_magic;
01142   else
01143     adata (abfd).magic = o_magic;
01144 
01145 #ifdef BFD_AOUT_DEBUG /* requires gcc2 */
01146 #if __GNUC__ >= 2
01147   fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
01148           ({ char *str;
01149              switch (adata (abfd).magic)
01150               {
01151               case n_magic: str = "NMAGIC"; break;
01152               case o_magic: str = "OMAGIC"; break;
01153               case z_magic: str = "ZMAGIC"; break;
01154               default: abort ();
01155               }
01156              str;
01157            }),
01158           obj_textsec (abfd)->vma, obj_textsec (abfd)->size,
01159               obj_textsec (abfd)->alignment_power,
01160           obj_datasec (abfd)->vma, obj_datasec (abfd)->size,
01161               obj_datasec (abfd)->alignment_power,
01162           obj_bsssec (abfd)->vma, obj_bsssec (abfd)->size,
01163               obj_bsssec (abfd)->alignment_power);
01164 #endif
01165 #endif
01166 
01167   switch (adata (abfd).magic)
01168     {
01169     case o_magic:
01170       adjust_o_magic (abfd, execp);
01171       break;
01172     case z_magic:
01173       adjust_z_magic (abfd, execp);
01174       break;
01175     case n_magic:
01176       adjust_n_magic (abfd, execp);
01177       break;
01178     default:
01179       abort ();
01180     }
01181 
01182 #ifdef BFD_AOUT_DEBUG
01183   fprintf (stderr, "       text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n",
01184           obj_textsec (abfd)->vma, obj_textsec (abfd)->size,
01185               obj_textsec (abfd)->filepos,
01186           obj_datasec (abfd)->vma, obj_datasec (abfd)->size,
01187               obj_datasec (abfd)->filepos,
01188           obj_bsssec (abfd)->vma, obj_bsssec (abfd)->size);
01189 #endif
01190 
01191   return TRUE;
01192 }
01193 
01194 /*
01195 FUNCTION
01196        aout_@var{size}_new_section_hook
01197 
01198 SYNOPSIS
01199         bfd_boolean aout_@var{size}_new_section_hook,
01200           (bfd *abfd,
01201            asection *newsect);
01202 
01203 DESCRIPTION
01204        Called by the BFD in response to a @code{bfd_make_section}
01205        request.
01206 */
01207 bfd_boolean
01208 NAME (aout, new_section_hook) (bfd *abfd, asection *newsect)
01209 {
01210   /* Align to double at least.  */
01211   newsect->alignment_power = bfd_get_arch_info (abfd)->section_align_power;
01212 
01213   if (bfd_get_format (abfd) == bfd_object)
01214     {
01215       if (obj_textsec (abfd) == NULL && !strcmp (newsect->name, ".text"))
01216        {
01217          obj_textsec (abfd)= newsect;
01218          newsect->target_index = N_TEXT;
01219        }
01220       else if (obj_datasec (abfd) == NULL && !strcmp (newsect->name, ".data"))
01221        {
01222          obj_datasec (abfd) = newsect;
01223          newsect->target_index = N_DATA;
01224        }
01225       else if (obj_bsssec (abfd) == NULL && !strcmp (newsect->name, ".bss"))
01226        {
01227          obj_bsssec (abfd) = newsect;
01228          newsect->target_index = N_BSS;
01229        }
01230     }
01231 
01232   /* We allow more than three sections internally.  */
01233   return _bfd_generic_new_section_hook (abfd, newsect);
01234 }
01235 
01236 bfd_boolean
01237 NAME (aout, set_section_contents) (bfd *abfd,
01238                                sec_ptr section,
01239                                const void * location,
01240                                file_ptr offset,
01241                                bfd_size_type count)
01242 {
01243   file_ptr text_end;
01244   bfd_size_type text_size;
01245 
01246   if (! abfd->output_has_begun)
01247     {
01248       if (! NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
01249        return FALSE;
01250     }
01251 
01252   if (section == obj_bsssec (abfd))
01253     {
01254       bfd_set_error (bfd_error_no_contents);
01255       return FALSE;
01256     }
01257 
01258   if (section != obj_textsec (abfd)
01259       && section != obj_datasec (abfd))
01260     {
01261       if (aout_section_merge_with_text_p (abfd, section))
01262        section->filepos = obj_textsec (abfd)->filepos +
01263                         (section->vma - obj_textsec (abfd)->vma);
01264       else
01265        {
01266           (*_bfd_error_handler)
01267           (_("%s: can not represent section `%s' in a.out object file format"),
01268             bfd_get_filename (abfd), bfd_get_section_name (abfd, section));
01269           bfd_set_error (bfd_error_nonrepresentable_section);
01270           return FALSE;
01271        }
01272     }
01273 
01274   if (count != 0)
01275     {
01276       if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
01277          || bfd_bwrite (location, count, abfd) != count)
01278        return FALSE;
01279     }
01280 
01281   return TRUE;
01282 }
01283 
01284 /* Read the external symbols from an a.out file.  */
01285 
01286 static bfd_boolean
01287 aout_get_external_symbols (bfd *abfd)
01288 {
01289   if (obj_aout_external_syms (abfd) == NULL)
01290     {
01291       bfd_size_type count;
01292       struct external_nlist *syms;
01293       bfd_size_type amt;
01294 
01295       count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
01296 
01297 #ifdef USE_MMAP
01298       if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd),
01299                              exec_hdr (abfd)->a_syms,
01300                              &obj_aout_sym_window (abfd), TRUE))
01301        return FALSE;
01302       syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
01303 #else
01304       /* We allocate using malloc to make the values easy to free
01305         later on.  If we put them on the objalloc it might not be
01306         possible to free them.  */
01307       syms = bfd_malloc (count * EXTERNAL_NLIST_SIZE);
01308       if (syms == NULL && count != 0)
01309        return FALSE;
01310 
01311       amt = exec_hdr (abfd)->a_syms;
01312       if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
01313          || bfd_bread (syms, amt, abfd) != amt)
01314        {
01315          free (syms);
01316          return FALSE;
01317        }
01318 #endif
01319 
01320       obj_aout_external_syms (abfd) = syms;
01321       obj_aout_external_sym_count (abfd) = count;
01322     }
01323 
01324   if (obj_aout_external_strings (abfd) == NULL
01325       && exec_hdr (abfd)->a_syms != 0)
01326     {
01327       unsigned char string_chars[BYTES_IN_WORD];
01328       bfd_size_type stringsize;
01329       char *strings;
01330       bfd_size_type amt = BYTES_IN_WORD;
01331 
01332       /* Get the size of the strings.  */
01333       if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
01334          || bfd_bread ((void *) string_chars, amt, abfd) != amt)
01335        return FALSE;
01336       stringsize = GET_WORD (abfd, string_chars);
01337 
01338 #ifdef USE_MMAP
01339       if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize,
01340                              &obj_aout_string_window (abfd), TRUE))
01341        return FALSE;
01342       strings = (char *) obj_aout_string_window (abfd).data;
01343 #else
01344       strings = bfd_malloc (stringsize + 1);
01345       if (strings == NULL)
01346        return FALSE;
01347 
01348       /* Skip space for the string count in the buffer for convenience
01349         when using indexes.  */
01350       amt = stringsize - BYTES_IN_WORD;
01351       if (bfd_bread (strings + BYTES_IN_WORD, amt, abfd) != amt)
01352        {
01353          free (strings);
01354          return FALSE;
01355        }
01356 #endif
01357 
01358       /* Ensure that a zero index yields an empty string.  */
01359       strings[0] = '\0';
01360 
01361       strings[stringsize - 1] = 0;
01362 
01363       obj_aout_external_strings (abfd) = strings;
01364       obj_aout_external_string_size (abfd) = stringsize;
01365     }
01366 
01367   return TRUE;
01368 }
01369 
01370 /* Translate an a.out symbol into a BFD symbol.  The desc, other, type
01371    and symbol->value fields of CACHE_PTR will be set from the a.out
01372    nlist structure.  This function is responsible for setting
01373    symbol->flags and symbol->section, and adjusting symbol->value.  */
01374 
01375 static bfd_boolean
01376 translate_from_native_sym_flags (bfd *abfd, aout_symbol_type *cache_ptr)
01377 {
01378   flagword visible;
01379 
01380   if ((cache_ptr->type & N_STAB) != 0
01381       || cache_ptr->type == N_FN)
01382     {
01383       asection *sec;
01384 
01385       /* This is a debugging symbol.  */
01386       cache_ptr->symbol.flags = BSF_DEBUGGING;
01387 
01388       /* Work out the symbol section.  */
01389       switch (cache_ptr->type & N_TYPE)
01390        {
01391        case N_TEXT:
01392        case N_FN:
01393          sec = obj_textsec (abfd);
01394          break;
01395        case N_DATA:
01396          sec = obj_datasec (abfd);
01397          break;
01398        case N_BSS:
01399          sec = obj_bsssec (abfd);
01400          break;
01401        default:
01402        case N_ABS:
01403          sec = bfd_abs_section_ptr;
01404          break;
01405        }
01406 
01407       cache_ptr->symbol.section = sec;
01408       cache_ptr->symbol.value -= sec->vma;
01409 
01410       return TRUE;
01411     }
01412 
01413   /* Get the default visibility.  This does not apply to all types, so
01414      we just hold it in a local variable to use if wanted.  */
01415   if ((cache_ptr->type & N_EXT) == 0)
01416     visible = BSF_LOCAL;
01417   else
01418     visible = BSF_GLOBAL;
01419 
01420   switch (cache_ptr->type)
01421     {
01422     default:
01423     case N_ABS: case N_ABS | N_EXT:
01424       cache_ptr->symbol.section = bfd_abs_section_ptr;
01425       cache_ptr->symbol.flags = visible;
01426       break;
01427 
01428     case N_UNDF | N_EXT:
01429       if (cache_ptr->symbol.value != 0)
01430        {
01431          /* This is a common symbol.  */
01432          cache_ptr->symbol.flags = BSF_GLOBAL;
01433          cache_ptr->symbol.section = bfd_com_section_ptr;
01434        }
01435       else
01436        {
01437          cache_ptr->symbol.flags = 0;
01438          cache_ptr->symbol.section = bfd_und_section_ptr;
01439        }
01440       break;
01441 
01442     case N_TEXT: case N_TEXT | N_EXT:
01443       cache_ptr->symbol.section = obj_textsec (abfd);
01444       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
01445       cache_ptr->symbol.flags = visible;
01446       break;
01447 
01448       /* N_SETV symbols used to represent set vectors placed in the
01449         data section.  They are no longer generated.  Theoretically,
01450         it was possible to extract the entries and combine them with
01451         new ones, although I don't know if that was ever actually
01452         done.  Unless that feature is restored, treat them as data
01453         symbols.  */
01454     case N_SETV: case N_SETV | N_EXT:
01455     case N_DATA: case N_DATA | N_EXT:
01456       cache_ptr->symbol.section = obj_datasec (abfd);
01457       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
01458       cache_ptr->symbol.flags = visible;
01459       break;
01460 
01461     case N_BSS: case N_BSS | N_EXT:
01462       cache_ptr->symbol.section = obj_bsssec (abfd);
01463       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
01464       cache_ptr->symbol.flags = visible;
01465       break;
01466 
01467     case N_SETA: case N_SETA | N_EXT:
01468     case N_SETT: case N_SETT | N_EXT:
01469     case N_SETD: case N_SETD | N_EXT:
01470     case N_SETB: case N_SETB | N_EXT:
01471       {
01472        /* This code is no longer needed.  It used to be used to make
01473            the linker handle set symbols, but they are now handled in
01474            the add_symbols routine instead.  */
01475        switch (cache_ptr->type & N_TYPE)
01476          {
01477          case N_SETA:
01478            cache_ptr->symbol.section = bfd_abs_section_ptr;
01479            break;
01480          case N_SETT:
01481            cache_ptr->symbol.section = obj_textsec (abfd);
01482            break;
01483          case N_SETD:
01484            cache_ptr->symbol.section = obj_datasec (abfd);
01485            break;
01486          case N_SETB:
01487            cache_ptr->symbol.section = obj_bsssec (abfd);
01488            break;
01489          }
01490 
01491        cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
01492       }
01493       break;
01494 
01495     case N_WARNING:
01496       /* This symbol is the text of a warning message.  The next
01497         symbol is the symbol to associate the warning with.  If a
01498         reference is made to that symbol, a warning is issued.  */
01499       cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
01500       cache_ptr->symbol.section = bfd_abs_section_ptr;
01501       break;
01502 
01503     case N_INDR: case N_INDR | N_EXT:
01504       /* An indirect symbol.  This consists of two symbols in a row.
01505         The first symbol is the name of the indirection.  The second
01506         symbol is the name of the target.  A reference to the first
01507         symbol becomes a reference to the second.  */
01508       cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible;
01509       cache_ptr->symbol.section = bfd_ind_section_ptr;
01510       break;
01511 
01512     case N_WEAKU:
01513       cache_ptr->symbol.section = bfd_und_section_ptr;
01514       cache_ptr->symbol.flags = BSF_WEAK;
01515       break;
01516 
01517     case N_WEAKA:
01518       cache_ptr->symbol.section = bfd_abs_section_ptr;
01519       cache_ptr->symbol.flags = BSF_WEAK;
01520       break;
01521 
01522     case N_WEAKT:
01523       cache_ptr->symbol.section = obj_textsec (abfd);
01524       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
01525       cache_ptr->symbol.flags = BSF_WEAK;
01526       break;
01527 
01528     case N_WEAKD:
01529       cache_ptr->symbol.section = obj_datasec (abfd);
01530       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
01531       cache_ptr->symbol.flags = BSF_WEAK;
01532       break;
01533 
01534     case N_WEAKB:
01535       cache_ptr->symbol.section = obj_bsssec (abfd);
01536       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
01537       cache_ptr->symbol.flags = BSF_WEAK;
01538       break;
01539     }
01540 
01541   return TRUE;
01542 }
01543 
01544 /* Set the fields of SYM_POINTER according to CACHE_PTR.  */
01545 
01546 static bfd_boolean
01547 translate_to_native_sym_flags (bfd *abfd,
01548                             asymbol *cache_ptr,
01549                             struct external_nlist *sym_pointer)
01550 {
01551   bfd_vma value = cache_ptr->value;
01552   asection *sec;
01553   bfd_vma off;
01554 
01555   /* Mask out any existing type bits in case copying from one section
01556      to another.  */
01557   sym_pointer->e_type[0] &= ~N_TYPE;
01558 
01559   sec = bfd_get_section (cache_ptr);
01560   off = 0;
01561 
01562   if (sec == NULL)
01563     {
01564       /* This case occurs, e.g., for the *DEBUG* section of a COFF
01565         file.  */
01566       (*_bfd_error_handler)
01567        (_("%s: can not represent section for symbol `%s' in a.out object file format"),
01568         bfd_get_filename (abfd),
01569         cache_ptr->name != NULL ? cache_ptr->name : _("*unknown*"));
01570       bfd_set_error (bfd_error_nonrepresentable_section);
01571       return FALSE;
01572     }
01573 
01574   if (sec->output_section != NULL)
01575     {
01576       off = sec->output_offset;
01577       sec = sec->output_section;
01578     }
01579 
01580   if (bfd_is_abs_section (sec))
01581     sym_pointer->e_type[0] |= N_ABS;
01582   else if (sec == obj_textsec (abfd))
01583     sym_pointer->e_type[0] |= N_TEXT;
01584   else if (sec == obj_datasec (abfd))
01585     sym_pointer->e_type[0] |= N_DATA;
01586   else if (sec == obj_bsssec (abfd))
01587     sym_pointer->e_type[0] |= N_BSS;
01588   else if (bfd_is_und_section (sec))
01589     sym_pointer->e_type[0] = N_UNDF | N_EXT;
01590   else if (bfd_is_ind_section (sec))
01591     sym_pointer->e_type[0] = N_INDR;
01592   else if (bfd_is_com_section (sec))
01593     sym_pointer->e_type[0] = N_UNDF | N_EXT;
01594   else
01595     {
01596       if (aout_section_merge_with_text_p (abfd, sec))
01597        sym_pointer->e_type[0] |= N_TEXT;
01598       else
01599        {
01600           (*_bfd_error_handler)
01601           (_("%s: can not represent section `%s' in a.out object file format"),
01602             bfd_get_filename (abfd), bfd_get_section_name (abfd, sec));
01603           bfd_set_error (bfd_error_nonrepresentable_section);
01604           return FALSE;
01605        }
01606     }
01607 
01608   /* Turn the symbol from section relative to absolute again.  */
01609   value += sec->vma + off;
01610 
01611   if ((cache_ptr->flags & BSF_WARNING) != 0)
01612     sym_pointer->e_type[0] = N_WARNING;
01613 
01614   if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
01615     sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
01616   else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
01617     sym_pointer->e_type[0] |= N_EXT;
01618   else if ((cache_ptr->flags & BSF_LOCAL) != 0)
01619     sym_pointer->e_type[0] &= ~N_EXT;
01620 
01621   if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
01622     {
01623       int type = ((aout_symbol_type *) cache_ptr)->type;
01624 
01625       switch (type)
01626        {
01627        case N_ABS:   type = N_SETA; break;
01628        case N_TEXT:  type = N_SETT; break;
01629        case N_DATA:  type = N_SETD; break;
01630        case N_BSS:   type = N_SETB; break;
01631        }
01632       sym_pointer->e_type[0] = type;
01633     }
01634 
01635   if ((cache_ptr->flags & BSF_WEAK) != 0)
01636     {
01637       int type;
01638 
01639       switch (sym_pointer->e_type[0] & N_TYPE)
01640        {
01641        default:
01642        case N_ABS:   type = N_WEAKA; break;
01643        case N_TEXT:  type = N_WEAKT; break;
01644        case N_DATA:  type = N_WEAKD; break;
01645        case N_BSS:   type = N_WEAKB; break;
01646        case N_UNDF:  type = N_WEAKU; break;
01647        }
01648       sym_pointer->e_type[0] = type;
01649     }
01650 
01651   PUT_WORD (abfd, value, sym_pointer->e_value);
01652 
01653   return TRUE;
01654 }
01655 
01656 /* Native-level interface to symbols.  */
01657 
01658 asymbol *
01659 NAME (aout, make_empty_symbol) (bfd *abfd)
01660 {
01661   bfd_size_type amt = sizeof (aout_symbol_type);
01662 
01663   aout_symbol_type *new = bfd_zalloc (abfd, amt);
01664   if (!new)
01665     return NULL;
01666   new->symbol.the_bfd = abfd;
01667 
01668   return &new->symbol;
01669 }
01670 
01671 /* Translate a set of internal symbols into external symbols.  */
01672 
01673 bfd_boolean
01674 NAME (aout, translate_symbol_table) (bfd *abfd,
01675                                  aout_symbol_type *in,
01676                                  struct external_nlist *ext,
01677                                  bfd_size_type count,
01678                                  char *str,
01679                                  bfd_size_type strsize,
01680                                  bfd_boolean dynamic)
01681 {
01682   struct external_nlist *ext_end;
01683 
01684   ext_end = ext + count;
01685   for (; ext < ext_end; ext++, in++)
01686     {
01687       bfd_vma x;
01688 
01689       x = GET_WORD (abfd, ext->e_strx);
01690       in->symbol.the_bfd = abfd;
01691 
01692       /* For the normal symbols, the zero index points at the number
01693         of bytes in the string table but is to be interpreted as the
01694         null string.  For the dynamic symbols, the number of bytes in
01695         the string table is stored in the __DYNAMIC structure and the
01696         zero index points at an actual string.  */
01697       if (x == 0 && ! dynamic)
01698        in->symbol.name = "";
01699       else if (x < strsize)
01700        in->symbol.name = str + x;
01701       else
01702        return FALSE;
01703 
01704       in->symbol.value = GET_SWORD (abfd,  ext->e_value);
01705       in->desc = H_GET_16 (abfd, ext->e_desc);
01706       in->other = H_GET_8 (abfd, ext->e_other);
01707       in->type = H_GET_8 (abfd,  ext->e_type);
01708       in->symbol.udata.p = NULL;
01709 
01710       if (! translate_from_native_sym_flags (abfd, in))
01711        return FALSE;
01712 
01713       if (dynamic)
01714        in->symbol.flags |= BSF_DYNAMIC;
01715     }
01716 
01717   return TRUE;
01718 }
01719 
01720 /* We read the symbols into a buffer, which is discarded when this
01721    function exits.  We read the strings into a buffer large enough to
01722    hold them all plus all the cached symbol entries.  */
01723 
01724 bfd_boolean
01725 NAME (aout, slurp_symbol_table) (bfd *abfd)
01726 {
01727   struct external_nlist *old_external_syms;
01728   aout_symbol_type *cached;
01729   bfd_size_type cached_size;
01730 
01731   /* If there's no work to be done, don't do any.  */
01732   if (obj_aout_symbols (abfd) != NULL)
01733     return TRUE;
01734 
01735   old_external_syms = obj_aout_external_syms (abfd);
01736 
01737   if (! aout_get_external_symbols (abfd))
01738     return FALSE;
01739 
01740   cached_size = obj_aout_external_sym_count (abfd);
01741   cached_size *= sizeof (aout_symbol_type);
01742   cached = bfd_zmalloc (cached_size);
01743   if (cached == NULL && cached_size != 0)
01744     return FALSE;
01745 
01746   /* Convert from external symbol information to internal.  */
01747   if (! (NAME (aout, translate_symbol_table)
01748         (abfd, cached,
01749          obj_aout_external_syms (abfd),
01750          obj_aout_external_sym_count (abfd),
01751          obj_aout_external_strings (abfd),
01752          obj_aout_external_string_size (abfd),
01753          FALSE)))
01754     {
01755       free (cached);
01756       return FALSE;
01757     }
01758 
01759   bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
01760 
01761   obj_aout_symbols (abfd) = cached;
01762 
01763   /* It is very likely that anybody who calls this function will not
01764      want the external symbol information, so if it was allocated
01765      because of our call to aout_get_external_symbols, we free it up
01766      right away to save space.  */
01767   if (old_external_syms == NULL
01768       && obj_aout_external_syms (abfd) != NULL)
01769     {
01770 #ifdef USE_MMAP
01771       bfd_free_window (&obj_aout_sym_window (abfd));
01772 #else
01773       free (obj_aout_external_syms (abfd));
01774 #endif
01775       obj_aout_external_syms (abfd) = NULL;
01776     }
01777 
01778   return TRUE;
01779 }
01780 
01781 /* We use a hash table when writing out symbols so that we only write
01782    out a particular string once.  This helps particularly when the
01783    linker writes out stabs debugging entries, because each different
01784    contributing object file tends to have many duplicate stabs
01785    strings.
01786 
01787    This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
01788    if BFD_TRADITIONAL_FORMAT is set.  */
01789 
01790 /* Get the index of a string in a strtab, adding it if it is not
01791    already present.  */
01792 
01793 static inline bfd_size_type
01794 add_to_stringtab (bfd *abfd,
01795                 struct bfd_strtab_hash *tab,
01796                 const char *str,
01797                 bfd_boolean copy)
01798 {
01799   bfd_boolean hash;
01800   bfd_size_type index;
01801 
01802   /* An index of 0 always means the empty string.  */
01803   if (str == 0 || *str == '\0')
01804     return 0;
01805 
01806   /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx
01807      doesn't understand a hashed string table.  */
01808   hash = TRUE;
01809   if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
01810     hash = FALSE;
01811 
01812   index = _bfd_stringtab_add (tab, str, hash, copy);
01813 
01814   if (index != (bfd_size_type) -1)
01815     /* Add BYTES_IN_WORD to the return value to account for the
01816        space taken up by the string table size.  */
01817     index += BYTES_IN_WORD;
01818 
01819   return index;
01820 }
01821 
01822 /* Write out a strtab.  ABFD is already at the right location in the
01823    file.  */
01824 
01825 static bfd_boolean
01826 emit_stringtab (bfd *abfd, struct bfd_strtab_hash *tab)
01827 {
01828   bfd_byte buffer[BYTES_IN_WORD];
01829   bfd_size_type amt = BYTES_IN_WORD;
01830 
01831   /* The string table starts with the size.  */
01832   PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer);
01833   if (bfd_bwrite ((void *) buffer, amt, abfd) != amt)
01834     return FALSE;
01835 
01836   return _bfd_stringtab_emit (abfd, tab);
01837 }
01838 
01839 bfd_boolean
01840 NAME (aout, write_syms) (bfd *abfd)
01841 {
01842   unsigned int count ;
01843   asymbol **generic = bfd_get_outsymbols (abfd);
01844   struct bfd_strtab_hash *strtab;
01845 
01846   strtab = _bfd_stringtab_init ();
01847   if (strtab == NULL)
01848     return FALSE;
01849 
01850   for (count = 0; count < bfd_get_symcount (abfd); count++)
01851     {
01852       asymbol *g = generic[count];
01853       bfd_size_type indx;
01854       struct external_nlist nsp;
01855       bfd_size_type amt;
01856 
01857       indx = add_to_stringtab (abfd, strtab, g->name, FALSE);
01858       if (indx == (bfd_size_type) -1)
01859        goto error_return;
01860       PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx);
01861 
01862       if (bfd_asymbol_flavour (g) == abfd->xvec->flavour)
01863        {
01864          H_PUT_16 (abfd, aout_symbol (g)->desc,  nsp.e_desc);
01865          H_PUT_8  (abfd, aout_symbol (g)->other, nsp.e_other);
01866          H_PUT_8  (abfd, aout_symbol (g)->type,  nsp.e_type);
01867        }
01868       else
01869        {
01870          H_PUT_16 (abfd, 0, nsp.e_desc);
01871          H_PUT_8  (abfd, 0, nsp.e_other);
01872          H_PUT_8  (abfd, 0, nsp.e_type);
01873        }
01874 
01875       if (! translate_to_native_sym_flags (abfd, g, &nsp))
01876        goto error_return;
01877 
01878       amt = EXTERNAL_NLIST_SIZE;
01879       if (bfd_bwrite ((void *) &nsp, amt, abfd) != amt)
01880        goto error_return;
01881 
01882       /* NB: `KEEPIT' currently overlays `udata.p', so set this only
01883         here, at the end.  */
01884       g->KEEPIT = count;
01885     }
01886 
01887   if (! emit_stringtab (abfd, strtab))
01888     goto error_return;
01889 
01890   _bfd_stringtab_free (strtab);
01891 
01892   return TRUE;
01893 
01894 error_return:
01895   _bfd_stringtab_free (strtab);
01896   return FALSE;
01897 }
01898 
01899 long
01900 NAME (aout, canonicalize_symtab) (bfd *abfd, asymbol **location)
01901 {
01902   unsigned int counter = 0;
01903   aout_symbol_type *symbase;
01904 
01905   if (!NAME (aout, slurp_symbol_table) (abfd))
01906     return -1;
01907 
01908   for (symbase = obj_aout_symbols (abfd);
01909        counter++ < bfd_get_symcount (abfd);
01910        )
01911     *(location++) = (asymbol *) (symbase++);
01912   *location++ =0;
01913   return bfd_get_symcount (abfd);
01914 }
01915 
01916 /* Standard reloc stuff.  */
01917 /* Output standard relocation information to a file in target byte order.  */
01918 
01919 extern void  NAME (aout, swap_std_reloc_out)
01920   (bfd *, arelent *, struct reloc_std_external *);
01921 
01922 void
01923 NAME (aout, swap_std_reloc_out) (bfd *abfd,
01924                              arelent *g,
01925                              struct reloc_std_external *natptr)
01926 {
01927   int r_index;
01928   asymbol *sym = *(g->sym_ptr_ptr);
01929   int r_extern;
01930   unsigned int r_length;
01931   int r_pcrel;
01932   int r_baserel, r_jmptable, r_relative;
01933   asection *output_section = sym->section->output_section;
01934 
01935   PUT_WORD (abfd, g->address, natptr->r_address);
01936 
01937   r_length = g->howto->size ;      /* Size as a power of two.  */
01938   r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC?  */
01939   /* XXX This relies on relocs coming from a.out files.  */
01940   r_baserel = (g->howto->type & 8) != 0;
01941   r_jmptable = (g->howto->type & 16) != 0;
01942   r_relative = (g->howto->type & 32) != 0;
01943 
01944   /* Name was clobbered by aout_write_syms to be symbol index.  */
01945 
01946   /* If this relocation is relative to a symbol then set the
01947      r_index to the symbols index, and the r_extern bit.
01948 
01949      Absolute symbols can come in in two ways, either as an offset
01950      from the abs section, or as a symbol which has an abs value.
01951      check for that here.  */
01952 
01953   if (bfd_is_com_section (output_section)
01954       || bfd_is_abs_section (output_section)
01955       || bfd_is_und_section (output_section))
01956     {
01957       if (bfd_abs_section_ptr->symbol == sym)
01958        {
01959          /* Whoops, looked like an abs symbol, but is
01960             really an offset from the abs section.  */
01961          r_index = N_ABS;
01962          r_extern = 0;
01963        }
01964       else
01965        {
01966          /* Fill in symbol.  */
01967          r_extern = 1;
01968          r_index = (*(g->sym_ptr_ptr))->KEEPIT;
01969        }
01970     }
01971   else
01972     {
01973       /* Just an ordinary section.  */
01974       r_extern = 0;
01975       r_index  = output_section->target_index;
01976     }
01977 
01978   /* Now the fun stuff.  */
01979   if (bfd_header_big_endian (abfd))
01980     {
01981       natptr->r_index[0] = r_index >> 16;
01982       natptr->r_index[1] = r_index >> 8;
01983       natptr->r_index[2] = r_index;
01984       natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
01985                         | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
01986                         | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
01987                         | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
01988                         | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
01989                         | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
01990     }
01991   else
01992     {
01993       natptr->r_index[2] = r_index >> 16;
01994       natptr->r_index[1] = r_index >> 8;
01995       natptr->r_index[0] = r_index;
01996       natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
01997                         | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
01998                         | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
01999                         | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
02000                         | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
02001                         | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
02002     }
02003 }
02004 
02005 /* Extended stuff.  */
02006 /* Output extended relocation information to a file in target byte order.  */
02007 
02008 extern void NAME (aout, swap_ext_reloc_out)
02009   (bfd *, arelent *, struct reloc_ext_external *);
02010 
02011 void
02012 NAME (aout, swap_ext_reloc_out) (bfd *abfd,
02013                              arelent *g,
02014                              struct reloc_ext_external *natptr)
02015 {
02016   int r_index;
02017   int r_extern;
02018   unsigned int r_type;
02019   bfd_vma r_addend;
02020   asymbol *sym = *(g->sym_ptr_ptr);
02021   asection *output_section = sym->section->output_section;
02022 
02023   PUT_WORD (abfd, g->address, natptr->r_address);
02024 
02025   r_type = (unsigned int) g->howto->type;
02026 
02027   r_addend = g->addend;
02028   if ((sym->flags & BSF_SECTION_SYM) != 0)
02029     r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma;
02030 
02031   /* If this relocation is relative to a symbol then set the
02032      r_index to the symbols index, and the r_extern bit.
02033 
02034      Absolute symbols can come in in two ways, either as an offset
02035      from the abs section, or as a symbol which has an abs value.
02036      check for that here.  */
02037   if (bfd_is_abs_section (bfd_get_section (sym)))
02038     {
02039       r_extern = 0;
02040       r_index = N_ABS;
02041     }
02042   else if ((sym->flags & BSF_SECTION_SYM) == 0)
02043     {
02044       if (bfd_is_und_section (bfd_get_section (sym))
02045          || (sym->flags & BSF_GLOBAL) != 0)
02046        r_extern = 1;
02047       else
02048        r_extern = 0;
02049       r_index = (*(g->sym_ptr_ptr))->KEEPIT;
02050     }
02051   else
02052     {
02053       /* Just an ordinary section.  */
02054       r_extern = 0;
02055       r_index = output_section->target_index;
02056     }
02057 
02058   /* Now the fun stuff.  */
02059   if (bfd_header_big_endian (abfd))
02060     {
02061       natptr->r_index[0] = r_index >> 16;
02062       natptr->r_index[1] = r_index >> 8;
02063       natptr->r_index[2] = r_index;
02064       natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
02065                         | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG));
02066     }
02067   else
02068     {
02069       natptr->r_index[2] = r_index >> 16;
02070       natptr->r_index[1] = r_index >> 8;
02071       natptr->r_index[0] = r_index;
02072       natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
02073                         | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE));
02074     }
02075 
02076   PUT_WORD (abfd, r_addend, natptr->r_addend);
02077 }
02078 
02079 /* BFD deals internally with all things based from the section they're
02080    in. so, something in 10 bytes into a text section  with a base of
02081    50 would have a symbol (.text+10) and know .text vma was 50.
02082 
02083    Aout keeps all it's symbols based from zero, so the symbol would
02084    contain 60. This macro subs the base of each section from the value
02085    to give the true offset from the section.  */
02086 
02087 #define MOVE_ADDRESS(ad)                                       \
02088   if (r_extern)                                                       \
02089     {                                                          \
02090       /* Undefined symbol.  */                                        \
02091       cache_ptr->sym_ptr_ptr = symbols + r_index;                     \
02092       cache_ptr->addend = ad;                                         \
02093     }                                                          \
02094    else                                                               \
02095     {                                                          \
02096       /* Defined, section relative.  Replace symbol with pointer to   \
02097         symbol which points to section.  */                           \
02098       switch (r_index)                                                \
02099        {                                                       \
02100        case N_TEXT:                                            \
02101        case N_TEXT | N_EXT:                                    \
02102          cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr; \
02103          cache_ptr->addend = ad - su->textsec->vma;                   \
02104          break;                                                \
02105        case N_DATA:                                            \
02106        case N_DATA | N_EXT:                                    \
02107          cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr; \
02108          cache_ptr->addend = ad - su->datasec->vma;                   \
02109          break;                                                \
02110        case N_BSS:                                             \
02111        case N_BSS | N_EXT:                                     \
02112          cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr;  \
02113          cache_ptr->addend = ad - su->bsssec->vma;                    \
02114          break;                                                \
02115        default:                                                \
02116        case N_ABS:                                             \
02117        case N_ABS | N_EXT:                                     \
02118          cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;       \
02119          cache_ptr->addend = ad;                               \
02120          break;                                                \
02121        }                                                       \
02122     }
02123 
02124 void
02125 NAME (aout, swap_ext_reloc_in) (bfd *abfd,
02126                             struct reloc_ext_external *bytes,
02127                             arelent *cache_ptr,
02128                             asymbol **symbols,
02129                             bfd_size_type symcount)
02130 {
02131   unsigned int r_index;
02132   int r_extern;
02133   unsigned int r_type;
02134   struct aoutdata *su = &(abfd->tdata.aout_data->a);
02135 
02136   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
02137 
02138   /* Now the fun stuff.  */
02139   if (bfd_header_big_endian (abfd))
02140     {
02141       r_index = (((unsigned int) bytes->r_index[0] << 16)
02142                | ((unsigned int) bytes->r_index[1] << 8)
02143                | bytes->r_index[2]);
02144       r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
02145       r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
02146               >> RELOC_EXT_BITS_TYPE_SH_BIG);
02147     }
02148   else
02149     {
02150       r_index =  (((unsigned int) bytes->r_index[2] << 16)
02151                 | ((unsigned int) bytes->r_index[1] << 8)
02152                 | bytes->r_index[0]);
02153       r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
02154       r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
02155               >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
02156     }
02157 
02158   cache_ptr->howto =  howto_table_ext + r_type;
02159 
02160   /* Base relative relocs are always against the symbol table,
02161      regardless of the setting of r_extern.  r_extern just reflects
02162      whether the symbol the reloc is against is local or global.  */
02163   if (r_type == (unsigned int) RELOC_BASE10
02164       || r_type == (unsigned int) RELOC_BASE13
02165       || r_type == (unsigned int) RELOC_BASE22)
02166     r_extern = 1;
02167 
02168   if (r_extern && r_index > symcount)
02169     {
02170       /* We could arrange to return an error, but it might be useful
02171          to see the file even if it is bad.  */
02172       r_extern = 0;
02173       r_index = N_ABS;
02174     }
02175 
02176   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
02177 }
02178 
02179 void
02180 NAME (aout, swap_std_reloc_in) (bfd *abfd,
02181                             struct reloc_std_external *bytes,
02182                             arelent *cache_ptr,
02183                             asymbol **symbols,
02184                             bfd_size_type symcount)
02185 {
02186   unsigned int r_index;
02187   int r_extern;
02188   unsigned int r_length;
02189   int r_pcrel;
02190   int r_baserel, r_jmptable, r_relative;
02191   struct aoutdata  *su = &(abfd->tdata.aout_data->a);
02192   unsigned int howto_idx;
02193 
02194   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
02195 
02196   /* Now the fun stuff.  */
02197   if (bfd_header_big_endian (abfd))
02198     {
02199       r_index = (((unsigned int) bytes->r_index[0] << 16)
02200                | ((unsigned int) bytes->r_index[1] << 8)
02201                | bytes->r_index[2]);
02202       r_extern  = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
02203       r_pcrel   = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
02204       r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
02205       r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
02206       r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
02207       r_length  = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
02208                  >> RELOC_STD_BITS_LENGTH_SH_BIG);
02209     }
02210   else
02211     {
02212       r_index = (((unsigned int) bytes->r_index[2] << 16)
02213                | ((unsigned int) bytes->r_index[1] << 8)
02214                | bytes->r_index[0]);
02215       r_extern  = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
02216       r_pcrel   = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
02217       r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
02218       r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
02219       r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
02220       r_length  = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
02221                  >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
02222     }
02223 
02224   howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel
02225               + 16 * r_jmptable + 32 * r_relative);
02226   BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
02227   cache_ptr->howto =  howto_table_std + howto_idx;
02228   BFD_ASSERT (cache_ptr->howto->type != (unsigned int) -1);
02229 
02230   /* Base relative relocs are always against the symbol table,
02231      regardless of the setting of r_extern.  r_extern just reflects
02232      whether the symbol the reloc is against is local or global.  */
02233   if (r_baserel)
02234     r_extern = 1;
02235 
02236   if (r_extern && r_index > symcount)
02237     {
02238       /* We could arrange to return an error, but it might be useful
02239          to see the file even if it is bad.  */
02240       r_extern = 0;
02241       r_index = N_ABS;
02242     }
02243 
02244   MOVE_ADDRESS (0);
02245 }
02246 
02247 /* Read and swap the relocs for a section.  */
02248 
02249 bfd_boolean
02250 NAME (aout, slurp_reloc_table) (bfd *abfd, sec_ptr asect, asymbol **symbols)
02251 {
02252   bfd_size_type count;
02253   bfd_size_type reloc_size;
02254   void * relocs;
02255   arelent *reloc_cache;
02256   size_t each_size;
02257   unsigned int counter = 0;
02258   arelent *cache_ptr;
02259   bfd_size_type amt;
02260 
02261   if (asect->relocation)
02262     return TRUE;
02263 
02264   if (asect->flags & SEC_CONSTRUCTOR)
02265     return TRUE;
02266 
02267   if (asect == obj_datasec (abfd))
02268     reloc_size = exec_hdr (abfd)->a_drsize;
02269   else if (asect == obj_textsec (abfd))
02270     reloc_size = exec_hdr (abfd)->a_trsize;
02271   else if (asect == obj_bsssec (abfd))
02272     reloc_size = 0;
02273   else
02274     {
02275       bfd_set_error (bfd_error_invalid_operation);
02276       return FALSE;
02277     }
02278 
02279   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
02280     return FALSE;
02281 
02282   each_size = obj_reloc_entry_size (abfd);
02283 
02284   count = reloc_size / each_size;
02285 
02286   amt = count * sizeof (arelent);
02287   reloc_cache = bfd_zmalloc (amt);
02288   if (reloc_cache == NULL && count != 0)
02289     return FALSE;
02290 
02291   relocs = bfd_malloc (reloc_size);
02292   if (relocs == NULL && reloc_size != 0)
02293     {
02294       free (reloc_cache);
02295       return FALSE;
02296     }
02297 
02298   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
02299     {
02300       free (relocs);
02301       free (reloc_cache);
02302       return FALSE;
02303     }
02304 
02305   cache_ptr = reloc_cache;
02306   if (each_size == RELOC_EXT_SIZE)
02307     {
02308       struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
02309 
02310       for (; counter < count; counter++, rptr++, cache_ptr++)
02311        MY_swap_ext_reloc_in (abfd, rptr, cache_ptr, symbols,
02312                            (bfd_size_type) bfd_get_symcount (abfd));
02313     }
02314   else
02315     {
02316       struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
02317 
02318       for (; counter < count; counter++, rptr++, cache_ptr++)
02319        MY_swap_std_reloc_in (abfd, rptr, cache_ptr, symbols,
02320                            (bfd_size_type) bfd_get_symcount (abfd));
02321     }
02322 
02323   free (relocs);
02324 
02325   asect->relocation = reloc_cache;
02326   asect->reloc_count = cache_ptr - reloc_cache;
02327 
02328   return TRUE;
02329 }
02330 
02331 /* Write out a relocation section into an object file.  */
02332 
02333 bfd_boolean
02334 NAME (aout, squirt_out_relocs) (bfd *abfd, asection *section)
02335 {
02336   arelent **generic;
02337   unsigned char *native, *natptr;
02338   size_t each_size;
02339 
02340   unsigned int count = section->reloc_count;
02341   bfd_size_type natsize;
02342 
02343   if (count == 0 || section->orelocation == NULL)
02344     return TRUE;
02345 
02346   each_size = obj_reloc_entry_size (abfd);
02347   natsize = (bfd_size_type) each_size * count;
02348   native = bfd_zalloc (abfd, natsize);
02349   if (!native)
02350     return FALSE;
02351 
02352   generic = section->orelocation;
02353 
02354   if (each_size == RELOC_EXT_SIZE)
02355     {
02356       for (natptr = native;
02357           count != 0;
02358           --count, natptr += each_size, ++generic)
02359        MY_swap_ext_reloc_out (abfd, *generic,
02360                             (struct reloc_ext_external *) natptr);
02361     }
02362   else
02363     {
02364       for (natptr = native;
02365           count != 0;
02366           --count, natptr += each_size, ++generic)
02367        MY_swap_std_reloc_out (abfd, *generic,
02368                             (struct reloc_std_external *) natptr);
02369     }
02370 
02371   if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
02372     {
02373       bfd_release (abfd, native);
02374       return FALSE;
02375     }
02376   bfd_release (abfd, native);
02377 
02378   return TRUE;
02379 }
02380 
02381 /* This is stupid.  This function should be a boolean predicate.  */
02382 
02383 long
02384 NAME (aout, canonicalize_reloc) (bfd *abfd,
02385                              sec_ptr section,
02386                              arelent **relptr,
02387                              asymbol **symbols)
02388 {
02389   arelent *tblptr = section->relocation;
02390   unsigned int count;
02391 
02392   if (section == obj_bsssec (abfd))
02393     {
02394       *relptr = NULL;
02395       return 0;
02396     }
02397 
02398   if (!(tblptr || NAME (aout, slurp_reloc_table) (abfd, section, symbols)))
02399     return -1;
02400 
02401   if (section->flags & SEC_CONSTRUCTOR)
02402     {
02403       arelent_chain *chain = section->constructor_chain;
02404       for (count = 0; count < section->reloc_count; count ++)
02405        {
02406          *relptr ++ = &chain->relent;
02407          chain = chain->next;
02408        }
02409     }
02410   else
02411     {
02412       tblptr = section->relocation;
02413 
02414       for (count = 0; count++ < section->reloc_count; )
02415        {
02416          *relptr++ = tblptr++;
02417        }
02418     }
02419   *relptr = 0;
02420 
02421   return section->reloc_count;
02422 }
02423 
02424 long
02425 NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
02426 {
02427   if (bfd_get_format (abfd) != bfd_object)
02428     {
02429       bfd_set_error (bfd_error_invalid_operation);
02430       return -1;
02431     }
02432 
02433   if (asect->flags & SEC_CONSTRUCTOR)
02434     return sizeof (arelent *) * (asect->reloc_count + 1);
02435 
02436   if (asect == obj_datasec (abfd))
02437     return sizeof (arelent *)
02438       * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd))
02439         + 1);
02440 
02441   if (asect == obj_textsec (abfd))
02442     return sizeof (arelent *)
02443       * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd))
02444         + 1);
02445 
02446   if (asect == obj_bsssec (abfd))
02447     return sizeof (arelent *);
02448 
02449   if (asect == obj_bsssec (abfd))
02450     return 0;
02451 
02452   bfd_set_error (bfd_error_invalid_operation);
02453   return -1;
02454 }
02455 
02456 long
02457 NAME (aout, get_symtab_upper_bound) (bfd *abfd)
02458 {
02459   if (!NAME (aout, slurp_symbol_table) (abfd))
02460     return -1;
02461 
02462   return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
02463 }
02464 
02465 alent *
02466 NAME (aout, get_lineno) (bfd *ignore_abfd ATTRIBUTE_UNUSED,
02467                       asymbol *ignore_symbol ATTRIBUTE_UNUSED)
02468 {
02469   return NULL;
02470 }
02471 
02472 void
02473 NAME (aout, get_symbol_info) (bfd *ignore_abfd ATTRIBUTE_UNUSED,
02474                            asymbol *symbol,
02475                            symbol_info *ret)
02476 {
02477   bfd_symbol_info (symbol, ret);
02478 
02479   if (ret->type == '?')
02480     {
02481       int type_code = aout_symbol (symbol)->type & 0xff;
02482       const char *stab_name = bfd_get_stab_name (type_code);
02483       static char buf[10];
02484 
02485       if (stab_name == NULL)
02486        {
02487          sprintf (buf, "(%d)", type_code);
02488          stab_name = buf;
02489        }
02490       ret->type = '-';
02491       ret->stab_type = type_code;
02492       ret->stab_other = (unsigned) (aout_symbol (symbol)->other & 0xff);
02493       ret->stab_desc = (unsigned) (aout_symbol (symbol)->desc & 0xffff);
02494       ret->stab_name = stab_name;
02495     }
02496 }
02497 
02498 void
02499 NAME (aout, print_symbol) (bfd *abfd,
02500                         void * afile,
02501                         asymbol *symbol,
02502                         bfd_print_symbol_type how)
02503 {
02504   FILE *file = (FILE *)afile;
02505 
02506   switch (how)
02507     {
02508     case bfd_print_symbol_name:
02509       if (symbol->name)
02510        fprintf (file,"%s", symbol->name);
02511       break;
02512     case bfd_print_symbol_more:
02513       fprintf (file,"%4x %2x %2x",
02514               (unsigned) (aout_symbol (symbol)->desc & 0xffff),
02515               (unsigned) (aout_symbol (symbol)->other & 0xff),
02516               (unsigned) (aout_symbol (symbol)->type));
02517       break;
02518     case bfd_print_symbol_all:
02519       {
02520        const char *section_name = symbol->section->name;
02521 
02522        bfd_print_symbol_vandf (abfd, (void *)file, symbol);
02523 
02524        fprintf (file," %-5s %04x %02x %02x",
02525                section_name,
02526                (unsigned) (aout_symbol (symbol)->desc & 0xffff),
02527                (unsigned) (aout_symbol (symbol)->other & 0xff),
02528                (unsigned) (aout_symbol (symbol)->type & 0xff));
02529        if (symbol->name)
02530          fprintf (file," %s", symbol->name);
02531       }
02532       break;
02533     }
02534 }
02535 
02536 /* If we don't have to allocate more than 1MB to hold the generic
02537    symbols, we use the generic minisymbol methord: it's faster, since
02538    it only translates the symbols once, not multiple times.  */
02539 #define MINISYM_THRESHOLD (1000000 / sizeof (asymbol))
02540 
02541 /* Read minisymbols.  For minisymbols, we use the unmodified a.out
02542    symbols.  The minisymbol_to_symbol function translates these into
02543    BFD asymbol structures.  */
02544 
02545 long
02546 NAME (aout, read_minisymbols) (bfd *abfd,
02547                             bfd_boolean dynamic,
02548                             void * *minisymsp,
02549                             unsigned int *sizep)
02550 {
02551   if (dynamic)
02552     /* We could handle the dynamic symbols here as well, but it's
02553        easier to hand them off.  */
02554     return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
02555 
02556   if (! aout_get_external_symbols (abfd))
02557     return -1;
02558 
02559   if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
02560     return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
02561 
02562   *minisymsp = (void *) obj_aout_external_syms (abfd);
02563 
02564   /* By passing the external symbols back from this routine, we are
02565      giving up control over the memory block.  Clear
02566      obj_aout_external_syms, so that we do not try to free it
02567      ourselves.  */
02568   obj_aout_external_syms (abfd) = NULL;
02569 
02570   *sizep = EXTERNAL_NLIST_SIZE;
02571   return obj_aout_external_sym_count (abfd);
02572 }
02573 
02574 /* Convert a minisymbol to a BFD asymbol.  A minisymbol is just an
02575    unmodified a.out symbol.  The SYM argument is a structure returned
02576    by bfd_make_empty_symbol, which we fill in here.  */
02577 
02578 asymbol *
02579 NAME (aout, minisymbol_to_symbol) (bfd *abfd,
02580                                bfd_boolean dynamic,
02581                                const void * minisym,
02582                                asymbol *sym)
02583 {
02584   if (dynamic
02585       || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
02586     return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym);
02587 
02588   memset (sym, 0, sizeof (aout_symbol_type));
02589 
02590   /* We call translate_symbol_table to translate a single symbol.  */
02591   if (! (NAME (aout, translate_symbol_table)
02592         (abfd,
02593          (aout_symbol_type *) sym,
02594          (struct external_nlist *) minisym,
02595          (bfd_size_type) 1,
02596          obj_aout_external_strings (abfd),
02597          obj_aout_external_string_size (abfd),
02598          FALSE)))
02599     return NULL;
02600 
02601   return sym;
02602 }
02603 
02604 /* Provided a BFD, a section and an offset into the section, calculate
02605    and return the name of the source file and the line nearest to the
02606    wanted location.  */
02607 
02608 bfd_boolean
02609 NAME (aout, find_nearest_line) (bfd *abfd,
02610                             asection *section,
02611                             asymbol **symbols,
02612                             bfd_vma offset,
02613                             const char **filename_ptr,
02614                             const char **functionname_ptr,
02615                             unsigned int *line_ptr)
02616 {
02617   /* Run down the file looking for the filename, function and linenumber.  */
02618   asymbol **p;
02619   const char *directory_name = NULL;
02620   const char *main_file_name = NULL;
02621   const char *current_file_name = NULL;
02622   const char *line_file_name = NULL;      /* Value of current_file_name at line number.  */
02623   const char *line_directory_name = NULL; /* Value of directory_name at line number.  */
02624   bfd_vma low_line_vma = 0;
02625   bfd_vma low_func_vma = 0;
02626   asymbol *func = 0;
02627   bfd_size_type filelen, funclen;
02628   char *buf;
02629 
02630   *filename_ptr = abfd->filename;
02631   *functionname_ptr = 0;
02632   *line_ptr = 0;
02633 
02634   if (symbols != NULL)
02635     {
02636       for (p = symbols; *p; p++)
02637        {
02638          aout_symbol_type  *q = (aout_symbol_type *) (*p);
02639        next:
02640          switch (q->type)
02641            {
02642            case N_TEXT:
02643              /* If this looks like a file name symbol, and it comes after
02644                the line number we have found so far, but before the
02645                offset, then we have probably not found the right line
02646                number.  */
02647              if (q->symbol.value <= offset
02648                 && ((q->symbol.value > low_line_vma
02649                      && (line_file_name != NULL
02650                         || *line_ptr != 0))
02651                     || (q->symbol.value > low_func_vma
02652                        && func != NULL)))
02653               {
02654                 const char *symname;
02655 
02656                 symname = q->symbol.name;
02657                 if (strcmp (symname + strlen (symname) - 2, ".o") == 0)
02658                   {
02659                     if (q->symbol.value > low_line_vma)
02660                      {
02661                        *line_ptr = 0;
02662                        line_file_name = NULL;
02663                      }
02664                     if (q->symbol.value > low_func_vma)
02665                      func = NULL;
02666                   }
02667               }
02668              break;
02669 
02670            case N_SO:
02671              /* If this symbol is less than the offset, but greater than
02672                the line number we have found so far, then we have not
02673                found the right line number.  */
02674              if (q->symbol.value <= offset)
02675               {
02676                 if (q->symbol.value > low_line_vma)
02677                   {
02678                     *line_ptr = 0;
02679                     line_file_name = NULL;
02680                   }
02681                 if (q->symbol.value > low_func_vma)
02682                   func = NULL;
02683               }
02684 
02685              main_file_name = current_file_name = q->symbol.name;
02686              /* Look ahead to next symbol to check if that too is an N_SO.  */
02687              p++;
02688              if (*p == NULL)
02689               goto done;
02690              q = (aout_symbol_type *) (*p);
02691              if (q->type != (int)N_SO)
02692               goto next;
02693 
02694              /* Found a second N_SO  First is directory; second is filename.  */
02695              directory_name = current_file_name;
02696              main_file_name = current_file_name = q->symbol.name;
02697              if (obj_textsec (abfd) != section)
02698               goto done;
02699              break;
02700            case N_SOL:
02701              current_file_name = q->symbol.name;
02702              break;
02703 
02704            case N_SLINE:
02705 
02706            case N_DSLINE:
02707            case N_BSLINE:
02708              /* We'll keep this if it resolves nearer than the one we have
02709                already.  */
02710              if (q->symbol.value >= low_line_vma
02711                 && q->symbol.value <= offset)
02712               {
02713                 *line_ptr = q->desc;
02714                 low_line_vma = q->symbol.value;
02715                 line_file_name = current_file_name;
02716                 line_directory_name = directory_name;
02717               }
02718              break;
02719            case N_FUN:
02720              {
02721               /* We'll keep this if it is nearer than the one we have already.  */
02722               if (q->symbol.value >= low_func_vma &&
02723                   q->symbol.value <= offset)
02724                 {
02725                   low_func_vma = q->symbol.value;
02726                   func = (asymbol *)q;
02727                 }
02728               else if (q->symbol.value > offset)
02729                 goto done;
02730              }
02731              break;
02732            }
02733        }
02734     }
02735 
02736  done:
02737   if (*line_ptr != 0)
02738     {
02739       main_file_name = line_file_name;
02740       directory_name = line_directory_name;
02741     }
02742 
02743   if (main_file_name == NULL
02744       || IS_ABSOLUTE_PATH (main_file_name)
02745       || directory_name == NULL)
02746     filelen = 0;
02747   else
02748     filelen = strlen (directory_name) + strlen (main_file_name);
02749 
02750   if (func == NULL)
02751     funclen = 0;
02752   else
02753     funclen = strlen (bfd_asymbol_name (func));
02754 
02755   if (adata (abfd).line_buf != NULL)
02756     free (adata (abfd).line_buf);
02757 
02758   if (filelen + funclen == 0)
02759     adata (abfd).line_buf = buf = NULL;
02760   else
02761     {
02762       buf = bfd_malloc (filelen + funclen + 3);
02763       adata (abfd).line_buf = buf;
02764       if (buf == NULL)
02765        return FALSE;
02766     }
02767 
02768   if (main_file_name != NULL)
02769     {
02770       if (IS_ABSOLUTE_PATH (main_file_name) || directory_name == NULL)
02771        *filename_ptr = main_file_name;
02772       else
02773        {
02774          sprintf (buf, "%s%s", directory_name, main_file_name);
02775          *filename_ptr = buf;
02776          buf += filelen + 1;
02777        }
02778     }
02779 
02780   if (func)
02781     {
02782       const char *function = func->name;
02783       char *colon;
02784 
02785       /* The caller expects a symbol name.  We actually have a
02786         function name, without the leading underscore.  Put the
02787         underscore back in, so that the caller gets a symbol name.  */
02788       if (bfd_get_symbol_leading_char (abfd) == '\0')
02789        strcpy (buf, function);
02790       else
02791        {
02792          buf[0] = bfd_get_symbol_leading_char (abfd);
02793          strcpy (buf + 1, function);
02794        }
02795       /* Have to remove : stuff.  */
02796       colon = strchr (buf, ':');
02797       if (colon != NULL)
02798        *colon = '\0';
02799       *functionname_ptr = buf;
02800     }
02801 
02802   return TRUE;
02803 }
02804 
02805 int
02806 NAME (aout, sizeof_headers) (bfd *abfd,
02807                           struct bfd_link_info *info ATTRIBUTE_UNUSED)
02808 {
02809   return adata (abfd).exec_bytes_size;
02810 }
02811 
02812 /* Free all information we have cached for this BFD.  We can always
02813    read it again later if we need it.  */
02814 
02815 bfd_boolean
02816 NAME (aout, bfd_free_cached_info) (bfd *abfd)
02817 {
02818   asection *o;
02819 
02820   if (bfd_get_format (abfd) != bfd_object
02821       || abfd->tdata.aout_data == NULL)
02822     return TRUE;
02823 
02824 #define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; }
02825   BFCI_FREE (obj_aout_symbols (abfd));
02826 #ifdef USE_MMAP
02827   obj_aout_external_syms (abfd) = 0;
02828   bfd_free_window (&obj_aout_sym_window (abfd));
02829   bfd_free_window (&obj_aout_string_window (abfd));
02830   obj_aout_external_strings (abfd) = 0;
02831 #else
02832   BFCI_FREE (obj_aout_external_syms (abfd));
02833   BFCI_FREE (obj_aout_external_strings (abfd));
02834 #endif
02835   for (o = abfd->sections; o != NULL; o = o->next)
02836     BFCI_FREE (o->relocation);
02837 #undef BFCI_FREE
02838 
02839   return TRUE;
02840 }
02841 
02842 /* a.out link code.  */
02843 
02844 /* Routine to create an entry in an a.out link hash table.  */
02845 
02846 struct bfd_hash_entry *
02847 NAME (aout, link_hash_newfunc) (struct bfd_hash_entry *entry,
02848                             struct bfd_hash_table *table,
02849                             const char *string)
02850 {
02851   struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry;
02852 
02853   /* Allocate the structure if it has not already been allocated by a
02854      subclass.  */
02855   if (ret == NULL)
02856     ret = bfd_hash_allocate (table, sizeof (* ret));
02857   if (ret == NULL)
02858     return NULL;
02859 
02860   /* Call the allocation method of the superclass.  */
02861   ret = ((struct aout_link_hash_entry *)
02862         _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
02863                              table, string));
02864   if (ret)
02865     {
02866       /* Set local fields.  */
02867       ret->written = FALSE;
02868       ret->indx = -1;
02869     }
02870 
02871   return (struct bfd_hash_entry *) ret;
02872 }
02873 
02874 /* Initialize an a.out link hash table.  */
02875 
02876 bfd_boolean
02877 NAME (aout, link_hash_table_init) (struct aout_link_hash_table *table,
02878                                bfd *abfd,
02879                                struct bfd_hash_entry *(*newfunc)
02880                                (struct bfd_hash_entry *, struct bfd_hash_table *,
02881                                 const char *),
02882                                unsigned int entsize)
02883 {
02884   return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
02885 }
02886 
02887 /* Create an a.out link hash table.  */
02888 
02889 struct bfd_link_hash_table *
02890 NAME (aout, link_hash_table_create) (bfd *abfd)
02891 {
02892   struct aout_link_hash_table *ret;
02893   bfd_size_type amt = sizeof (* ret);
02894 
02895   ret = bfd_malloc (amt);
02896   if (ret == NULL)
02897     return NULL;
02898 
02899   if (!NAME (aout, link_hash_table_init) (ret, abfd,
02900                                      NAME (aout, link_hash_newfunc),
02901                                      sizeof (struct aout_link_hash_entry)))
02902     {
02903       free (ret);
02904       return NULL;
02905     }
02906   return &ret->root;
02907 }
02908 
02909 /* Add all symbols from an object file to the hash table.  */
02910 
02911 static bfd_boolean
02912 aout_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
02913 {
02914   bfd_boolean (*add_one_symbol)
02915     (struct bfd_link_info *, bfd *, const char *, flagword, asection *,
02916             bfd_vma, const char *, bfd_boolean, bfd_boolean,
02917             struct bfd_link_hash_entry **);
02918   struct external_nlist *syms;
02919   bfd_size_type sym_count;
02920   char *strings;
02921   bfd_boolean copy;
02922   struct aout_link_hash_entry **sym_hash;
02923   struct external_nlist *p;
02924   struct external_nlist *pend;
02925   bfd_size_type amt;
02926 
02927   syms = obj_aout_external_syms (abfd);
02928   sym_count = obj_aout_external_sym_count (abfd);
02929   strings = obj_aout_external_strings (abfd);
02930   if (info->keep_memory)
02931     copy = FALSE;
02932   else
02933     copy = TRUE;
02934 
02935   if (aout_backend_info (abfd)->add_dynamic_symbols != NULL)
02936     {
02937       if (! ((*aout_backend_info (abfd)->add_dynamic_symbols)
02938             (abfd, info, &syms, &sym_count, &strings)))
02939        return FALSE;
02940     }
02941 
02942   /* We keep a list of the linker hash table entries that correspond
02943      to particular symbols.  We could just look them up in the hash
02944      table, but keeping the list is more efficient.  Perhaps this
02945      should be conditional on info->keep_memory.  */
02946   amt = sym_count * sizeof (struct aout_link_hash_entry *);
02947   sym_hash = bfd_alloc (abfd, amt);
02948   if (sym_hash == NULL && sym_count != 0)
02949     return FALSE;
02950   obj_aout_sym_hashes (abfd) = sym_hash;
02951 
02952   add_one_symbol = aout_backend_info (abfd)->add_one_symbol;
02953   if (add_one_symbol == NULL)
02954     add_one_symbol = _bfd_generic_link_add_one_symbol;
02955 
02956   p = syms;
02957   pend = p + sym_count;
02958   for (; p < pend; p++, sym_hash++)
02959     {
02960       int type;
02961       const char *name;
02962       bfd_vma value;
02963       asection *section;
02964       flagword flags;
02965       const char *string;
02966 
02967       *sym_hash = NULL;
02968 
02969       type = H_GET_8 (abfd, p->e_type);
02970 
02971       /* Ignore debugging symbols.  */
02972       if ((type & N_STAB) != 0)
02973        continue;
02974 
02975       name = strings + GET_WORD (abfd, p->e_strx);
02976       value = GET_WORD (abfd, p->e_value);
02977       flags = BSF_GLOBAL;
02978       string = NULL;
02979       switch (type)
02980        {
02981        default:
02982          abort ();
02983 
02984        case N_UNDF:
02985        case N_ABS:
02986        case N_TEXT:
02987        case N_DATA:
02988        case N_BSS:
02989        case N_FN_SEQ:
02990        case N_COMM:
02991        case N_SETV:
02992        case N_FN:
02993          /* Ignore symbols that are not externally visible.  */
02994          continue;
02995        case N_INDR:
02996          /* Ignore local indirect symbol.  */
02997          ++p;
02998          ++sym_hash;
02999          continue;
03000 
03001        case N_UNDF | N_EXT:
03002          if (value == 0)
03003            {
03004              section = bfd_und_section_ptr;
03005              flags = 0;
03006            }
03007          else
03008            section = bfd_com_section_ptr;
03009          break;
03010        case N_ABS | N_EXT:
03011          section = bfd_abs_section_ptr;
03012          break;
03013        case N_TEXT | N_EXT:
03014          section = obj_textsec (abfd);
03015          value -= bfd_get_section_vma (abfd, section);
03016          break;
03017        case N_DATA | N_EXT:
03018        case N_SETV | N_EXT:
03019          /* Treat N_SETV symbols as N_DATA symbol; see comment in
03020             translate_from_native_sym_flags.  */
03021          section = obj_datasec (abfd);
03022          value -= bfd_get_section_vma (abfd, section);
03023          break;
03024        case N_BSS | N_EXT:
03025          section = obj_bsssec (abfd);
03026          value -= bfd_get_section_vma (abfd, section);
03027          break;
03028        case N_INDR | N_EXT:
03029          /* An indirect symbol.  The next symbol is the symbol
03030             which this one really is.  */
03031          BFD_ASSERT (p + 1 < pend);
03032          ++p;
03033          string = strings + GET_WORD (abfd, p->e_strx);
03034          section = bfd_ind_section_ptr;
03035          flags |= BSF_INDIRECT;
03036          break;
03037        case N_COMM | N_EXT:
03038          section = bfd_com_section_ptr;
03039          break;
03040        case N_SETA: case N_SETA | N_EXT:
03041          section = bfd_abs_section_ptr;
03042          flags |= BSF_CONSTRUCTOR;
03043          break;
03044        case N_SETT: case N_SETT | N_EXT:
03045          section = obj_textsec (abfd);
03046          flags |= BSF_CONSTRUCTOR;
03047          value -= bfd_get_section_vma (abfd, section);
03048          break;
03049        case N_SETD: case N_SETD | N_EXT:
03050          section = obj_datasec (abfd);
03051          flags |= BSF_CONSTRUCTOR;
03052          value -= bfd_get_section_vma (abfd, section);
03053          break;
03054        case N_SETB: case N_SETB | N_EXT:
03055          section = obj_bsssec (abfd);
03056          flags |= BSF_CONSTRUCTOR;
03057          value -= bfd_get_section_vma (abfd, section);
03058          break;
03059        case N_WARNING:
03060          /* A warning symbol.  The next symbol is the one to warn
03061             about.  If there is no next symbol, just look away.  */
03062          if (p + 1 >= pend)
03063            return TRUE;
03064          ++p;
03065          string = name;
03066          name = strings + GET_WORD (abfd, p->e_strx);
03067          section = bfd_und_section_ptr;
03068          flags |= BSF_WARNING;
03069          break;
03070        case N_WEAKU:
03071          section = bfd_und_section_ptr;
03072          flags = BSF_WEAK;
03073          break;
03074        case N_WEAKA:
03075          section = bfd_abs_section_ptr;
03076          flags = BSF_WEAK;
03077          break;
03078        case N_WEAKT:
03079          section = obj_textsec (abfd);
03080          value -= bfd_get_section_vma (abfd, section);
03081          flags = BSF_WEAK;
03082          break;
03083        case N_WEAKD:
03084          section = obj_datasec (abfd);
03085          value -= bfd_get_section_vma (abfd, section);
03086          flags = BSF_WEAK;
03087          break;
03088        case N_WEAKB:
03089          section = obj_bsssec (abfd);
03090          value -= bfd_get_section_vma (abfd, section);
03091          flags = BSF_WEAK;
03092          break;
03093        }
03094 
03095       if (! ((*add_one_symbol)
03096             (info, abfd, name, flags, section, value, string, copy, FALSE,
03097              (struct bfd_link_hash_entry **) sym_hash)))
03098        return FALSE;
03099 
03100       /* Restrict the maximum alignment of a common symbol based on
03101         the architecture, since a.out has no way to represent
03102         alignment requirements of a section in a .o file.  FIXME:
03103         This isn't quite right: it should use the architecture of the
03104         output file, not the input files.  */
03105       if ((*sym_hash)->root.type == bfd_link_hash_common
03106          && ((*sym_hash)->root.u.c.p->alignment_power >
03107              bfd_get_arch_info (abfd)->section_align_power))
03108        (*sym_hash)->root.u.c.p->alignment_power =
03109          bfd_get_arch_info (abfd)->section_align_power;
03110 
03111       /* If this is a set symbol, and we are not building sets, then
03112         it is possible for the hash entry to not have been set.  In
03113         such a case, treat the symbol as not globally defined.  */
03114       if ((*sym_hash)->root.type == bfd_link_hash_new)
03115        {
03116          BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0);
03117          *sym_hash = NULL;
03118        }
03119 
03120       if (type == (N_INDR | N_EXT) || type == N_WARNING)
03121        ++sym_hash;
03122     }
03123 
03124   return TRUE;
03125 }
03126 
03127 /* Free up the internal symbols read from an a.out file.  */
03128 
03129 static bfd_boolean
03130 aout_link_free_symbols (bfd *abfd)
03131 {
03132   if (obj_aout_external_syms (abfd) != NULL)
03133     {
03134 #ifdef USE_MMAP
03135       bfd_free_window (&obj_aout_sym_window (abfd));
03136 #else
03137       free ((void *) obj_aout_external_syms (abfd));
03138 #endif
03139       obj_aout_external_syms (abfd) = NULL;
03140     }
03141   if (obj_aout_external_strings (abfd) != NULL)
03142     {
03143 #ifdef USE_MMAP
03144       bfd_free_window (&obj_aout_string_window (abfd));
03145 #else
03146       free ((void *) obj_aout_external_strings (abfd));
03147 #endif
03148       obj_aout_external_strings (abfd) = NULL;
03149     }
03150   return TRUE;
03151 }
03152 
03153 /* Add symbols from an a.out object file.  */
03154 
03155 static bfd_boolean
03156 aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
03157 {
03158   if (! aout_get_external_symbols (abfd))
03159     return FALSE;
03160   if (! aout_link_add_symbols (abfd, info))
03161     return FALSE;
03162   if (! info->keep_memory)
03163     {
03164       if (! aout_link_free_symbols (abfd))
03165        return FALSE;
03166     }
03167   return TRUE;
03168 }
03169 
03170 /* Look through the internal symbols to see if this object file should
03171    be included in the link.  We should include this object file if it
03172    defines any symbols which are currently undefined.  If this object
03173    file defines a common symbol, then we may adjust the size of the
03174    known symbol but we do not include the object file in the link
03175    (unless there is some other reason to include it).  */
03176 
03177 static bfd_boolean
03178 aout_link_check_ar_symbols (bfd *abfd,
03179                          struct bfd_link_info *info,
03180                          bfd_boolean *pneeded)
03181 {
03182   struct external_nlist *p;
03183   struct external_nlist *pend;
03184   char *strings;
03185 
03186   *pneeded = FALSE;
03187 
03188   /* Look through all the symbols.  */
03189   p = obj_aout_external_syms (abfd);
03190   pend = p + obj_aout_external_sym_count (abfd);
03191   strings = obj_aout_external_strings (abfd);
03192   for (; p < pend; p++)
03193     {
03194       int type = H_GET_8 (abfd, p->e_type);
03195       const char *name;
03196       struct bfd_link_hash_entry *h;
03197 
03198       /* Ignore symbols that are not externally visible.  This is an
03199         optimization only, as we check the type more thoroughly
03200         below.  */
03201       if (((type & N_EXT) == 0
03202           || (type & N_STAB) != 0
03203           || type == N_FN)
03204          && type != N_WEAKA
03205          && type != N_WEAKT
03206          && type != N_WEAKD
03207          && type != N_WEAKB)
03208        {
03209          if (type == N_WARNING
03210              || type == N_INDR)
03211            ++p;
03212          continue;
03213        }
03214 
03215       name = strings + GET_WORD (abfd, p->e_strx);
03216       h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
03217 
03218       /* We are only interested in symbols that are currently
03219         undefined or common.  */
03220       if (h == NULL
03221          || (h->type != bfd_link_hash_undefined
03222              && h->type != bfd_link_hash_common))
03223        {
03224          if (type == (N_INDR | N_EXT))
03225            ++p;
03226          continue;
03227        }
03228 
03229       if (type == (N_TEXT | N_EXT)
03230          || type == (N_DATA | N_EXT)
03231          || type == (N_BSS | N_EXT)
03232          || type == (N_ABS | N_EXT)
03233          || type == (N_INDR | N_EXT))
03234        {
03235          /* This object file defines this symbol.  We must link it
03236             in.  This is true regardless of whether the current
03237             definition of the symbol is undefined or common.
03238 
03239              If the current definition is common, we have a case in
03240             which we have already seen an object file including:
03241                 int a;
03242             and this object file from the archive includes:
03243                 int a = 5;
03244             In such a case, whether to include this object is target
03245              dependant for backward compatibility.
03246 
03247             FIXME: The SunOS 4.1.3 linker will pull in the archive
03248             element if the symbol is defined in the .data section,
03249             but not if it is defined in the .text section.  That
03250             seems a bit crazy to me, and it has not been implemented
03251             yet.  However, it might be correct.  */
03252          if (h->type == bfd_link_hash_common)
03253            {
03254              int skip = 0;
03255 
03256              switch (info->common_skip_ar_aymbols)
03257               {
03258               case bfd_link_common_skip_text:
03259                 skip = (type == (N_TEXT | N_EXT));
03260                 break;
03261               case bfd_link_common_skip_data:
03262                 skip = (type == (N_DATA | N_EXT));
03263                 break;
03264               default:
03265               case bfd_link_common_skip_all:
03266                 skip = 1;
03267                 break;
03268               }
03269 
03270              if (skip)
03271               continue;
03272            }
03273 
03274          if (! (*info->callbacks->add_archive_element) (info, abfd, name))
03275            return FALSE;
03276          *pneeded = TRUE;
03277          return TRUE;
03278        }
03279 
03280       if (type == (N_UNDF | N_EXT))
03281        {
03282          bfd_vma value;
03283 
03284          value = GET_WORD (abfd, p->e_value);
03285          if (value != 0)
03286            {
03287              /* This symbol is common in the object from the archive
03288                file.  */
03289              if (h->type == bfd_link_hash_undefined)
03290               {
03291                 bfd *symbfd;
03292                 unsigned int power;
03293 
03294                 symbfd = h->u.undef.abfd;
03295                 if (symbfd == NULL)
03296                   {
03297                     /* This symbol was created as undefined from
03298                       outside BFD.  We assume that we should link
03299                       in the object file.  This is done for the -u
03300                       option in the linker.  */
03301                     if (! (*info->callbacks->add_archive_element) (info,
03302                                                              abfd,
03303                                                              name))
03304                      return FALSE;
03305                     *pneeded = TRUE;
03306                     return TRUE;
03307                   }
03308                 /* Turn the current link symbol into a common
03309                    symbol.  It is already on the undefs list.  */
03310                 h->type = bfd_link_hash_common;
03311                 h->u.c.p = bfd_hash_allocate (&info->hash->table,
03312                                           sizeof (struct bfd_link_hash_common_entry));
03313                 if (h->u.c.p == NULL)
03314                   return FALSE;
03315 
03316                 h->u.c.size = value;
03317 
03318                 /* FIXME: This isn't quite right.  The maximum
03319                    alignment of a common symbol should be set by the
03320                    architecture of the output file, not of the input
03321                    file.  */
03322                 power = bfd_log2 (value);
03323                 if (power > bfd_get_arch_info (abfd)->section_align_power)
03324                   power = bfd_get_arch_info (abfd)->section_align_power;
03325                 h->u.c.p->alignment_power = power;
03326 
03327                 h->u.c.p->section = bfd_make_section_old_way (symbfd,
03328                                                         "COMMON");
03329               }
03330              else
03331               {
03332                 /* Adjust the size of the common symbol if
03333                    necessary.  */
03334                 if (value > h->u.c.size)
03335                   h->u.c.size = value;
03336               }
03337            }
03338        }
03339 
03340       if (type == N_WEAKA
03341          || type == N_WEAKT
03342          || type == N_WEAKD
03343          || type == N_WEAKB)
03344        {
03345          /* This symbol is weak but defined.  We must pull it in if
03346             the current link symbol is undefined, but we don't want
03347             it if the current link symbol is common.  */
03348          if (h->type == bfd_link_hash_undefined)
03349            {
03350              if (! (*info->callbacks->add_archive_element) (info, abfd, name))
03351               return FALSE;
03352              *pneeded = TRUE;
03353              return TRUE;
03354            }
03355        }
03356     }
03357 
03358   /* We do not need this object file.  */
03359   return TRUE;
03360 }
03361 /* Check a single archive element to see if we need to include it in
03362    the link.  *PNEEDED is set according to whether this element is
03363    needed in the link or not.  This is called from
03364    _bfd_generic_link_add_archive_symbols.  */
03365 
03366 static bfd_boolean
03367 aout_link_check_archive_element (bfd *abfd,
03368                              struct bfd_link_info *info,
03369                              bfd_boolean *pneeded)
03370 {
03371   if (! aout_get_external_symbols (abfd))
03372     return FALSE;
03373 
03374   if (! aout_link_check_ar_symbols (abfd, info, pneeded))
03375     return FALSE;
03376 
03377   if (*pneeded)
03378     {
03379       if (! aout_link_add_symbols (abfd, info))
03380        return FALSE;
03381     }
03382 
03383   if (! info->keep_memory || ! *pneeded)
03384     {
03385       if (! aout_link_free_symbols (abfd))
03386        return FALSE;
03387     }
03388 
03389   return TRUE;
03390 }
03391 
03392 /* Given an a.out BFD, add symbols to the global hash table as
03393    appropriate.  */
03394 
03395 bfd_boolean
03396 NAME (aout, link_add_symbols) (bfd *abfd, struct bfd_link_info *info)
03397 {
03398   switch (bfd_get_format (abfd))
03399     {
03400     case bfd_object:
03401       return aout_link_add_object_symbols (abfd, info);
03402     case bfd_archive:
03403       return _bfd_generic_link_add_archive_symbols
03404        (abfd, info, aout_link_check_archive_element);
03405     default:
03406       bfd_set_error (bfd_error_wrong_format);
03407       return FALSE;
03408     }
03409 }
03410 
03411 /* A hash table used for header files with N_BINCL entries.  */
03412 
03413 struct aout_link_includes_table
03414 {
03415   struct bfd_hash_table root;
03416 };
03417 
03418 /* A linked list of totals that we have found for a particular header
03419    file.  */
03420 
03421 struct aout_link_includes_totals
03422 {
03423   struct aout_link_includes_totals *next;
03424   bfd_vma total;
03425 };
03426 
03427 /* An entry in the header file hash table.  */
03428 
03429 struct aout_link_includes_entry
03430 {
03431   struct bfd_hash_entry root;
03432   /* List of totals we have found for this file.  */
03433   struct aout_link_includes_totals *totals;
03434 };
03435 
03436 /* Look up an entry in an the header file hash table.  */
03437 
03438 #define aout_link_includes_lookup(table, string, create, copy)        \
03439   ((struct aout_link_includes_entry *)                                \
03440    bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
03441 
03442 /* During the final link step we need to pass around a bunch of
03443    information, so we do it in an instance of this structure.  */
03444 
03445 struct aout_final_link_info
03446 {
03447   /* General link information.  */
03448   struct bfd_link_info *info;
03449   /* Output bfd.  */
03450   bfd *output_bfd;
03451   /* Reloc file positions.  */
03452   file_ptr treloff, dreloff;
03453   /* File position of symbols.  */
03454   file_ptr symoff;
03455   /* String table.  */
03456   struct bfd_strtab_hash *strtab;
03457   /* Header file hash table.  */
03458   struct aout_link_includes_table includes;
03459   /* A buffer large enough to hold the contents of any section.  */
03460   bfd_byte *contents;
03461   /* A buffer large enough to hold the relocs of any section.  */
03462   void * relocs;
03463   /* A buffer large enough to hold the symbol map of any input BFD.  */
03464   int *symbol_map;
03465   /* A buffer large enough to hold output symbols of any input BFD.  */
03466   struct external_nlist *output_syms;
03467 };
03468 
03469 /* The function to create a new entry in the header file hash table.  */
03470 
03471 static struct bfd_hash_entry *
03472 aout_link_includes_newfunc (struct bfd_hash_entry *entry,
03473                          struct bfd_hash_table *table,
03474                          const char *string)
03475 {
03476   struct aout_link_includes_entry *ret =
03477     (struct aout_link_includes_entry *) entry;
03478 
03479   /* Allocate the structure if it has not already been allocated by a
03480      subclass.  */
03481   if (ret == NULL)
03482     ret = bfd_hash_allocate (table, sizeof (* ret));
03483   if (ret == NULL)
03484     return NULL;
03485 
03486   /* Call the allocation method of the superclass.  */
03487   ret = ((struct aout_link_includes_entry *)
03488         bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
03489   if (ret)
03490     {
03491       /* Set local fields.  */
03492       ret->totals = NULL;
03493     }
03494 
03495   return (struct bfd_hash_entry *) ret;
03496 }
03497 
03498 /* Write out a symbol that was not associated with an a.out input
03499    object.  */
03500 
03501 static bfd_boolean
03502 aout_link_write_other_symbol (struct aout_link_hash_entry *h, void * data)
03503 {
03504   struct aout_final_link_info *finfo = (struct aout_final_link_info *) data;
03505   bfd *output_bfd;
03506   int type;
03507   bfd_vma val;
03508   struct external_nlist outsym;
03509   bfd_size_type indx;
03510   bfd_size_type amt;
03511 
03512   if (h->root.type == bfd_link_hash_warning)
03513     {
03514       h = (struct aout_link_hash_entry *) h->root.u.i.link;
03515       if (h->root.type == bfd_link_hash_new)
03516        return TRUE;
03517     }
03518 
03519   output_bfd = finfo->output_bfd;
03520 
03521   if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
03522     {
03523       if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
03524             (output_bfd, finfo->info, h)))
03525        {
03526          /* FIXME: No way to handle errors.  */
03527          abort ();
03528        }
03529     }
03530 
03531   if (h->written)
03532     return TRUE;
03533 
03534   h->written = TRUE;
03535 
03536   /* An indx of -2 means the symbol must be written.  */
03537   if (h->indx != -2
03538       && (finfo->info->strip == strip_all
03539          || (finfo->info->strip == strip_some
03540              && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
03541                               FALSE, FALSE) == NULL)))
03542     return TRUE;
03543 
03544   switch (h->root.type)
03545     {
03546     default:
03547     case bfd_link_hash_warning:
03548       abort ();
03549       /* Avoid variable not initialized warnings.  */
03550       return TRUE;
03551     case bfd_link_hash_new:
03552       /* This can happen for set symbols when sets are not being
03553          built.  */
03554       return TRUE;
03555     case bfd_link_hash_undefined:
03556       type = N_UNDF | N_EXT;
03557       val = 0;
03558       break;
03559     case bfd_link_hash_defined:
03560     case bfd_link_hash_defweak:
03561       {
03562        asection *sec;
03563 
03564        sec = h->root.u.def.section->output_section;
03565        BFD_ASSERT (bfd_is_abs_section (sec)
03566                   || sec->owner == output_bfd);
03567        if (sec == obj_textsec (output_bfd))
03568          type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
03569        else if (sec == obj_datasec (output_bfd))
03570          type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
03571        else if (sec == obj_bsssec (output_bfd))
03572          type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
03573        else
03574          type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
03575        type |= N_EXT;
03576        val = (h->root.u.def.value
03577               + sec->vma
03578               + h->root.u.def.section->output_offset);
03579       }
03580       break;
03581     case bfd_link_hash_common:
03582       type = N_UNDF | N_EXT;
03583       val = h->root.u.c.size;
03584       break;
03585     case bfd_link_hash_undefweak:
03586       type = N_WEAKU;
03587       val = 0;
03588     case bfd_link_hash_indirect:
03589       /* We ignore these symbols, since the indirected symbol is
03590         already in the hash table.  */
03591       return TRUE;
03592     }
03593 
03594   H_PUT_8 (output_bfd, type, outsym.e_type);
03595   H_PUT_8 (output_bfd, 0, outsym.e_other);
03596   H_PUT_16 (output_bfd, 0, outsym.e_desc);
03597   indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string,
03598                         FALSE);
03599   if (indx == - (bfd_size_type) 1)
03600     /* FIXME: No way to handle errors.  */
03601     abort ();
03602 
03603   PUT_WORD (output_bfd, indx, outsym.e_strx);
03604   PUT_WORD (output_bfd, val, outsym.e_value);
03605 
03606   amt = EXTERNAL_NLIST_SIZE;
03607   if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0
03608       || bfd_bwrite ((void *) &outsym, amt, output_bfd) != amt)
03609     /* FIXME: No way to handle errors.  */
03610     abort ();
03611 
03612   finfo->symoff += EXTERNAL_NLIST_SIZE;
03613   h->indx = obj_aout_external_sym_count (output_bfd);
03614   ++obj_aout_external_sym_count (output_bfd);
03615 
03616   return TRUE;
03617 }
03618 
03619 /* Handle a link order which is supposed to generate a reloc.  */
03620 
03621 static bfd_boolean
03622 aout_link_reloc_link_order (struct aout_final_link_info *finfo,
03623                          asection *o,
03624                          struct bfd_link_order *p)
03625 {
03626   struct bfd_link_order_reloc *pr;
03627   int r_index;
03628   int r_extern;
03629   reloc_howto_type *howto;
03630   file_ptr *reloff_ptr = NULL;
03631   struct reloc_std_external srel;
03632   struct reloc_ext_external erel;
03633   void * rel_ptr;
03634   bfd_size_type amt;
03635 
03636   pr = p->u.reloc.p;
03637 
03638   if (p->type == bfd_section_reloc_link_order)
03639     {
03640       r_extern = 0;
03641       if (bfd_is_abs_section (pr->u.section))
03642        r_index = N_ABS | N_EXT;
03643       else
03644        {
03645          BFD_ASSERT (pr->u.section->owner == finfo->output_bfd);
03646          r_index = pr->u.section->target_index;
03647        }
03648     }
03649   else
03650     {
03651       struct aout_link_hash_entry *h;
03652 
03653       BFD_ASSERT (p->type == bfd_symbol_reloc_link_order);
03654       r_extern = 1;
03655       h = ((struct aout_link_hash_entry *)
03656           bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info,
03657                                     pr->u.name, FALSE, FALSE, TRUE));
03658       if (h != NULL
03659          && h->indx >= 0)
03660        r_index = h->indx;
03661       else if (h != NULL)
03662        {
03663          /* We decided to strip this symbol, but it turns out that we
03664             can't.  Note that we lose the other and desc information
03665             here.  I don't think that will ever matter for a global
03666             symbol.  */
03667          h->indx = -2;
03668          h->written = FALSE;
03669          if (! aout_link_write_other_symbol (h, (void *) finfo))
03670            return FALSE;
03671          r_index = h->indx;
03672        }
03673       else
03674        {
03675          if (! ((*finfo->info->callbacks->unattached_reloc)
03676                (finfo->info, pr->u.name, NULL, NULL, (bfd_vma) 0)))
03677            return FALSE;
03678          r_index = 0;
03679        }
03680     }
03681 
03682   howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc);
03683   if (howto == 0)
03684     {
03685       bfd_set_error (bfd_error_bad_value);
03686       return FALSE;
03687     }
03688 
03689   if (o == obj_textsec (finfo->output_bfd))
03690     reloff_ptr = &finfo->treloff;
03691   else if (o == obj_datasec (finfo->output_bfd))
03692     reloff_ptr = &finfo->dreloff;
03693   else
03694     abort ();
03695 
03696   if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE)
03697     {
03698 #ifdef MY_put_reloc
03699       MY_put_reloc (finfo->output_bfd, r_extern, r_index, p->offset, howto,
03700                   &srel);
03701 #else
03702       {
03703        int r_pcrel;
03704        int r_baserel;
03705        int r_jmptable;
03706        int r_relative;
03707        int r_length;
03708 
03709        r_pcrel = (int) howto->pc_relative;
03710        r_baserel = (howto->type & 8) != 0;
03711        r_jmptable = (howto->type & 16) != 0;
03712        r_relative = (howto->type & 32) != 0;
03713        r_length = howto->size;
03714 
03715        PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
03716        if (bfd_header_big_endian (finfo->output_bfd))
03717          {
03718            srel.r_index[0] = r_index >> 16;
03719            srel.r_index[1] = r_index >> 8;
03720            srel.r_index[2] = r_index;
03721            srel.r_type[0] =
03722              ((r_extern ?     RELOC_STD_BITS_EXTERN_BIG : 0)
03723               | (r_pcrel ?    RELOC_STD_BITS_PCREL_BIG : 0)
03724               | (r_baserel ?  RELOC_STD_BITS_BASEREL_BIG : 0)
03725               | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
03726               | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
03727               | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
03728          }
03729        else
03730          {
03731            srel.r_index[2] = r_index >> 16;
03732            srel.r_index[1] = r_index >> 8;
03733            srel.r_index[0] = r_index;
03734            srel.r_type[0] =
03735              ((r_extern ?     RELOC_STD_BITS_EXTERN_LITTLE : 0)
03736               | (r_pcrel ?    RELOC_STD_BITS_PCREL_LITTLE : 0)
03737               | (r_baserel ?  RELOC_STD_BITS_BASEREL_LITTLE : 0)
03738               | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
03739               | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
03740               | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
03741          }
03742       }
03743 #endif
03744       rel_ptr = (void *) &srel;
03745 
03746       /* We have to write the addend into the object file, since
03747         standard a.out relocs are in place.  It would be more
03748         reliable if we had the current contents of the file here,
03749         rather than assuming zeroes, but we can't read the file since
03750         it was opened using bfd_openw.  */
03751       if (pr->addend != 0)
03752        {
03753          bfd_size_type size;
03754          bfd_reloc_status_type r;
03755          bfd_byte *buf;
03756          bfd_boolean ok;
03757 
03758          size = bfd_get_reloc_size (howto);
03759          buf = bfd_zmalloc (size);
03760          if (buf == NULL)
03761            return FALSE;
03762          r = MY_relocate_contents (howto, finfo->output_bfd,
03763                                 (bfd_vma) pr->addend, buf);
03764          switch (r)
03765            {
03766            case bfd_reloc_ok:
03767              break;
03768            default:
03769            case bfd_reloc_outofrange:
03770              abort ();
03771            case bfd_reloc_overflow:
03772              if (! ((*finfo->info->callbacks->reloc_overflow)
03773                    (finfo->info, NULL,
03774                     (p->type == bfd_section_reloc_link_order
03775                      ? bfd_section_name (finfo->output_bfd,
03776                                       pr->u.section)
03777                      : pr->u.name),
03778                     howto->name, pr->addend, NULL, NULL, (bfd_vma) 0)))
03779               {
03780                 free (buf);
03781                 return FALSE;
03782               }
03783              break;
03784            }
03785          ok = bfd_set_section_contents (finfo->output_bfd, o, (void *) buf,
03786                                     (file_ptr) p->offset, size);
03787          free (buf);
03788          if (! ok)
03789            return FALSE;
03790        }
03791     }
03792   else
03793     {
03794 #ifdef MY_put_ext_reloc
03795       MY_put_ext_reloc (finfo->output_bfd, r_extern, r_index, p->offset,
03796                      howto, &erel, pr->addend);
03797 #else
03798       PUT_WORD (finfo->output_bfd, p->offset, erel.r_address);
03799 
03800       if (bfd_header_big_endian (finfo->output_bfd))
03801        {
03802          erel.r_index[0] = r_index >> 16;
03803          erel.r_index[1] = r_index >> 8;
03804          erel.r_index[2] = r_index;
03805          erel.r_type[0] =
03806            ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
03807             | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG));
03808        }
03809       else
03810        {
03811          erel.r_index[2] = r_index >> 16;
03812          erel.r_index[1] = r_index >> 8;
03813          erel.r_index[0] = r_index;
03814          erel.r_type[0] =
03815            (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
03816              | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
03817        }
03818 
03819       PUT_WORD (finfo->output_bfd, (bfd_vma) pr->addend, erel.r_addend);
03820 #endif /* MY_put_ext_reloc */
03821 
03822       rel_ptr = (void *) &erel;
03823     }
03824 
03825   amt = obj_reloc_entry_size (finfo->output_bfd);
03826   if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0
03827       || bfd_bwrite (rel_ptr, amt, finfo->output_bfd) != amt)
03828     return FALSE;
03829 
03830   *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd);
03831 
03832   /* Assert that the relocs have not run into the symbols, and that n
03833      the text relocs have not run into the data relocs.  */
03834   BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
03835              && (reloff_ptr != &finfo->treloff
03836                 || (*reloff_ptr
03837                     <= obj_datasec (finfo->output_bfd)->rel_filepos)));
03838 
03839   return TRUE;
03840 }
03841 
03842 /* Get the section corresponding to a reloc index.  */
03843 
03844 static INLINE asection *
03845 aout_reloc_index_to_section (bfd *abfd, int indx)
03846 {
03847   switch (indx & N_TYPE)
03848     {
03849     case N_TEXT:   return obj_textsec (abfd);
03850     case N_DATA:   return obj_datasec (abfd);
03851     case N_BSS:    return obj_bsssec (abfd);
03852     case N_ABS:
03853     case N_UNDF:   return bfd_abs_section_ptr;
03854     default:       abort ();
03855     }
03856   return NULL;
03857 }
03858 
03859 /* Relocate an a.out section using standard a.out relocs.  */
03860 
03861 static bfd_boolean
03862 aout_link_input_section_std (struct aout_final_link_info *finfo,
03863                           bfd *input_bfd,
03864                           asection *input_section,
03865                           struct reloc_std_external *relocs,
03866                           bfd_size_type rel_size,
03867                           bfd_byte *contents)
03868 {
03869   bfd_boolean (*check_dynamic_reloc)
03870     (struct bfd_link_info *, bfd *, asection *,
03871             struct aout_link_hash_entry *, void *, bfd_byte *, bfd_boolean *,
03872             bfd_vma *);
03873   bfd *output_bfd;
03874   bfd_boolean relocatable;
03875   struct external_nlist *syms;
03876   char *strings;
03877   struct aout_link_hash_entry **sym_hashes;
03878   int *symbol_map;
03879   bfd_size_type reloc_count;
03880   struct reloc_std_external *rel;
03881   struct reloc_std_external *rel_end;
03882 
03883   output_bfd = finfo->output_bfd;
03884   check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
03885 
03886   BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE);
03887   BFD_ASSERT (input_bfd->xvec->header_byteorder
03888              == output_bfd->xvec->header_byteorder);
03889 
03890   relocatable = finfo->info->relocatable;
03891   syms = obj_aout_external_syms (input_bfd);
03892   strings = obj_aout_external_strings (input_bfd);
03893   sym_hashes = obj_aout_sym_hashes (input_bfd);
03894   symbol_map = finfo->symbol_map;
03895 
03896   reloc_count = rel_size / RELOC_STD_SIZE;
03897   rel = relocs;
03898   rel_end = rel + reloc_count;
03899   for (; rel < rel_end; rel++)
03900     {
03901       bfd_vma r_addr;
03902       int r_index;
03903       int r_extern;
03904       int r_pcrel;
03905       int r_baserel = 0;
03906       reloc_howto_type *howto;
03907       struct aout_link_hash_entry *h = NULL;
03908       bfd_vma relocation;
03909       bfd_reloc_status_type r;
03910 
03911       r_addr = GET_SWORD (input_bfd, rel->r_address);
03912 
03913 #ifdef MY_reloc_howto
03914       howto = MY_reloc_howto (input_bfd, rel, r_index, r_extern, r_pcrel);
03915 #else
03916       {
03917        int r_jmptable;
03918        int r_relative;
03919        int r_length;
03920        unsigned int howto_idx;
03921 
03922        if (bfd_header_big_endian (input_bfd))
03923          {
03924            r_index   =  (((unsigned int) rel->r_index[0] << 16)
03925                        | ((unsigned int) rel->r_index[1] << 8)
03926                        | rel->r_index[2]);
03927            r_extern  = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
03928            r_pcrel   = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
03929            r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
03930            r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
03931            r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
03932            r_length  = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
03933                       >> RELOC_STD_BITS_LENGTH_SH_BIG);
03934          }
03935        else
03936          {
03937            r_index   = (((unsigned int) rel->r_index[2] << 16)
03938                       | ((unsigned int) rel->r_index[1] << 8)
03939                       | rel->r_index[0]);
03940            r_extern  = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
03941            r_pcrel   = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
03942            r_baserel = (0 != (rel->r_type[0]
03943                             & RELOC_STD_BITS_BASEREL_LITTLE));
03944            r_jmptable= (0 != (rel->r_type[0]
03945                             & RELOC_STD_BITS_JMPTABLE_LITTLE));
03946            r_relative= (0 != (rel->r_type[0]
03947                             & RELOC_STD_BITS_RELATIVE_LITTLE));
03948            r_length  = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
03949                       >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
03950          }
03951 
03952        howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel
03953                    + 16 * r_jmptable + 32 * r_relative);
03954        BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
03955        howto = howto_table_std + howto_idx;
03956       }
03957 #endif
03958 
03959       if (relocatable)
03960        {
03961          /* We are generating a relocatable output file, and must
03962             modify the reloc accordingly.  */
03963          if (r_extern)
03964            {
03965              /* If we know the symbol this relocation is against,
03966                convert it into a relocation against a section.  This
03967                is what the native linker does.  */
03968              h = sym_hashes[r_index];
03969              if (h != NULL
03970                 && (h->root.type == bfd_link_hash_defined
03971                     || h->root.type == bfd_link_hash_defweak))
03972               {
03973                 asection *output_section;
03974 
03975                 /* Change the r_extern value.  */
03976                 if (bfd_header_big_endian (output_bfd))
03977                   rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG;
03978                 else
03979                   rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE;
03980 
03981                 /* Compute a new r_index.  */
03982                 output_section = h->root.u.def.section->output_section;
03983                 if (output_section == obj_textsec (output_bfd))
03984                   r_index = N_TEXT;
03985                 else if (output_section == obj_datasec (output_bfd))
03986                   r_index = N_DATA;
03987                 else if (output_section == obj_bsssec (output_bfd))
03988                   r_index = N_BSS;
03989                 else
03990                   r_index = N_ABS;
03991 
03992                 /* Add the symbol value and the section VMA to the
03993                    addend stored in the contents.  */
03994                 relocation = (h->root.u.def.value
03995                             + output_section->vma
03996                             + h->root.u.def.section->output_offset);
03997               }
03998              else
03999               {
04000                 /* We must change r_index according to the symbol
04001                    map.  */
04002                 r_index = symbol_map[r_index];
04003 
04004                 if (r_index == -1)
04005                   {
04006                     if (h != NULL)
04007                      {
04008                        /* We decided to strip this symbol, but it
04009                              turns out that we can't.  Note that we
04010                              lose the other and desc information here.
04011                              I don't think that will ever matter for a
04012                              global symbol.  */
04013                        if (h->indx < 0)
04014                          {
04015                            h->indx = -2;
04016                            h->written = FALSE;
04017                            if (! aout_link_write_other_symbol (h,
04018                                                           (void *) finfo))
04019                             return FALSE;
04020                          }
04021                        r_index = h->indx;
04022                      }
04023                     else
04024                      {
04025                        const char *name;
04026 
04027                        name = strings + GET_WORD (input_bfd,
04028                                                syms[r_index].e_strx);
04029                        if (! ((*finfo->info->callbacks->unattached_reloc)
04030                              (finfo->info, name, input_bfd, input_section,
04031                               r_addr)))
04032                          return FALSE;
04033                        r_index = 0;
04034                      }
04035                   }
04036 
04037                 relocation = 0;
04038               }
04039 
04040              /* Write out the new r_index value.  */
04041              if (bfd_header_big_endian (output_bfd))
04042               {
04043                 rel->r_index[0] = r_index >> 16;
04044                 rel->r_index[1] = r_index >> 8;
04045                 rel->r_index[2] = r_index;
04046               }
04047              else
04048               {
04049                 rel->r_index[2] = r_index >> 16;
04050                 rel->r_index[1] = r_index >> 8;
04051                 rel->r_index[0] = r_index;
04052               }
04053            }
04054          else
04055            {
04056              asection *section;
04057 
04058              /* This is a relocation against a section.  We must
04059                adjust by the amount that the section moved.  */
04060              section = aout_reloc_index_to_section (input_bfd, r_index);
04061              relocation = (section->output_section->vma
04062                          + section->output_offset
04063                          - section->vma);
04064            }
04065 
04066          /* Change the address of the relocation.  */
04067          PUT_WORD (output_bfd,
04068                   r_addr + input_section->output_offset,
04069                   rel->r_address);
04070 
04071          /* Adjust a PC relative relocation by removing the reference
04072             to the original address in the section and including the
04073             reference to the new address.  */
04074          if (r_pcrel)
04075            relocation -= (input_section->output_section->vma
04076                         + input_section->output_offset
04077                         - input_section->vma);
04078 
04079 #ifdef MY_relocatable_reloc
04080          MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr);
04081 #endif
04082 
04083          if (relocation == 0)
04084            r = bfd_reloc_ok;
04085          else
04086            r = MY_relocate_contents (howto,
04087                                    input_bfd, relocation,
04088                                    contents + r_addr);
04089        }
04090       else
04091        {
04092          bfd_boolean hundef;
04093 
04094          /* We are generating an executable, and must do a full
04095             relocation.  */
04096          hundef = FALSE;
04097 
04098          if (r_extern)
04099            {
04100              h = sym_hashes[r_index];
04101 
04102              if (h != NULL
04103                 && (h->root.type == bfd_link_hash_defined
04104                     || h->root.type == bfd_link_hash_defweak))
04105               {
04106                 relocation = (h->root.u.def.value
04107                             + h->root.u.def.section->output_section->vma
04108                             + h->root.u.def.section->output_offset);
04109               }
04110              else if (h != NULL
04111                      && h->root.type == bfd_link_hash_undefweak)
04112               relocation = 0;
04113              else
04114               {
04115                 hundef = TRUE;
04116                 relocation = 0;
04117               }
04118            }
04119          else
04120            {
04121              asection *section;
04122 
04123              section = aout_reloc_index_to_section (input_bfd, r_index);
04124              relocation = (section->output_section->vma
04125                          + section->output_offset
04126                          - section->vma);
04127              if (r_pcrel)
04128               relocation += input_section->vma;
04129            }
04130 
04131          if (check_dynamic_reloc != NULL)
04132            {
04133              bfd_boolean skip;
04134 
04135              if (! ((*check_dynamic_reloc)
04136                    (finfo->info, input_bfd, input_section, h,
04137                     (void *) rel, contents, &skip, &relocation)))
04138               return FALSE;
04139              if (skip)
04140               continue;
04141            }
04142 
04143          /* Now warn if a global symbol is undefined.  We could not
04144              do this earlier, because check_dynamic_reloc might want
04145              to skip this reloc.  */
04146          if (hundef && ! finfo->info->shared && ! r_baserel)
04147            {
04148              const char *name;
04149 
04150              if (h != NULL)
04151               name = h->root.root.string;
04152              else
04153               name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
04154              if (! ((*finfo->info->callbacks->undefined_symbol)
04155                    (finfo->info, name, input_bfd, input_section,
04156                    r_addr, TRUE)))
04157               return FALSE;
04158            }
04159 
04160          r = MY_final_link_relocate (howto,
04161                                   input_bfd, input_section,
04162                                   contents, r_addr, relocation,
04163                                   (bfd_vma) 0);
04164        }
04165 
04166       if (r != bfd_reloc_ok)
04167        {
04168          switch (r)
04169            {
04170            default:
04171            case bfd_reloc_outofrange:
04172              abort ();
04173            case bfd_reloc_overflow:
04174              {
04175               const char *name;
04176 
04177               if (h != NULL)
04178                 name = NULL;
04179               else if (r_extern)
04180                 name = strings + GET_WORD (input_bfd,
04181                                         syms[r_index].e_strx);
04182               else
04183                 {
04184                   asection *s;
04185 
04186                   s = aout_reloc_index_to_section (input_bfd, r_index);
04187                   name = bfd_section_name (input_bfd, s);
04188                 }
04189               if (! ((*finfo->info->callbacks->reloc_overflow)
04190                      (finfo->info, (h ? &h->root : NULL), name,
04191                      howto->name, (bfd_vma) 0, input_bfd,
04192                      input_section, r_addr)))
04193                 return FALSE;
04194              }
04195              break;
04196            }
04197        }
04198     }
04199 
04200   return TRUE;
04201 }
04202 
04203 /* Relocate an a.out section using extended a.out relocs.  */
04204 
04205 static bfd_boolean
04206 aout_link_input_section_ext (struct aout_final_link_info *finfo,
04207                           bfd *input_bfd,
04208                           asection *input_section,
04209                           struct reloc_ext_external *relocs,
04210                           bfd_size_type rel_size,
04211                           bfd_byte *contents)
04212 {
04213   bfd_boolean (*check_dynamic_reloc)
04214     (struct bfd_link_info *, bfd *, asection *,
04215             struct aout_link_hash_entry *, void *, bfd_byte *, bfd_boolean *,
04216             bfd_vma *);
04217   bfd *output_bfd;
04218   bfd_boolean relocatable;
04219   struct external_nlist *syms;
04220   char *strings;
04221   struct aout_link_hash_entry **sym_hashes;
04222   int *symbol_map;
04223   bfd_size_type reloc_count;
04224   struct reloc_ext_external *rel;
04225   struct reloc_ext_external *rel_end;
04226 
04227   output_bfd = finfo->output_bfd;
04228   check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
04229 
04230   BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE);
04231   BFD_ASSERT (input_bfd->xvec->header_byteorder
04232              == output_bfd->xvec->header_byteorder);
04233 
04234   relocatable = finfo->info->relocatable;
04235   syms = obj_aout_external_syms (input_bfd);
04236   strings = obj_aout_external_strings (input_bfd);
04237   sym_hashes = obj_aout_sym_hashes (input_bfd);
04238   symbol_map = finfo->symbol_map;
04239 
04240   reloc_count = rel_size / RELOC_EXT_SIZE;
04241   rel = relocs;
04242   rel_end = rel + reloc_count;
04243   for (; rel < rel_end; rel++)
04244     {
04245       bfd_vma r_addr;
04246       int r_index;
04247       int r_extern;
04248       unsigned int r_type;
04249       bfd_vma r_addend;
04250       struct aout_link_hash_entry *h = NULL;
04251       asection *r_section = NULL;
04252       bfd_vma relocation;
04253 
04254       r_addr = GET_SWORD (input_bfd, rel->r_address);
04255 
04256       if (bfd_header_big_endian (input_bfd))
04257        {
04258          r_index  = (((unsigned int) rel->r_index[0] << 16)
04259                     | ((unsigned int) rel->r_index[1] << 8)
04260                     | rel->r_index[2]);
04261          r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
04262          r_type   = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
04263                     >> RELOC_EXT_BITS_TYPE_SH_BIG);
04264        }
04265       else
04266        {
04267          r_index  = (((unsigned int) rel->r_index[2] << 16)
04268                     | ((unsigned int) rel->r_index[1] << 8)
04269                     | rel->r_index[0]);
04270          r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
04271          r_type   = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
04272                     >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
04273        }
04274 
04275       r_addend = GET_SWORD (input_bfd, rel->r_addend);
04276 
04277       BFD_ASSERT (r_type < TABLE_SIZE (howto_table_ext));
04278 
04279       if (relocatable)
04280        {
04281          /* We are generating a relocatable output file, and must
04282             modify the reloc accordingly.  */
04283          if (r_extern
04284              || r_type == (unsigned int) RELOC_BASE10
04285              || r_type == (unsigned int) RELOC_BASE13
04286              || r_type == (unsigned int) RELOC_BASE22)
04287            {
04288              /* If we know the symbol this relocation is against,
04289                convert it into a relocation against a section.  This
04290                is what the native linker does.  */
04291              if (r_type == (unsigned int) RELOC_BASE10
04292                 || r_type == (unsigned int) RELOC_BASE13
04293                 || r_type == (unsigned int) RELOC_BASE22)
04294               h = NULL;
04295              else
04296               h = sym_hashes[r_index];
04297              if (h != NULL
04298                 && (h->root.type == bfd_link_hash_defined
04299                     || h->root.type == bfd_link_hash_defweak))
04300               {
04301                 asection *output_section;
04302 
04303                 /* Change the r_extern value.  */
04304                 if (bfd_header_big_endian (output_bfd))
04305                   rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG;
04306                 else
04307                   rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE;
04308 
04309                 /* Compute a new r_index.  */
04310                 output_section = h->root.u.def.section->output_section;
04311                 if (output_section == obj_textsec (output_bfd))
04312                   r_index = N_TEXT;
04313                 else if (output_section == obj_datasec (output_bfd))
04314                   r_index = N_DATA;
04315                 else if (output_section == obj_bsssec (output_bfd))
04316                   r_index = N_BSS;
04317                 else
04318                   r_index = N_ABS;
04319 
04320                 /* Add the symbol value and the section VMA to the
04321                    addend.  */
04322                 relocation = (h->root.u.def.value
04323                             + output_section->vma
04324                             + h->root.u.def.section->output_offset);
04325 
04326                 /* Now RELOCATION is the VMA of the final
04327                    destination.  If this is a PC relative reloc,
04328                    then ADDEND is the negative of the source VMA.
04329                    We want to set ADDEND to the difference between
04330                    the destination VMA and the source VMA, which
04331                    means we must adjust RELOCATION by the change in
04332                    the source VMA.  This is done below.  */
04333               }
04334              else
04335               {
04336                 /* We must change r_index according to the symbol
04337                    map.  */
04338                 r_index = symbol_map[r_index];
04339 
04340                 if (r_index == -1)
04341                   {
04342                     if (h != NULL)
04343                      {
04344                        /* We decided to strip this symbol, but it
04345                              turns out that we can't.  Note that we
04346                              lose the other and desc information here.
04347                              I don't think that will ever matter for a
04348                              global symbol.  */
04349                        if (h->indx < 0)
04350                          {
04351                            h->indx = -2;
04352                            h->written = FALSE;
04353                            if (! aout_link_write_other_symbol (h,
04354                                                           (void *) finfo))
04355                             return FALSE;
04356                          }
04357                        r_index = h->indx;
04358                      }
04359                     else
04360                      {
04361                        const char *name;
04362 
04363                        name = strings + GET_WORD (input_bfd,
04364                                                syms[r_index].e_strx);
04365                        if (! ((*finfo->info->callbacks->unattached_reloc)
04366                              (finfo->info, name, input_bfd, input_section,
04367                               r_addr)))
04368                          return FALSE;
04369                        r_index = 0;
04370                      }
04371                   }
04372 
04373                 relocation = 0;
04374 
04375                 /* If this is a PC relative reloc, then the addend
04376                    is the negative of the source VMA.  We must
04377                    adjust it by the change in the source VMA.  This
04378                    is done below.  */
04379               }
04380 
04381              /* Write out the new r_index value.  */
04382              if (bfd_header_big_endian (output_bfd))
04383               {
04384                 rel->r_index[0] = r_index >> 16;
04385                 rel->r_index[1] = r_index >> 8;
04386                 rel->r_index[2] = r_index;
04387               }
04388              else
04389               {
04390                 rel->r_index[2] = r_index >> 16;
04391                 rel->r_index[1] = r_index >> 8;
04392                 rel->r_index[0] = r_index;
04393               }
04394            }
04395          else
04396            {
04397              /* This is a relocation against a section.  We must
04398                adjust by the amount that the section moved.  */
04399              r_section = aout_reloc_index_to_section (input_bfd, r_index);
04400              relocation = (r_section->output_section->vma
04401                          + r_section->output_offset
04402                          - r_section->vma);
04403 
04404              /* If this is a PC relative reloc, then the addend is
04405                the difference in VMA between the destination and the
04406                source.  We have just adjusted for the change in VMA
04407                of the destination, so we must also adjust by the
04408                change in VMA of the source.  This is done below.  */
04409            }
04410 
04411          /* As described above, we must always adjust a PC relative
04412             reloc by the change in VMA of the source.  However, if
04413             pcrel_offset is set, then the addend does not include the
04414             location within the section, in which case we don't need
04415             to adjust anything.  */
04416          if (howto_table_ext[r_type].pc_relative
04417              && ! howto_table_ext[r_type].pcrel_offset)
04418            relocation -= (input_section->output_section->vma
04419                         + input_section->output_offset
04420                         - input_section->vma);
04421 
04422          /* Change the addend if necessary.  */
04423          if (relocation != 0)
04424            PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend);
04425 
04426          /* Change the address of the relocation.  */
04427          PUT_WORD (output_bfd,
04428                   r_addr + input_section->output_offset,
04429                   rel->r_address);
04430        }
04431       else
04432        {
04433          bfd_boolean hundef;
04434          bfd_reloc_status_type r;
04435 
04436          /* We are generating an executable, and must do a full
04437             relocation.  */
04438          hundef = FALSE;
04439 
04440          if (r_extern)
04441            {
04442              h = sym_hashes[r_index];
04443 
04444              if (h != NULL
04445                 && (h->root.type == bfd_link_hash_defined
04446                     || h->root.type == bfd_link_hash_defweak))
04447               {
04448                 relocation = (h->root.u.def.value
04449                             + h->root.u.def.section->output_section->vma
04450                             + h->root.u.def.section->output_offset);
04451               }
04452              else if (h != NULL
04453                      && h->root.type == bfd_link_hash_undefweak)
04454               relocation = 0;
04455              else
04456               {
04457                 hundef = TRUE;
04458                 relocation = 0;
04459               }
04460            }
04461          else if (r_type == (unsigned int) RELOC_BASE10
04462                  || r_type == (unsigned int) RELOC_BASE13
04463                  || r_type == (unsigned int) RELOC_BASE22)
04464            {
04465              struct external_nlist *sym;
04466              int type;
04467 
04468              /* For base relative relocs, r_index is always an index
04469                  into the symbol table, even if r_extern is 0.  */
04470              sym = syms + r_index;
04471              type = H_GET_8 (input_bfd, sym->e_type);
04472              if ((type & N_TYPE) == N_TEXT
04473                 || type == N_WEAKT)
04474               r_section = obj_textsec (input_bfd);
04475              else if ((type & N_TYPE) == N_DATA
04476                      || type == N_WEAKD)
04477               r_section = obj_datasec (input_bfd);
04478              else if ((type & N_TYPE) == N_BSS
04479                      || type == N_WEAKB)
04480               r_section = obj_bsssec (input_bfd);
04481              else if ((type & N_TYPE) == N_ABS
04482                      || type == N_WEAKA)
04483               r_section = bfd_abs_section_ptr;
04484              else
04485               abort ();
04486              relocation = (r_section->output_section->vma
04487                          + r_section->output_offset
04488                          + (GET_WORD (input_bfd, sym->e_value)
04489                             - r_section->vma));
04490            }
04491          else
04492            {
04493              r_section = aout_reloc_index_to_section (input_bfd, r_index);
04494 
04495              /* If this is a PC relative reloc, then R_ADDEND is the
04496                difference between the two vmas, or
04497                  old_dest_sec + old_dest_off - (old_src_sec + old_src_off)
04498                where
04499                  old_dest_sec == section->vma
04500                and
04501                  old_src_sec == input_section->vma
04502                and
04503                  old_src_off == r_addr
04504 
04505                _bfd_final_link_relocate expects RELOCATION +
04506                R_ADDEND to be the VMA of the destination minus
04507                r_addr (the minus r_addr is because this relocation
04508                is not pcrel_offset, which is a bit confusing and
04509                should, perhaps, be changed), or
04510                  new_dest_sec
04511                where
04512                  new_dest_sec == output_section->vma + output_offset
04513                We arrange for this to happen by setting RELOCATION to
04514                  new_dest_sec + old_src_sec - old_dest_sec
04515 
04516                If this is not a PC relative reloc, then R_ADDEND is
04517                simply the VMA of the destination, so we set
04518                RELOCATION to the change in the destination VMA, or
04519                  new_dest_sec - old_dest_sec
04520                */
04521              relocation = (r_section->output_section->vma
04522                          + r_section->output_offset
04523                          - r_section->vma);
04524              if (howto_table_ext[r_type].pc_relative)
04525               relocation += input_section->vma;
04526            }
04527 
04528          if (check_dynamic_reloc != NULL)
04529            {
04530              bfd_boolean skip;
04531 
04532              if (! ((*check_dynamic_reloc)
04533                    (finfo->info, input_bfd, input_section, h,
04534                     (void *) rel, contents, &skip, &relocation)))
04535               return FALSE;
04536              if (skip)
04537               continue;
04538            }
04539 
04540          /* Now warn if a global symbol is undefined.  We could not
04541              do this earlier, because check_dynamic_reloc might want
04542              to skip this reloc.  */
04543          if (hundef
04544              && ! finfo->info->shared
04545              && r_type != (unsigned int) RELOC_BASE10
04546              && r_type != (unsigned int) RELOC_BASE13
04547              && r_type != (unsigned int) RELOC_BASE22)
04548            {
04549              const char *name;
04550 
04551              if (h != NULL)
04552               name = h->root.root.string;
04553              else
04554               name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
04555              if (! ((*finfo->info->callbacks->undefined_symbol)
04556                    (finfo->info, name, input_bfd, input_section,
04557                    r_addr, TRUE)))
04558               return FALSE;
04559            }
04560 
04561          if (r_type != (unsigned int) RELOC_SPARC_REV32)
04562            r = MY_final_link_relocate (howto_table_ext + r_type,
04563                                    input_bfd, input_section,
04564                                    contents, r_addr, relocation,
04565                                    r_addend);
04566          else
04567            {
04568              bfd_vma x;
04569 
04570              x = bfd_get_32 (input_bfd, contents + r_addr);
04571              x = x + relocation + r_addend;
04572              bfd_putl32 (/*input_bfd,*/ x, contents + r_addr);
04573              r = bfd_reloc_ok;
04574            }
04575 
04576          if (r != bfd_reloc_ok)
04577            {
04578              switch (r)
04579               {
04580               default:
04581               case bfd_reloc_outofrange:
04582                 abort ();
04583               case bfd_reloc_overflow:
04584                 {
04585                   const char *name;
04586 
04587                   if (h != NULL)
04588                     name = NULL;
04589                   else if (r_extern
04590                           || r_type == (unsigned int) RELOC_BASE10
04591                           || r_type == (unsigned int) RELOC_BASE13
04592                           || r_type == (unsigned int) RELOC_BASE22)
04593                     name = strings + GET_WORD (input_bfd,
04594                                            syms[r_index].e_strx);
04595                   else
04596                     {
04597                      asection *s;
04598 
04599                      s = aout_reloc_index_to_section (input_bfd, r_index);
04600                      name = bfd_section_name (input_bfd, s);
04601                     }
04602                   if (! ((*finfo->info->callbacks->reloc_overflow)
04603                         (finfo->info, (h ? &h->root : NULL), name,
04604                          howto_table_ext[r_type].name,
04605                          r_addend, input_bfd, input_section, r_addr)))
04606                     return FALSE;
04607                 }
04608                 break;
04609               }
04610            }
04611        }
04612     }
04613 
04614   return TRUE;
04615 }
04616 
04617 /* Link an a.out section into the output file.  */
04618 
04619 static bfd_boolean
04620 aout_link_input_section (struct aout_final_link_info *finfo,
04621                       bfd *input_bfd,
04622                       asection *input_section,
04623                       file_ptr *reloff_ptr,
04624                       bfd_size_type rel_size)
04625 {
04626   bfd_size_type input_size;
04627   void * relocs;
04628 
04629   /* Get the section contents.  */
04630   input_size = input_section->size;
04631   if (! bfd_get_section_contents (input_bfd, input_section,
04632                               (void *) finfo->contents,
04633                               (file_ptr) 0, input_size))
04634     return FALSE;
04635 
04636   /* Read in the relocs if we haven't already done it.  */
04637   if (aout_section_data (input_section) != NULL
04638       && aout_section_data (input_section)->relocs != NULL)
04639     relocs = aout_section_data (input_section)->relocs;
04640   else
04641     {
04642       relocs = finfo->relocs;
04643       if (rel_size > 0)
04644        {
04645          if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
04646              || bfd_bread (relocs, rel_size, input_bfd) != rel_size)
04647            return FALSE;
04648        }
04649     }
04650 
04651   /* Relocate the section contents.  */
04652   if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
04653     {
04654       if (! aout_link_input_section_std (finfo, input_bfd, input_section,
04655                                     (struct reloc_std_external *) relocs,
04656                                     rel_size, finfo->contents))
04657        return FALSE;
04658     }
04659   else
04660     {
04661       if (! aout_link_input_section_ext (finfo, input_bfd, input_section,
04662                                     (struct reloc_ext_external *) relocs,
04663                                     rel_size, finfo->contents))
04664        return FALSE;
04665     }
04666 
04667   /* Write out the section contents.  */
04668   if (! bfd_set_section_contents (finfo->output_bfd,
04669                               input_section->output_section,
04670                               (void *) finfo->contents,
04671                               (file_ptr) input_section->output_offset,
04672                               input_size))
04673     return FALSE;
04674 
04675   /* If we are producing relocatable output, the relocs were
04676      modified, and we now write them out.  */
04677   if (finfo->info->relocatable && rel_size > 0)
04678     {
04679       if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
04680        return FALSE;
04681       if (bfd_bwrite (relocs, rel_size, finfo->output_bfd) != rel_size)
04682        return FALSE;
04683       *reloff_ptr += rel_size;
04684 
04685       /* Assert that the relocs have not run into the symbols, and
04686         that if these are the text relocs they have not run into the
04687         data relocs.  */
04688       BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
04689                 && (reloff_ptr != &finfo->treloff
04690                     || (*reloff_ptr
04691                        <= obj_datasec (finfo->output_bfd)->rel_filepos)));
04692     }
04693 
04694   return TRUE;
04695 }
04696 
04697 /* Adjust and write out the symbols for an a.out file.  Set the new
04698    symbol indices into a symbol_map.  */
04699 
04700 static bfd_boolean
04701 aout_link_write_symbols (struct aout_final_link_info *finfo, bfd *input_bfd)
04702 {
04703   bfd *output_bfd;
04704   bfd_size_type sym_count;
04705   char *strings;
04706   enum bfd_link_strip strip;
04707   enum bfd_link_discard discard;
04708   struct external_nlist *outsym;
04709   bfd_size_type strtab_index;
04710   struct external_nlist *sym;
04711   struct external_nlist *sym_end;
04712   struct aout_link_hash_entry **sym_hash;
04713   int *symbol_map;
04714   bfd_boolean pass;
04715   bfd_boolean skip_next;
04716 
04717   output_bfd = finfo->output_bfd;
04718   sym_count = obj_aout_external_sym_count (input_bfd);
04719   strings = obj_aout_external_strings (input_bfd);
04720   strip = finfo->info->strip;
04721   discard = finfo->info->discard;
04722   outsym = finfo->output_syms;
04723 
04724   /* First write out a symbol for this object file, unless we are
04725      discarding such symbols.  */
04726   if (strip != strip_all
04727       && (strip != strip_some
04728          || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename,
04729                            FALSE, FALSE) != NULL)
04730       && discard != discard_all)
04731     {
04732       H_PUT_8 (output_bfd, N_TEXT, outsym->e_type);
04733       H_PUT_8 (output_bfd, 0, outsym->e_other);
04734       H_PUT_16 (output_bfd, 0, outsym->e_desc);
04735       strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
04736                                    input_bfd->filename, FALSE);
04737       if (strtab_index == (bfd_size_type) -1)
04738        return FALSE;
04739       PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
04740       PUT_WORD (output_bfd,
04741               (bfd_get_section_vma (output_bfd,
04742                                   obj_textsec (input_bfd)->output_section)
04743                + obj_textsec (input_bfd)->output_offset),
04744               outsym->e_value);
04745       ++obj_aout_external_sym_count (output_bfd);
04746       ++outsym;
04747     }
04748 
04749   pass = FALSE;
04750   skip_next = FALSE;
04751   sym = obj_aout_external_syms (input_bfd);
04752   sym_end = sym + sym_count;
04753   sym_hash = obj_aout_sym_hashes (input_bfd);
04754   symbol_map = finfo->symbol_map;
04755   memset (symbol_map, 0, (size_t) sym_count * sizeof *symbol_map);
04756   for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
04757     {
04758       const char *name;
04759       int type;
04760       struct aout_link_hash_entry *h;
04761       bfd_boolean skip;
04762       asection *symsec;
04763       bfd_vma val = 0;
04764       bfd_boolean copy;
04765 
04766       /* We set *symbol_map to 0 above for all symbols.  If it has
04767          already been set to -1 for this symbol, it means that we are
04768          discarding it because it appears in a duplicate header file.
04769          See the N_BINCL code below.  */
04770       if (*symbol_map == -1)
04771        continue;
04772 
04773       /* Initialize *symbol_map to -1, which means that the symbol was
04774          not copied into the output file.  We will change it later if
04775          we do copy the symbol over.  */
04776       *symbol_map = -1;
04777 
04778       type = H_GET_8 (input_bfd, sym->e_type);
04779       name = strings + GET_WORD (input_bfd, sym->e_strx);
04780 
04781       h = NULL;
04782 
04783       if (pass)
04784        {
04785          /* Pass this symbol through.  It is the target of an
04786             indirect or warning symbol.  */
04787          val = GET_WORD (input_bfd, sym->e_value);
04788          pass = FALSE;
04789        }
04790       else if (skip_next)
04791        {
04792          /* Skip this symbol, which is the target of an indirect
04793             symbol that we have changed to no longer be an indirect
04794             symbol.  */
04795          skip_next = FALSE;
04796          continue;
04797        }
04798       else
04799        {
04800          struct aout_link_hash_entry *hresolve;
04801 
04802          /* We have saved the hash table entry for this symbol, if
04803             there is one.  Note that we could just look it up again
04804             in the hash table, provided we first check that it is an
04805             external symbol.  */
04806          h = *sym_hash;
04807 
04808          /* Use the name from the hash table, in case the symbol was
04809              wrapped.  */
04810          if (h != NULL
04811              && h->root.type != bfd_link_hash_warning)
04812            name = h->root.root.string;
04813 
04814          /* If this is an indirect or warning symbol, then change
04815             hresolve to the base symbol.  We also change *sym_hash so
04816             that the relocation routines relocate against the real
04817             symbol.  */
04818          hresolve = h;
04819          if (h != (struct aout_link_hash_entry *) NULL
04820              && (h->root.type == bfd_link_hash_indirect
04821                 || h->root.type == bfd_link_hash_warning))
04822            {
04823              hresolve = (struct aout_link_hash_entry *) h->root.u.i.link;
04824              while (hresolve->root.type == bfd_link_hash_indirect
04825                    || hresolve->root.type == bfd_link_hash_warning)
04826               hresolve = ((struct aout_link_hash_entry *)
04827                          hresolve->root.u.i.link);
04828              *sym_hash = hresolve;
04829            }
04830 
04831          /* If the symbol has already been written out, skip it.  */
04832          if (h != NULL
04833              && h->written)
04834            {
04835              if ((type & N_TYPE) == N_INDR
04836                 || type == N_WARNING)
04837               skip_next = TRUE;
04838              *symbol_map = h->indx;
04839              continue;
04840            }
04841 
04842          /* See if we are stripping this symbol.  */
04843          skip = FALSE;
04844          switch (strip)
04845            {
04846            case strip_none:
04847              break;
04848            case strip_debugger:
04849              if ((type & N_STAB) != 0)
04850               skip = TRUE;
04851              break;
04852            case strip_some:
04853              if (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE)
04854                 == NULL)
04855               skip = TRUE;
04856              break;
04857            case strip_all:
04858              skip = TRUE;
04859              break;
04860            }
04861          if (skip)
04862            {
04863              if (h != NULL)
04864               h->written = TRUE;
04865              continue;
04866            }
04867 
04868          /* Get the value of the symbol.  */
04869          if ((type & N_TYPE) == N_TEXT
04870              || type == N_WEAKT)
04871            symsec = obj_textsec (input_bfd);
04872          else if ((type & N_TYPE) == N_DATA
04873                  || type == N_WEAKD)
04874            symsec = obj_datasec (input_bfd);
04875          else if ((type & N_TYPE) == N_BSS
04876                  || type == N_WEAKB)
04877            symsec = obj_bsssec (input_bfd);
04878          else if ((type & N_TYPE) == N_ABS
04879                  || type == N_WEAKA)
04880            symsec = bfd_abs_section_ptr;
04881          else if (((type & N_TYPE) == N_INDR
04882                   && (hresolve == NULL
04883                      || (hresolve->root.type != bfd_link_hash_defined
04884                          && hresolve->root.type != bfd_link_hash_defweak
04885                          && hresolve->root.type != bfd_link_hash_common)))
04886                  || type == N_WARNING)
04887            {
04888              /* Pass the next symbol through unchanged.  The
04889                condition above for indirect symbols is so that if
04890                the indirect symbol was defined, we output it with
04891                the correct definition so the debugger will
04892                understand it.  */
04893              pass = TRUE;
04894              val = GET_WORD (input_bfd, sym->e_value);
04895              symsec = NULL;
04896            }
04897          else if ((type & N_STAB) != 0)
04898            {
04899              val = GET_WORD (input_bfd, sym->e_value);
04900              symsec = NULL;
04901            }
04902          else
04903            {
04904              /* If we get here with an indirect symbol, it means that
04905                we are outputting it with a real definition.  In such
04906                a case we do not want to output the next symbol,
04907                which is the target of the indirection.  */
04908              if ((type & N_TYPE) == N_INDR)
04909               skip_next = TRUE;
04910 
04911              symsec = NULL;
04912 
04913              /* We need to get the value from the hash table.  We use
04914                hresolve so that if we have defined an indirect
04915                symbol we output the final definition.  */
04916              if (h == NULL)
04917               {
04918                 switch (type & N_TYPE)
04919                   {
04920                   case N_SETT:
04921                     symsec = obj_textsec (input_bfd);
04922                     break;
04923                   case N_SETD:
04924                     symsec = obj_datasec (input_bfd);
04925                     break;
04926                   case N_SETB:
04927                     symsec = obj_bsssec (input_bfd);
04928                     break;
04929                   case N_SETA:
04930                     symsec = bfd_abs_section_ptr;
04931                     break;
04932                   default:
04933                     val = 0;
04934                     break;
04935                   }
04936               }
04937              else if (hresolve->root.type == bfd_link_hash_defined
04938                      || hresolve->root.type == bfd_link_hash_defweak)
04939               {
04940                 asection *input_section;
04941                 asection *output_section;
04942 
04943                 /* This case usually means a common symbol which was
04944                    turned into a defined symbol.  */
04945                 input_section = hresolve->root.u.def.section;
04946                 output_section = input_section->output_section;
04947                 BFD_ASSERT (bfd_is_abs_section (output_section)
04948                            || output_section->owner == output_bfd);
04949                 val = (hresolve->root.u.def.value
04950                       + bfd_get_section_vma (output_bfd, output_section)
04951                       + input_section->output_offset);
04952 
04953                 /* Get the correct type based on the section.  If
04954                    this is a constructed set, force it to be
04955                    globally visible.  */
04956                 if (type == N_SETT
04957                     || type == N_SETD
04958                     || type == N_SETB
04959                     || type == N_SETA)
04960                   type |= N_EXT;
04961 
04962                 type &=~ N_TYPE;
04963 
04964                 if (output_section == obj_textsec (output_bfd))
04965                   type |= (hresolve->root.type == bfd_link_hash_defined
04966                           ? N_TEXT
04967                           : N_WEAKT);
04968                 else if (output_section == obj_datasec (output_bfd))
04969                   type |= (hresolve->root.type == bfd_link_hash_defined
04970                           ? N_DATA
04971                           : N_WEAKD);
04972                 else if (output_section == obj_bsssec (output_bfd))
04973                   type |= (hresolve->root.type == bfd_link_hash_defined
04974                           ? N_BSS
04975                           : N_WEAKB);
04976                 else
04977                   type |= (hresolve->root.type == bfd_link_hash_defined
04978                           ? N_ABS
04979                           : N_WEAKA);
04980               }
04981              else if (hresolve->root.type == bfd_link_hash_common)
04982               val = hresolve->root.u.c.size;
04983              else if (hresolve->root.type == bfd_link_hash_undefweak)
04984               {
04985                 val = 0;
04986                 type = N_WEAKU;
04987               }
04988              else
04989               val = 0;
04990            }
04991          if (symsec != NULL)
04992            val = (symsec->output_section->vma
04993                  + symsec->output_offset
04994                  + (GET_WORD (input_bfd, sym->e_value)
04995                     - symsec->vma));
04996 
04997          /* If this is a global symbol set the written flag, and if
04998             it is a local symbol see if we should discard it.  */
04999          if (h != NULL)
05000            {
05001              h->written = TRUE;
05002              h->indx = obj_aout_external_sym_count (output_bfd);
05003            }
05004          else if ((type & N_TYPE) != N_SETT
05005                  && (type & N_TYPE) != N_SETD
05006                  && (type & N_TYPE) != N_SETB
05007                  && (type & N_TYPE) != N_SETA)
05008            {
05009              switch (discard)
05010               {
05011               case discard_none:
05012               case discard_sec_merge:
05013                 break;
05014               case discard_l:
05015                 if ((type & N_STAB) == 0
05016                     && bfd_is_local_label_name (input_bfd, name))
05017                   skip = TRUE;
05018                 break;
05019               case discard_all:
05020                 skip = TRUE;
05021                 break;
05022               }
05023              if (skip)
05024               {
05025                 pass = FALSE;
05026                 continue;
05027               }
05028            }
05029 
05030          /* An N_BINCL symbol indicates the start of the stabs
05031             entries for a header file.  We need to scan ahead to the
05032             next N_EINCL symbol, ignoring nesting, adding up all the
05033             characters in the symbol names, not including the file
05034             numbers in types (the first number after an open
05035             parenthesis).  */
05036          if (type == (int) N_BINCL)
05037            {
05038              struct external_nlist *incl_sym;
05039              int nest;
05040              struct aout_link_includes_entry *incl_entry;
05041              struct aout_link_includes_totals *t;
05042 
05043              val = 0;
05044              nest = 0;
05045              for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
05046               {
05047                 int incl_type;
05048 
05049                 incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
05050                 if (incl_type == (int) N_EINCL)
05051                   {
05052                     if (nest == 0)
05053                      break;
05054                     --nest;
05055                   }
05056                 else if (incl_type == (int) N_BINCL)
05057                   ++nest;
05058                 else if (nest == 0)
05059                   {
05060                     const char *s;
05061 
05062                     s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
05063                     for (; *s != '\0'; s++)
05064                      {
05065                        val += *s;
05066                        if (*s == '(')
05067                          {
05068                            /* Skip the file number.  */
05069                            ++s;
05070                            while (ISDIGIT (*s))
05071                             ++s;
05072                            --s;
05073                          }
05074                      }
05075                   }
05076               }
05077 
05078              /* If we have already included a header file with the
05079                  same value, then replace this one with an N_EXCL
05080                  symbol.  */
05081              copy = (bfd_boolean) (! finfo->info->keep_memory);
05082              incl_entry = aout_link_includes_lookup (&finfo->includes,
05083                                                 name, TRUE, copy);
05084              if (incl_entry == NULL)
05085               return FALSE;
05086              for (t = incl_entry->totals; t != NULL; t = t->next)
05087               if (t->total == val)
05088                 break;
05089              if (t == NULL)
05090               {
05091                 /* This is the first time we have seen this header
05092                      file with this set of stabs strings.  */
05093                 t = bfd_hash_allocate (&finfo->includes.root,
05094                                     sizeof *t);
05095                 if (t == NULL)
05096                   return FALSE;
05097                 t->total = val;
05098                 t->next = incl_entry->totals;
05099                 incl_entry->totals = t;
05100               }
05101              else
05102               {
05103                 int *incl_map;
05104 
05105                 /* This is a duplicate header file.  We must change
05106                      it to be an N_EXCL entry, and mark all the
05107                      included symbols to prevent outputting them.  */
05108                 type = (int) N_EXCL;
05109 
05110                 nest = 0;
05111                 for (incl_sym = sym + 1, incl_map = symbol_map + 1;
05112                      incl_sym < sym_end;
05113                      incl_sym++, incl_map++)
05114                   {
05115                     int incl_type;
05116 
05117                     incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
05118                     if (incl_type == (int) N_EINCL)
05119                      {
05120                        if (nest == 0)
05121                          {
05122                            *incl_map = -1;
05123                            break;
05124                          }
05125                        --nest;
05126                      }
05127                     else if (incl_type == (int) N_BINCL)
05128                      ++nest;
05129                     else if (nest == 0)
05130                      *incl_map = -1;
05131                   }
05132               }
05133            }
05134        }
05135 
05136       /* Copy this symbol into the list of symbols we are going to
05137         write out.  */
05138       H_PUT_8 (output_bfd, type, outsym->e_type);
05139       H_PUT_8 (output_bfd, H_GET_8 (input_bfd, sym->e_other), outsym->e_other);
05140       H_PUT_16 (output_bfd, H_GET_16 (input_bfd, sym->e_desc), outsym->e_desc);
05141       copy = FALSE;
05142       if (! finfo->info->keep_memory)
05143        {
05144          /* name points into a string table which we are going to
05145             free.  If there is a hash table entry, use that string.
05146             Otherwise, copy name into memory.  */
05147          if (h != NULL)
05148            name = h->root.root.string;
05149          else
05150            copy = TRUE;
05151        }
05152       strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
05153                                    name, copy);
05154       if (strtab_index == (bfd_size_type) -1)
05155        return FALSE;
05156       PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
05157       PUT_WORD (output_bfd, val, outsym->e_value);
05158       *symbol_map = obj_aout_external_sym_count (output_bfd);
05159       ++obj_aout_external_sym_count (output_bfd);
05160       ++outsym;
05161     }
05162 
05163   /* Write out the output symbols we have just constructed.  */
05164   if (outsym > finfo->output_syms)
05165     {
05166       bfd_size_type outsym_size;
05167 
05168       if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
05169        return FALSE;
05170       outsym_size = outsym - finfo->output_syms;
05171       outsym_size *= EXTERNAL_NLIST_SIZE;
05172       if (bfd_bwrite ((void *) finfo->output_syms, outsym_size, output_bfd)
05173          != outsym_size)
05174        return FALSE;
05175       finfo->symoff += outsym_size;
05176     }
05177 
05178   return TRUE;
05179 }
05180 
05181 /* Link an a.out input BFD into the output file.  */
05182 
05183 static bfd_boolean
05184 aout_link_input_bfd (struct aout_final_link_info *finfo, bfd *input_bfd)
05185 {
05186   bfd_size_type sym_count;
05187 
05188   BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
05189 
05190   /* If this is a dynamic object, it may need special handling.  */
05191   if ((input_bfd->flags & DYNAMIC) != 0
05192       && aout_backend_info (input_bfd)->link_dynamic_object != NULL)
05193     return ((*aout_backend_info (input_bfd)->link_dynamic_object)
05194            (finfo->info, input_bfd));
05195 
05196   /* Get the symbols.  We probably have them already, unless
05197      finfo->info->keep_memory is FALSE.  */
05198   if (! aout_get_external_symbols (input_bfd))
05199     return FALSE;
05200 
05201   sym_count = obj_aout_external_sym_count (input_bfd);
05202 
05203   /* Write out the symbols and get a map of the new indices.  The map
05204      is placed into finfo->symbol_map.  */
05205   if (! aout_link_write_symbols (finfo, input_bfd))
05206     return FALSE;
05207 
05208   /* Relocate and write out the sections.  These functions use the
05209      symbol map created by aout_link_write_symbols.  The linker_mark
05210      field will be set if these sections are to be included in the
05211      link, which will normally be the case.  */
05212   if (obj_textsec (input_bfd)->linker_mark)
05213     {
05214       if (! aout_link_input_section (finfo, input_bfd,
05215                                  obj_textsec (input_bfd),
05216                                  &finfo->treloff,
05217                                  exec_hdr (input_bfd)->a_trsize))
05218        return FALSE;
05219     }
05220   if (obj_datasec (input_bfd)->linker_mark)
05221     {
05222       if (! aout_link_input_section (finfo, input_bfd,
05223                                  obj_datasec (input_bfd),
05224                                  &finfo->dreloff,
05225                                  exec_hdr (input_bfd)->a_drsize))
05226        return FALSE;
05227     }
05228 
05229   /* If we are not keeping memory, we don't need the symbols any
05230      longer.  We still need them if we are keeping memory, because the
05231      strings in the hash table point into them.  */
05232   if (! finfo->info->keep_memory)
05233     {
05234       if (! aout_link_free_symbols (input_bfd))
05235        return FALSE;
05236     }
05237 
05238   return TRUE;
05239 }
05240 
05241 /* Do the final link step.  This is called on the output BFD.  The
05242    INFO structure should point to a list of BFDs linked through the
05243    link_next field which can be used to find each BFD which takes part
05244    in the output.  Also, each section in ABFD should point to a list
05245    of bfd_link_order structures which list all the input sections for
05246    the output section.  */
05247 
05248 bfd_boolean
05249 NAME (aout, final_link) (bfd *abfd,
05250                       struct bfd_link_info *info,
05251                       void (*callback) (bfd *, file_ptr *, file_ptr *, file_ptr *))
05252 {
05253   struct aout_final_link_info aout_info;
05254   bfd_boolean includes_hash_initialized = FALSE;
05255   bfd *sub;
05256   bfd_size_type trsize, drsize;
05257   bfd_size_type max_contents_size;
05258   bfd_size_type max_relocs_size;
05259   bfd_size_type max_sym_count;
05260   bfd_size_type text_size;
05261   file_ptr text_end;
05262   struct bfd_link_order *p;
05263   asection *o;
05264   bfd_boolean have_link_order_relocs;
05265 
05266   if (info->shared)
05267     abfd->flags |= DYNAMIC;
05268 
05269   aout_info.info = info;
05270   aout_info.output_bfd = abfd;
05271   aout_info.contents = NULL;
05272   aout_info.relocs = NULL;
05273   aout_info.symbol_map = NULL;
05274   aout_info.output_syms = NULL;
05275 
05276   if (!bfd_hash_table_init_n (&aout_info.includes.root,
05277                            aout_link_includes_newfunc,
05278                            sizeof (struct aout_link_includes_entry),
05279                            251))
05280     goto error_return;
05281   includes_hash_initialized = TRUE;
05282 
05283   /* Figure out the largest section size.  Also, if generating
05284      relocatable output, count the relocs.  */
05285   trsize = 0;
05286   drsize = 0;
05287   max_contents_size = 0;
05288   max_relocs_size = 0;
05289   max_sym_count = 0;
05290   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
05291     {
05292       bfd_size_type sz;
05293 
05294       if (info->relocatable)
05295        {
05296          if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
05297            {
05298              trsize += exec_hdr (sub)->a_trsize;
05299              drsize += exec_hdr (sub)->a_drsize;
05300            }
05301          else
05302            {
05303              /* FIXME: We need to identify the .text and .data sections
05304                and call get_reloc_upper_bound and canonicalize_reloc to
05305                work out the number of relocs needed, and then multiply
05306                by the reloc size.  */
05307              (*_bfd_error_handler)
05308               (_("%s: relocatable link from %s to %s not supported"),
05309                bfd_get_filename (abfd),
05310                sub->xvec->name, abfd->xvec->name);
05311              bfd_set_error (bfd_error_invalid_operation);
05312              goto error_return;
05313            }
05314        }
05315 
05316       if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
05317        {
05318          sz = obj_textsec (sub)->size;
05319          if (sz > max_contents_size)
05320            max_contents_size = sz;
05321          sz = obj_datasec (sub)->size;
05322          if (sz > max_contents_size)
05323            max_contents_size = sz;
05324 
05325          sz = exec_hdr (sub)->a_trsize;
05326          if (sz > max_relocs_size)
05327            max_relocs_size = sz;
05328          sz = exec_hdr (sub)->a_drsize;
05329          if (sz > max_relocs_size)
05330            max_relocs_size = sz;
05331 
05332          sz = obj_aout_external_sym_count (sub);
05333          if (sz > max_sym_count)
05334            max_sym_count = sz;
05335        }
05336     }
05337 
05338   if (info->relocatable)
05339     {
05340       if (obj_textsec (abfd) != NULL)
05341        trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
05342                                            ->map_head.link_order)
05343                  * obj_reloc_entry_size (abfd));
05344       if (obj_datasec (abfd) != NULL)
05345        drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
05346                                            ->map_head.link_order)
05347                  * obj_reloc_entry_size (abfd));
05348     }
05349 
05350   exec_hdr (abfd)->a_trsize = trsize;
05351   exec_hdr (abfd)->a_drsize = drsize;
05352 
05353   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
05354 
05355   /* Adjust the section sizes and vmas according to the magic number.
05356      This sets a_text, a_data and a_bss in the exec_hdr and sets the
05357      filepos for each section.  */
05358   if (! NAME (aout, adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
05359     goto error_return;
05360 
05361   /* The relocation and symbol file positions differ among a.out
05362      targets.  We are passed a callback routine from the backend
05363      specific code to handle this.
05364      FIXME: At this point we do not know how much space the symbol
05365      table will require.  This will not work for any (nonstandard)
05366      a.out target that needs to know the symbol table size before it
05367      can compute the relocation file positions.  This may or may not
05368      be the case for the hp300hpux target, for example.  */
05369   (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff,
05370               &aout_info.symoff);
05371   obj_textsec (abfd)->rel_filepos = aout_info.treloff;
05372   obj_datasec (abfd)->rel_filepos = aout_info.dreloff;
05373   obj_sym_filepos (abfd) = aout_info.symoff;
05374 
05375   /* We keep a count of the symbols as we output them.  */
05376   obj_aout_external_sym_count (abfd) = 0;
05377 
05378   /* We accumulate the string table as we write out the symbols.  */
05379   aout_info.strtab = _bfd_stringtab_init ();
05380   if (aout_info.strtab == NULL)
05381     goto error_return;
05382 
05383   /* Allocate buffers to hold section contents and relocs.  */
05384   aout_info.contents = bfd_malloc (max_contents_size);
05385   aout_info.relocs = bfd_malloc (max_relocs_size);
05386   aout_info.symbol_map = bfd_malloc (max_sym_count * sizeof (int *));
05387   aout_info.output_syms = bfd_malloc ((max_sym_count + 1)
05388                                   * sizeof (struct external_nlist));
05389   if ((aout_info.contents == NULL && max_contents_size != 0)
05390       || (aout_info.relocs == NULL && max_relocs_size != 0)
05391       || (aout_info.symbol_map == NULL && max_sym_count != 0)
05392       || aout_info.output_syms == NULL)
05393     goto error_return;
05394 
05395   /* If we have a symbol named __DYNAMIC, force it out now.  This is
05396      required by SunOS.  Doing this here rather than in sunos.c is a
05397      hack, but it's easier than exporting everything which would be
05398      needed.  */
05399   {
05400     struct aout_link_hash_entry *h;
05401 
05402     h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
05403                             FALSE, FALSE, FALSE);
05404     if (h != NULL)
05405       aout_link_write_other_symbol (h, &aout_info);
05406   }
05407 
05408   /* The most time efficient way to do the link would be to read all
05409      the input object files into memory and then sort out the
05410      information into the output file.  Unfortunately, that will
05411      probably use too much memory.  Another method would be to step
05412      through everything that composes the text section and write it
05413      out, and then everything that composes the data section and write
05414      it out, and then write out the relocs, and then write out the
05415      symbols.  Unfortunately, that requires reading stuff from each
05416      input file several times, and we will not be able to keep all the
05417      input files open simultaneously, and reopening them will be slow.
05418 
05419      What we do is basically process one input file at a time.  We do
05420      everything we need to do with an input file once--copy over the
05421      section contents, handle the relocation information, and write
05422      out the symbols--and then we throw away the information we read
05423      from it.  This approach requires a lot of lseeks of the output
05424      file, which is unfortunate but still faster than reopening a lot
05425      of files.
05426 
05427      We use the output_has_begun field of the input BFDs to see
05428      whether we have already handled it.  */
05429   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
05430     sub->output_has_begun = FALSE;
05431 
05432   /* Mark all sections which are to be included in the link.  This
05433      will normally be every section.  We need to do this so that we
05434      can identify any sections which the linker has decided to not
05435      include.  */
05436   for (o = abfd->sections; o != NULL; o = o->next)
05437     {
05438       for (p = o->map_head.link_order; p != NULL; p = p->next)
05439        if (p->type == bfd_indirect_link_order)
05440          p->u.indirect.section->linker_mark = TRUE;
05441     }
05442 
05443   have_link_order_relocs = FALSE;
05444   for (o = abfd->sections; o != NULL; o = o->next)
05445     {
05446       for (p = o->map_head.link_order;
05447           p != NULL;
05448           p = p->next)
05449        {
05450          if (p->type == bfd_indirect_link_order
05451              && (bfd_get_flavour (p->u.indirect.section->owner)
05452                 == bfd_target_aout_flavour))
05453            {
05454              bfd *input_bfd;
05455 
05456              input_bfd = p->u.indirect.section->owner;
05457              if (! input_bfd->output_has_begun)
05458               {
05459                 if (! aout_link_input_bfd (&aout_info, input_bfd))
05460                   goto error_return;
05461                 input_bfd->output_has_begun = TRUE;
05462               }
05463            }
05464          else if (p->type == bfd_section_reloc_link_order
05465                  || p->type == bfd_symbol_reloc_link_order)
05466            {
05467              /* These are handled below.  */
05468              have_link_order_relocs = TRUE;
05469            }
05470          else
05471            {
05472              if (! _bfd_default_link_order (abfd, info, o, p))
05473               goto error_return;
05474            }
05475        }
05476     }
05477 
05478   /* Write out any symbols that we have not already written out.  */
05479   aout_link_hash_traverse (aout_hash_table (info),
05480                         aout_link_write_other_symbol,
05481                         (void *) &aout_info);
05482 
05483   /* Now handle any relocs we were asked to create by the linker.
05484      These did not come from any input file.  We must do these after
05485      we have written out all the symbols, so that we know the symbol
05486      indices to use.  */
05487   if (have_link_order_relocs)
05488     {
05489       for (o = abfd->sections; o != NULL; o = o->next)
05490        {
05491          for (p = o->map_head.link_order;
05492               p != NULL;
05493               p = p->next)
05494            {
05495              if (p->type == bfd_section_reloc_link_order
05496                 || p->type == bfd_symbol_reloc_link_order)
05497               {
05498                 if (! aout_link_reloc_link_order (&aout_info, o, p))
05499                   goto error_return;
05500               }
05501            }
05502        }
05503     }
05504 
05505   if (aout_info.contents != NULL)
05506     {
05507       free (aout_info.contents);
05508       aout_info.contents = NULL;
05509     }
05510   if (aout_info.relocs != NULL)
05511     {
05512       free (aout_info.relocs);
05513       aout_info.relocs = NULL;
05514     }
05515   if (aout_info.symbol_map != NULL)
05516     {
05517       free (aout_info.symbol_map);
05518       aout_info.symbol_map = NULL;
05519     }
05520   if (aout_info.output_syms != NULL)
05521     {
05522       free (aout_info.output_syms);
05523       aout_info.output_syms = NULL;
05524     }
05525   if (includes_hash_initialized)
05526     {
05527       bfd_hash_table_free (&aout_info.includes.root);
05528       includes_hash_initialized = FALSE;
05529     }
05530 
05531   /* Finish up any dynamic linking we may be doing.  */
05532   if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
05533     {
05534       if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
05535        goto error_return;
05536     }
05537 
05538   /* Update the header information.  */
05539   abfd->symcount = obj_aout_external_sym_count (abfd);
05540   exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE;
05541   obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms;
05542   obj_textsec (abfd)->reloc_count =
05543     exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
05544   obj_datasec (abfd)->reloc_count =
05545     exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
05546 
05547   /* Write out the string table, unless there are no symbols.  */
05548   if (abfd->symcount > 0)
05549     {
05550       if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
05551          || ! emit_stringtab (abfd, aout_info.strtab))
05552        goto error_return;
05553     }
05554   else if (obj_textsec (abfd)->reloc_count == 0
05555           && obj_datasec (abfd)->reloc_count == 0)
05556     {
05557       bfd_byte b;
05558       file_ptr pos;
05559 
05560       b = 0;
05561       pos = obj_datasec (abfd)->filepos + exec_hdr (abfd)->a_data - 1;
05562       if (bfd_seek (abfd, pos, SEEK_SET) != 0
05563          || bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
05564        goto error_return;
05565     }
05566 
05567   return TRUE;
05568 
05569  error_return:
05570   if (aout_info.contents != NULL)
05571     free (aout_info.contents);
05572   if (aout_info.relocs != NULL)
05573     free (aout_info.relocs);
05574   if (aout_info.symbol_map != NULL)
05575     free (aout_info.symbol_map);
05576   if (aout_info.output_syms != NULL)
05577     free (aout_info.output_syms);
05578   if (includes_hash_initialized)
05579     bfd_hash_table_free (&aout_info.includes.root);
05580   return FALSE;
05581 }