aoutx.h revision 61843
133965Sjdp/* BFD semi-generic back-end for a.out binaries.
261843Sobrien   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
338889Sjdp   Free Software Foundation, Inc.
433965Sjdp   Written by Cygnus Support.
533965Sjdp
633965SjdpThis file is part of BFD, the Binary File Descriptor library.
733965Sjdp
833965SjdpThis program is free software; you can redistribute it and/or modify
933965Sjdpit under the terms of the GNU General Public License as published by
1033965Sjdpthe Free Software Foundation; either version 2 of the License, or
1133965Sjdp(at your option) any later version.
1233965Sjdp
1333965SjdpThis program is distributed in the hope that it will be useful,
1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965SjdpGNU General Public License for more details.
1733965Sjdp
1833965SjdpYou should have received a copy of the GNU General Public License
1933965Sjdpalong with this program; if not, write to the Free Software
2033965SjdpFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2133965Sjdp
2233965Sjdp/*
2333965SjdpSECTION
2433965Sjdp	a.out backends
2533965Sjdp
2633965Sjdp
2733965SjdpDESCRIPTION
2833965Sjdp
2933965Sjdp	BFD supports a number of different flavours of a.out format,
3033965Sjdp	though the major differences are only the sizes of the
3133965Sjdp	structures on disk, and the shape of the relocation
3233965Sjdp	information.
3333965Sjdp
3433965Sjdp	The support is split into a basic support file @file{aoutx.h}
3533965Sjdp	and other files which derive functions from the base. One
3633965Sjdp	derivation file is @file{aoutf1.h} (for a.out flavour 1), and
3733965Sjdp	adds to the basic a.out functions support for sun3, sun4, 386
3833965Sjdp	and 29k a.out files, to create a target jump vector for a
3933965Sjdp	specific target.
4033965Sjdp
4133965Sjdp	This information is further split out into more specific files
4233965Sjdp	for each machine, including @file{sunos.c} for sun3 and sun4,
4333965Sjdp	@file{newsos3.c} for the Sony NEWS, and @file{demo64.c} for a
4433965Sjdp	demonstration of a 64 bit a.out format.
4533965Sjdp
4633965Sjdp	The base file @file{aoutx.h} defines general mechanisms for
4733965Sjdp	reading and writing records to and from disk and various
4833965Sjdp	other methods which BFD requires. It is included by
4933965Sjdp	@file{aout32.c} and @file{aout64.c} to form the names
5033965Sjdp	<<aout_32_swap_exec_header_in>>, <<aout_64_swap_exec_header_in>>, etc.
5133965Sjdp
5233965Sjdp	As an example, this is what goes on to make the back end for a
5333965Sjdp	sun4, from @file{aout32.c}:
5433965Sjdp
5533965Sjdp|	#define ARCH_SIZE 32
5633965Sjdp|	#include "aoutx.h"
5733965Sjdp
5833965Sjdp	Which exports names:
5933965Sjdp
6033965Sjdp|	...
6133965Sjdp|	aout_32_canonicalize_reloc
6233965Sjdp|	aout_32_find_nearest_line
6333965Sjdp|	aout_32_get_lineno
6433965Sjdp|	aout_32_get_reloc_upper_bound
6533965Sjdp|	...
6633965Sjdp
6733965Sjdp	from @file{sunos.c}:
6833965Sjdp
6933965Sjdp|	#define TARGET_NAME "a.out-sunos-big"
7033965Sjdp|	#define VECNAME    sunos_big_vec
7133965Sjdp|	#include "aoutf1.h"
7233965Sjdp
7333965Sjdp	requires all the names from @file{aout32.c}, and produces the jump vector
7433965Sjdp
7533965Sjdp|	sunos_big_vec
7633965Sjdp
7733965Sjdp	The file @file{host-aout.c} is a special case.  It is for a large set
7833965Sjdp	of hosts that use ``more or less standard'' a.out files, and
7933965Sjdp	for which cross-debugging is not interesting.  It uses the
8033965Sjdp	standard 32-bit a.out support routines, but determines the
8133965Sjdp	file offsets and addresses of the text, data, and BSS
8233965Sjdp	sections, the machine architecture and machine type, and the
8333965Sjdp	entry point address, in a host-dependent manner.  Once these
8433965Sjdp	values have been determined, generic code is used to handle
8533965Sjdp	the  object file.
8633965Sjdp
8733965Sjdp	When porting it to run on a new system, you must supply:
8833965Sjdp
8933965Sjdp|        HOST_PAGE_SIZE
9033965Sjdp|        HOST_SEGMENT_SIZE
9133965Sjdp|        HOST_MACHINE_ARCH       (optional)
9233965Sjdp|        HOST_MACHINE_MACHINE    (optional)
9333965Sjdp|        HOST_TEXT_START_ADDR
9433965Sjdp|        HOST_STACK_END_ADDR
9533965Sjdp
9633965Sjdp	in the file @file{../include/sys/h-@var{XXX}.h} (for your host).  These
9733965Sjdp	values, plus the structures and macros defined in @file{a.out.h} on
9833965Sjdp	your host system, will produce a BFD target that will access
9933965Sjdp	ordinary a.out files on your host. To configure a new machine
10033965Sjdp	to use @file{host-aout.c}, specify:
10133965Sjdp
10233965Sjdp|	TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
10333965Sjdp|	TDEPFILES= host-aout.o trad-core.o
10433965Sjdp
10533965Sjdp	in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in}
10633965Sjdp	to use the
10733965Sjdp	@file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your
10833965Sjdp	configuration is selected.
10933965Sjdp
11033965Sjdp*/
11133965Sjdp
11233965Sjdp/* Some assumptions:
11333965Sjdp   * Any BFD with D_PAGED set is ZMAGIC, and vice versa.
11433965Sjdp     Doesn't matter what the setting of WP_TEXT is on output, but it'll
11533965Sjdp     get set on input.
11633965Sjdp   * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC.
11733965Sjdp   * Any BFD with both flags clear is OMAGIC.
11833965Sjdp   (Just want to make these explicit, so the conditions tested in this
11933965Sjdp   file make sense if you're more familiar with a.out than with BFD.)  */
12033965Sjdp
12133965Sjdp#define KEEPIT udata.i
12233965Sjdp
12333965Sjdp#include <ctype.h>
12433965Sjdp#include "bfd.h"
12560484Sobrien#include "sysdep.h"
12633965Sjdp#include "bfdlink.h"
12733965Sjdp
12833965Sjdp#include "libaout.h"
12933965Sjdp#include "libbfd.h"
13033965Sjdp#include "aout/aout64.h"
13133965Sjdp#include "aout/stab_gnu.h"
13233965Sjdp#include "aout/ar.h"
13333965Sjdp
13433965Sjdpstatic boolean aout_get_external_symbols PARAMS ((bfd *));
13533965Sjdpstatic boolean translate_from_native_sym_flags
13633965Sjdp  PARAMS ((bfd *, aout_symbol_type *));
13733965Sjdpstatic boolean translate_to_native_sym_flags
13833965Sjdp  PARAMS ((bfd *, asymbol *, struct external_nlist *));
13933965Sjdpstatic void adjust_o_magic PARAMS ((bfd *, struct internal_exec *));
14033965Sjdpstatic void adjust_z_magic PARAMS ((bfd *, struct internal_exec *));
14133965Sjdpstatic void adjust_n_magic PARAMS ((bfd *, struct internal_exec *));
14233965Sjdp
14333965Sjdp/*
14433965SjdpSUBSECTION
14533965Sjdp	Relocations
14633965Sjdp
14733965SjdpDESCRIPTION
14833965Sjdp	The file @file{aoutx.h} provides for both the @emph{standard}
14933965Sjdp	and @emph{extended} forms of a.out relocation records.
15033965Sjdp
15133965Sjdp	The standard records contain only an
15233965Sjdp	address, a symbol index, and a type field. The extended records
15333965Sjdp	(used on 29ks and sparcs) also have a full integer for an
15433965Sjdp	addend.
15533965Sjdp
15633965Sjdp*/
15733965Sjdp#ifndef CTOR_TABLE_RELOC_HOWTO
15833965Sjdp#define CTOR_TABLE_RELOC_IDX 2
15933965Sjdp#define CTOR_TABLE_RELOC_HOWTO(BFD) ((obj_reloc_entry_size(BFD) == RELOC_EXT_SIZE \
16033965Sjdp	     ? howto_table_ext : howto_table_std) \
16133965Sjdp	    + CTOR_TABLE_RELOC_IDX)
16233965Sjdp#endif
16333965Sjdp
16433965Sjdp#ifndef MY_swap_std_reloc_in
16533965Sjdp#define MY_swap_std_reloc_in NAME(aout,swap_std_reloc_in)
16633965Sjdp#endif
16733965Sjdp
16833965Sjdp#ifndef MY_swap_std_reloc_out
16933965Sjdp#define MY_swap_std_reloc_out NAME(aout,swap_std_reloc_out)
17033965Sjdp#endif
17133965Sjdp
17233965Sjdp#ifndef MY_final_link_relocate
17333965Sjdp#define MY_final_link_relocate _bfd_final_link_relocate
17433965Sjdp#endif
17533965Sjdp
17633965Sjdp#ifndef MY_relocate_contents
17733965Sjdp#define MY_relocate_contents _bfd_relocate_contents
17833965Sjdp#endif
17933965Sjdp
18033965Sjdp#define howto_table_ext NAME(aout,ext_howto_table)
18133965Sjdp#define howto_table_std NAME(aout,std_howto_table)
18233965Sjdp
18333965Sjdpreloc_howto_type howto_table_ext[] =
18433965Sjdp{
18533965Sjdp  /* type           rs   size bsz  pcrel bitpos ovrf                  sf name          part_inpl readmask setmask pcdone */
18633965Sjdp  HOWTO(RELOC_8,      0,  0,  	8,  false, 0, complain_overflow_bitfield,0,"8",        false, 0,0x000000ff, false),
18733965Sjdp  HOWTO(RELOC_16,     0,  1, 	16, false, 0, complain_overflow_bitfield,0,"16",       false, 0,0x0000ffff, false),
18833965Sjdp  HOWTO(RELOC_32,     0,  2, 	32, false, 0, complain_overflow_bitfield,0,"32",       false, 0,0xffffffff, false),
18933965Sjdp  HOWTO(RELOC_DISP8,  0,  0, 	8,  true,  0, complain_overflow_signed,0,"DISP8", 	false, 0,0x000000ff, false),
19033965Sjdp  HOWTO(RELOC_DISP16, 0,  1, 	16, true,  0, complain_overflow_signed,0,"DISP16", 	false, 0,0x0000ffff, false),
19133965Sjdp  HOWTO(RELOC_DISP32, 0,  2, 	32, true,  0, complain_overflow_signed,0,"DISP32", 	false, 0,0xffffffff, false),
19233965Sjdp  HOWTO(RELOC_WDISP30,2,  2, 	30, true,  0, complain_overflow_signed,0,"WDISP30", 	false, 0,0x3fffffff, false),
19333965Sjdp  HOWTO(RELOC_WDISP22,2,  2, 	22, true,  0, complain_overflow_signed,0,"WDISP22", 	false, 0,0x003fffff, false),
19433965Sjdp  HOWTO(RELOC_HI22,   10, 2, 	22, false, 0, complain_overflow_bitfield,0,"HI22",	false, 0,0x003fffff, false),
19533965Sjdp  HOWTO(RELOC_22,     0,  2, 	22, false, 0, complain_overflow_bitfield,0,"22",       false, 0,0x003fffff, false),
19633965Sjdp  HOWTO(RELOC_13,     0,  2, 	13, false, 0, complain_overflow_bitfield,0,"13",       false, 0,0x00001fff, false),
19733965Sjdp  HOWTO(RELOC_LO10,   0,  2, 	10, false, 0, complain_overflow_dont,0,"LO10",     false, 0,0x000003ff, false),
19833965Sjdp  HOWTO(RELOC_SFA_BASE,0, 2, 	32, false, 0, complain_overflow_bitfield,0,"SFA_BASE", false, 0,0xffffffff, false),
19933965Sjdp  HOWTO(RELOC_SFA_OFF13,0,2, 	32, false, 0, complain_overflow_bitfield,0,"SFA_OFF13",false, 0,0xffffffff, false),
20033965Sjdp  HOWTO(RELOC_BASE10, 0,  2, 	10, false, 0, complain_overflow_dont,0,"BASE10",   false, 0,0x000003ff, false),
20160484Sobrien  HOWTO(RELOC_BASE13, 0,  2,	13, false, 0, complain_overflow_signed,0,"BASE13",   false, 0,0x00001fff, false),
20233965Sjdp  HOWTO(RELOC_BASE22, 10, 2,	22, false, 0, complain_overflow_bitfield,0,"BASE22",   false, 0,0x003fffff, false),
20333965Sjdp  HOWTO(RELOC_PC10,   0,  2,	10, true,  0, complain_overflow_dont,0,"PC10",	false, 0,0x000003ff, true),
20433965Sjdp  HOWTO(RELOC_PC22,   10,  2,	22, true,  0, complain_overflow_signed,0,"PC22", false, 0,0x003fffff, true),
20533965Sjdp  HOWTO(RELOC_JMP_TBL,2,  2, 	30, true,  0, complain_overflow_signed,0,"JMP_TBL", 	false, 0,0x3fffffff, false),
20633965Sjdp  HOWTO(RELOC_SEGOFF16,0, 2,	0,  false, 0, complain_overflow_bitfield,0,"SEGOFF16",	false, 0,0x00000000, false),
20733965Sjdp  HOWTO(RELOC_GLOB_DAT,0, 2,	0,  false, 0, complain_overflow_bitfield,0,"GLOB_DAT",	false, 0,0x00000000, false),
20833965Sjdp  HOWTO(RELOC_JMP_SLOT,0, 2,	0,  false, 0, complain_overflow_bitfield,0,"JMP_SLOT",	false, 0,0x00000000, false),
20933965Sjdp  HOWTO(RELOC_RELATIVE,0, 2,	0,  false, 0, complain_overflow_bitfield,0,"RELATIVE",	false, 0,0x00000000, false),
21060484Sobrien  HOWTO(0,  0, 0,    0,  false, 0, complain_overflow_dont, 0, "R_SPARC_NONE",    false,0,0x00000000,true),
21160484Sobrien  HOWTO(0,  0, 0,    0,  false, 0, complain_overflow_dont, 0, "R_SPARC_NONE",    false,0,0x00000000,true),
21260484Sobrien#define RELOC_SPARC_REV32 RELOC_WDISP19
21360484Sobrien  HOWTO(RELOC_SPARC_REV32,    0,  2, 	32, false, 0, complain_overflow_dont,0,"R_SPARC_REV32",       false, 0,0xffffffff, false),
21433965Sjdp};
21533965Sjdp
21633965Sjdp/* Convert standard reloc records to "arelent" format (incl byte swap).  */
21733965Sjdp
21833965Sjdpreloc_howto_type howto_table_std[] = {
21933965Sjdp  /* type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
22033965SjdpHOWTO( 0,	       0,  0,  	8,  false, 0, complain_overflow_bitfield,0,"8",		true, 0x000000ff,0x000000ff, false),
22133965SjdpHOWTO( 1,	       0,  1, 	16, false, 0, complain_overflow_bitfield,0,"16",	true, 0x0000ffff,0x0000ffff, false),
22233965SjdpHOWTO( 2,	       0,  2, 	32, false, 0, complain_overflow_bitfield,0,"32",	true, 0xffffffff,0xffffffff, false),
22333965SjdpHOWTO( 3,	       0,  4, 	64, false, 0, complain_overflow_bitfield,0,"64",	true, 0xdeaddead,0xdeaddead, false),
22433965SjdpHOWTO( 4,	       0,  0, 	8,  true,  0, complain_overflow_signed,  0,"DISP8",	true, 0x000000ff,0x000000ff, false),
22533965SjdpHOWTO( 5,	       0,  1, 	16, true,  0, complain_overflow_signed,  0,"DISP16",	true, 0x0000ffff,0x0000ffff, false),
22633965SjdpHOWTO( 6,	       0,  2, 	32, true,  0, complain_overflow_signed,  0,"DISP32",	true, 0xffffffff,0xffffffff, false),
22733965SjdpHOWTO( 7,	       0,  4, 	64, true,  0, complain_overflow_signed,  0,"DISP64",	true, 0xfeedface,0xfeedface, false),
22833965SjdpHOWTO( 8,	       0,  2,    0, false, 0, complain_overflow_bitfield,0,"GOT_REL",	false,         0,0x00000000, false),
22933965SjdpHOWTO( 9,	       0,  1,   16, false, 0, complain_overflow_bitfield,0,"BASE16",	false,0xffffffff,0xffffffff, false),
23033965SjdpHOWTO(10,	       0,  2,   32, false, 0, complain_overflow_bitfield,0,"BASE32",	false,0xffffffff,0xffffffff, false),
23160484SobrienEMPTY_HOWTO (-1),
23260484SobrienEMPTY_HOWTO (-1),
23360484SobrienEMPTY_HOWTO (-1),
23460484SobrienEMPTY_HOWTO (-1),
23560484SobrienEMPTY_HOWTO (-1),
23633965Sjdp  HOWTO(16,	       0,  2,	 0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false,         0,0x00000000, false),
23760484SobrienEMPTY_HOWTO (-1),
23860484SobrienEMPTY_HOWTO (-1),
23960484SobrienEMPTY_HOWTO (-1),
24060484SobrienEMPTY_HOWTO (-1),
24160484SobrienEMPTY_HOWTO (-1),
24260484SobrienEMPTY_HOWTO (-1),
24360484SobrienEMPTY_HOWTO (-1),
24460484SobrienEMPTY_HOWTO (-1),
24560484SobrienEMPTY_HOWTO (-1),
24660484SobrienEMPTY_HOWTO (-1),
24760484SobrienEMPTY_HOWTO (-1),
24860484SobrienEMPTY_HOWTO (-1),
24960484SobrienEMPTY_HOWTO (-1),
25060484SobrienEMPTY_HOWTO (-1),
25160484SobrienEMPTY_HOWTO (-1),
25233965Sjdp  HOWTO(32,	       0,  2,	 0, false, 0, complain_overflow_bitfield,0,"RELATIVE",  false,         0,0x00000000, false),
25360484SobrienEMPTY_HOWTO (-1),
25460484SobrienEMPTY_HOWTO (-1),
25560484SobrienEMPTY_HOWTO (-1),
25660484SobrienEMPTY_HOWTO (-1),
25760484SobrienEMPTY_HOWTO (-1),
25860484SobrienEMPTY_HOWTO (-1),
25960484SobrienEMPTY_HOWTO (-1),
26033965Sjdp  HOWTO(40,	       0,  2,	 0, false, 0, complain_overflow_bitfield,0,"BASEREL",   false,         0,0x00000000, false),
26133965Sjdp};
26233965Sjdp
26333965Sjdp#define TABLE_SIZE(TABLE)	(sizeof(TABLE)/sizeof(TABLE[0]))
26433965Sjdp
26533965Sjdpreloc_howto_type *
26633965SjdpNAME(aout,reloc_type_lookup) (abfd,code)
26733965Sjdp     bfd *abfd;
26833965Sjdp     bfd_reloc_code_real_type code;
26933965Sjdp{
27033965Sjdp#define EXT(i,j)	case i: return &howto_table_ext[j]
27133965Sjdp#define STD(i,j)	case i: return &howto_table_std[j]
27233965Sjdp  int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
27333965Sjdp  if (code == BFD_RELOC_CTOR)
27433965Sjdp    switch (bfd_get_arch_info (abfd)->bits_per_address)
27533965Sjdp      {
27633965Sjdp      case 32:
27733965Sjdp	code = BFD_RELOC_32;
27833965Sjdp	break;
27933965Sjdp      case 64:
28033965Sjdp	code = BFD_RELOC_64;
28133965Sjdp	break;
28233965Sjdp      }
28333965Sjdp  if (ext)
28433965Sjdp    switch (code)
28533965Sjdp      {
28633965Sjdp	EXT (BFD_RELOC_32, 2);
28733965Sjdp	EXT (BFD_RELOC_HI22, 8);
28833965Sjdp	EXT (BFD_RELOC_LO10, 11);
28933965Sjdp	EXT (BFD_RELOC_32_PCREL_S2, 6);
29033965Sjdp	EXT (BFD_RELOC_SPARC_WDISP22, 7);
29133965Sjdp	EXT (BFD_RELOC_SPARC13, 10);
29233965Sjdp	EXT (BFD_RELOC_SPARC_GOT10, 14);
29333965Sjdp	EXT (BFD_RELOC_SPARC_BASE13, 15);
29433965Sjdp	EXT (BFD_RELOC_SPARC_GOT13, 15);
29533965Sjdp	EXT (BFD_RELOC_SPARC_GOT22, 16);
29633965Sjdp	EXT (BFD_RELOC_SPARC_PC10, 17);
29733965Sjdp	EXT (BFD_RELOC_SPARC_PC22, 18);
29833965Sjdp	EXT (BFD_RELOC_SPARC_WPLT30, 19);
29960484Sobrien	EXT (BFD_RELOC_SPARC_REV32, 26);
30033965Sjdp      default: return (reloc_howto_type *) NULL;
30133965Sjdp      }
30233965Sjdp  else
30333965Sjdp    /* std relocs */
30433965Sjdp    switch (code)
30533965Sjdp      {
30633965Sjdp	STD (BFD_RELOC_16, 1);
30733965Sjdp	STD (BFD_RELOC_32, 2);
30833965Sjdp	STD (BFD_RELOC_8_PCREL, 4);
30933965Sjdp	STD (BFD_RELOC_16_PCREL, 5);
31033965Sjdp	STD (BFD_RELOC_32_PCREL, 6);
31133965Sjdp	STD (BFD_RELOC_16_BASEREL, 9);
31233965Sjdp	STD (BFD_RELOC_32_BASEREL, 10);
31333965Sjdp      default: return (reloc_howto_type *) NULL;
31433965Sjdp      }
31533965Sjdp}
31633965Sjdp
31733965Sjdp/*
31833965SjdpSUBSECTION
31933965Sjdp	Internal entry points
32033965Sjdp
32133965SjdpDESCRIPTION
32233965Sjdp	@file{aoutx.h} exports several routines for accessing the
32333965Sjdp	contents of an a.out file, which are gathered and exported in
32433965Sjdp	turn by various format specific files (eg sunos.c).
32533965Sjdp
32633965Sjdp*/
32733965Sjdp
32833965Sjdp/*
32933965SjdpFUNCTION
33033965Sjdp	 aout_@var{size}_swap_exec_header_in
33133965Sjdp
33233965SjdpSYNOPSIS
33333965Sjdp	void aout_@var{size}_swap_exec_header_in,
33433965Sjdp           (bfd *abfd,
33533965Sjdp            struct external_exec *raw_bytes,
33633965Sjdp            struct internal_exec *execp);
33733965Sjdp
33833965SjdpDESCRIPTION
33933965Sjdp	Swap the information in an executable header @var{raw_bytes} taken
34033965Sjdp	from a raw byte stream memory image into the internal exec header
34133965Sjdp	structure @var{execp}.
34233965Sjdp*/
34333965Sjdp
34433965Sjdp#ifndef NAME_swap_exec_header_in
34533965Sjdpvoid
34633965SjdpNAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp)
34733965Sjdp     bfd *abfd;
34833965Sjdp     struct external_exec *raw_bytes;
34933965Sjdp     struct internal_exec *execp;
35033965Sjdp{
35133965Sjdp  struct external_exec *bytes = (struct external_exec *)raw_bytes;
35233965Sjdp
35333965Sjdp  /* The internal_exec structure has some fields that are unused in this
35433965Sjdp     configuration (IE for i960), so ensure that all such uninitialized
35533965Sjdp     fields are zero'd out.  There are places where two of these structs
35633965Sjdp     are memcmp'd, and thus the contents do matter. */
35733965Sjdp  memset ((PTR) execp, 0, sizeof (struct internal_exec));
35833965Sjdp  /* Now fill in fields in the execp, from the bytes in the raw data.  */
35933965Sjdp  execp->a_info   = bfd_h_get_32 (abfd, bytes->e_info);
36033965Sjdp  execp->a_text   = GET_WORD (abfd, bytes->e_text);
36133965Sjdp  execp->a_data   = GET_WORD (abfd, bytes->e_data);
36233965Sjdp  execp->a_bss    = GET_WORD (abfd, bytes->e_bss);
36333965Sjdp  execp->a_syms   = GET_WORD (abfd, bytes->e_syms);
36433965Sjdp  execp->a_entry  = GET_WORD (abfd, bytes->e_entry);
36533965Sjdp  execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
36633965Sjdp  execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
36733965Sjdp}
36833965Sjdp#define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in)
36933965Sjdp#endif
37033965Sjdp
37133965Sjdp/*
37233965SjdpFUNCTION
37333965Sjdp	aout_@var{size}_swap_exec_header_out
37433965Sjdp
37533965SjdpSYNOPSIS
37633965Sjdp	void aout_@var{size}_swap_exec_header_out
37733965Sjdp	  (bfd *abfd,
37833965Sjdp	   struct internal_exec *execp,
37933965Sjdp	   struct external_exec *raw_bytes);
38033965Sjdp
38133965SjdpDESCRIPTION
38233965Sjdp	Swap the information in an internal exec header structure
38333965Sjdp	@var{execp} into the buffer @var{raw_bytes} ready for writing to disk.
38433965Sjdp*/
38533965Sjdpvoid
38633965SjdpNAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes)
38733965Sjdp     bfd *abfd;
38833965Sjdp     struct internal_exec *execp;
38933965Sjdp     struct external_exec *raw_bytes;
39033965Sjdp{
39133965Sjdp  struct external_exec *bytes = (struct external_exec *)raw_bytes;
39233965Sjdp
39333965Sjdp  /* Now fill in fields in the raw data, from the fields in the exec struct. */
39433965Sjdp  bfd_h_put_32 (abfd, execp->a_info  , bytes->e_info);
39533965Sjdp  PUT_WORD (abfd, execp->a_text  , bytes->e_text);
39633965Sjdp  PUT_WORD (abfd, execp->a_data  , bytes->e_data);
39733965Sjdp  PUT_WORD (abfd, execp->a_bss   , bytes->e_bss);
39833965Sjdp  PUT_WORD (abfd, execp->a_syms  , bytes->e_syms);
39933965Sjdp  PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
40033965Sjdp  PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
40133965Sjdp  PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
40233965Sjdp}
40333965Sjdp
40433965Sjdp/* Make all the section for an a.out file.  */
40533965Sjdp
40633965Sjdpboolean
40733965SjdpNAME(aout,make_sections) (abfd)
40833965Sjdp     bfd *abfd;
40933965Sjdp{
41033965Sjdp  if (obj_textsec (abfd) == (asection *) NULL
41133965Sjdp      && bfd_make_section (abfd, ".text") == (asection *) NULL)
41233965Sjdp    return false;
41333965Sjdp  if (obj_datasec (abfd) == (asection *) NULL
41433965Sjdp      && bfd_make_section (abfd, ".data") == (asection *) NULL)
41533965Sjdp    return false;
41633965Sjdp  if (obj_bsssec (abfd) == (asection *) NULL
41733965Sjdp      && bfd_make_section (abfd, ".bss") == (asection *) NULL)
41833965Sjdp    return false;
41933965Sjdp  return true;
42033965Sjdp}
42133965Sjdp
42233965Sjdp/*
42333965SjdpFUNCTION
42433965Sjdp	aout_@var{size}_some_aout_object_p
42533965Sjdp
42633965SjdpSYNOPSIS
42733965Sjdp	const bfd_target *aout_@var{size}_some_aout_object_p
42833965Sjdp	 (bfd *abfd,
42933965Sjdp	  const bfd_target *(*callback_to_real_object_p)());
43033965Sjdp
43133965SjdpDESCRIPTION
43233965Sjdp	Some a.out variant thinks that the file open in @var{abfd}
43333965Sjdp	checking is an a.out file.  Do some more checking, and set up
43433965Sjdp	for access if it really is.  Call back to the calling
43533965Sjdp	environment's "finish up" function just before returning, to
43633965Sjdp	handle any last-minute setup.
43733965Sjdp*/
43833965Sjdp
43933965Sjdpconst bfd_target *
44033965SjdpNAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
44133965Sjdp     bfd *abfd;
44233965Sjdp     struct internal_exec *execp;
44333965Sjdp     const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *));
44433965Sjdp{
44533965Sjdp  struct aout_data_struct *rawptr, *oldrawptr;
44633965Sjdp  const bfd_target *result;
44733965Sjdp
44833965Sjdp  rawptr = (struct aout_data_struct  *) bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
44933965Sjdp  if (rawptr == NULL)
45033965Sjdp    return 0;
45133965Sjdp
45233965Sjdp  oldrawptr = abfd->tdata.aout_data;
45333965Sjdp  abfd->tdata.aout_data = rawptr;
45433965Sjdp
45533965Sjdp  /* Copy the contents of the old tdata struct.
45633965Sjdp     In particular, we want the subformat, since for hpux it was set in
45733965Sjdp     hp300hpux.c:swap_exec_header_in and will be used in
45833965Sjdp     hp300hpux.c:callback.  */
45933965Sjdp  if (oldrawptr != NULL)
46033965Sjdp    *abfd->tdata.aout_data = *oldrawptr;
46133965Sjdp
46233965Sjdp  abfd->tdata.aout_data->a.hdr = &rawptr->e;
46333965Sjdp  *(abfd->tdata.aout_data->a.hdr) = *execp;	/* Copy in the internal_exec struct */
46433965Sjdp  execp = abfd->tdata.aout_data->a.hdr;
46533965Sjdp
46633965Sjdp  /* Set the file flags */
46733965Sjdp  abfd->flags = BFD_NO_FLAGS;
46833965Sjdp  if (execp->a_drsize || execp->a_trsize)
46933965Sjdp    abfd->flags |= HAS_RELOC;
47033965Sjdp  /* Setting of EXEC_P has been deferred to the bottom of this function */
47133965Sjdp  if (execp->a_syms)
47233965Sjdp    abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
47333965Sjdp  if (N_DYNAMIC(*execp))
47433965Sjdp    abfd->flags |= DYNAMIC;
47533965Sjdp
47633965Sjdp  if (N_MAGIC (*execp) == ZMAGIC)
47733965Sjdp    {
47833965Sjdp      abfd->flags |= D_PAGED | WP_TEXT;
47933965Sjdp      adata (abfd).magic = z_magic;
48033965Sjdp    }
48133965Sjdp  else if (N_MAGIC (*execp) == QMAGIC)
48233965Sjdp    {
48333965Sjdp      abfd->flags |= D_PAGED | WP_TEXT;
48433965Sjdp      adata (abfd).magic = z_magic;
48533965Sjdp      adata (abfd).subformat = q_magic_format;
48633965Sjdp    }
48733965Sjdp  else if (N_MAGIC (*execp) == NMAGIC)
48833965Sjdp    {
48933965Sjdp      abfd->flags |= WP_TEXT;
49033965Sjdp      adata (abfd).magic = n_magic;
49133965Sjdp    }
49233965Sjdp  else if (N_MAGIC (*execp) == OMAGIC
49333965Sjdp	   || N_MAGIC (*execp) == BMAGIC)
49433965Sjdp    adata (abfd).magic = o_magic;
49533965Sjdp  else
49633965Sjdp    {
49733965Sjdp      /* Should have been checked with N_BADMAG before this routine
49833965Sjdp	 was called.  */
49933965Sjdp      abort ();
50033965Sjdp    }
50133965Sjdp
50233965Sjdp  bfd_get_start_address (abfd) = execp->a_entry;
50333965Sjdp
50433965Sjdp  obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
50533965Sjdp  bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
50633965Sjdp
50733965Sjdp  /* The default relocation entry size is that of traditional V7 Unix.  */
50833965Sjdp  obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
50933965Sjdp
51033965Sjdp  /* The default symbol entry size is that of traditional Unix. */
51133965Sjdp  obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
51233965Sjdp
51333965Sjdp#ifdef USE_MMAP
51433965Sjdp  bfd_init_window (&obj_aout_sym_window (abfd));
51533965Sjdp  bfd_init_window (&obj_aout_string_window (abfd));
51633965Sjdp#endif
51733965Sjdp  obj_aout_external_syms (abfd) = NULL;
51833965Sjdp  obj_aout_external_strings (abfd) = NULL;
51933965Sjdp  obj_aout_sym_hashes (abfd) = NULL;
52033965Sjdp
52133965Sjdp  if (! NAME(aout,make_sections) (abfd))
52233965Sjdp    return NULL;
52333965Sjdp
52433965Sjdp  obj_datasec (abfd)->_raw_size = execp->a_data;
52533965Sjdp  obj_bsssec (abfd)->_raw_size = execp->a_bss;
52633965Sjdp
52733965Sjdp  obj_textsec (abfd)->flags =
52833965Sjdp    (execp->a_trsize != 0
52933965Sjdp     ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
53033965Sjdp     : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
53133965Sjdp  obj_datasec (abfd)->flags =
53233965Sjdp    (execp->a_drsize != 0
53333965Sjdp     ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
53433965Sjdp     : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
53533965Sjdp  obj_bsssec (abfd)->flags = SEC_ALLOC;
53633965Sjdp
53733965Sjdp#ifdef THIS_IS_ONLY_DOCUMENTATION
53833965Sjdp  /* The common code can't fill in these things because they depend
53933965Sjdp     on either the start address of the text segment, the rounding
54033965Sjdp     up of virtual addresses between segments, or the starting file
54133965Sjdp     position of the text segment -- all of which varies among different
54233965Sjdp     versions of a.out.  */
54333965Sjdp
54433965Sjdp  /* Call back to the format-dependent code to fill in the rest of the
54533965Sjdp     fields and do any further cleanup.  Things that should be filled
54633965Sjdp     in by the callback:  */
54733965Sjdp
54833965Sjdp  struct exec *execp = exec_hdr (abfd);
54933965Sjdp
55033965Sjdp  obj_textsec (abfd)->size = N_TXTSIZE(*execp);
55133965Sjdp  obj_textsec (abfd)->raw_size = N_TXTSIZE(*execp);
55233965Sjdp  /* data and bss are already filled in since they're so standard */
55333965Sjdp
55433965Sjdp  /* The virtual memory addresses of the sections */
55533965Sjdp  obj_textsec (abfd)->vma = N_TXTADDR(*execp);
55633965Sjdp  obj_datasec (abfd)->vma = N_DATADDR(*execp);
55733965Sjdp  obj_bsssec  (abfd)->vma = N_BSSADDR(*execp);
55833965Sjdp
55933965Sjdp  /* The file offsets of the sections */
56033965Sjdp  obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
56133965Sjdp  obj_datasec (abfd)->filepos = N_DATOFF(*execp);
56233965Sjdp
56333965Sjdp  /* The file offsets of the relocation info */
56433965Sjdp  obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
56533965Sjdp  obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
56633965Sjdp
56733965Sjdp  /* The file offsets of the string table and symbol table.  */
56833965Sjdp  obj_str_filepos (abfd) = N_STROFF (*execp);
56933965Sjdp  obj_sym_filepos (abfd) = N_SYMOFF (*execp);
57033965Sjdp
57133965Sjdp  /* Determine the architecture and machine type of the object file.  */
57233965Sjdp  switch (N_MACHTYPE (*exec_hdr (abfd))) {
57333965Sjdp  default:
57433965Sjdp    abfd->obj_arch = bfd_arch_obscure;
57533965Sjdp    break;
57633965Sjdp  }
57733965Sjdp
57833965Sjdp  adata(abfd)->page_size = TARGET_PAGE_SIZE;
57933965Sjdp  adata(abfd)->segment_size = SEGMENT_SIZE;
58033965Sjdp  adata(abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
58133965Sjdp
58233965Sjdp  return abfd->xvec;
58333965Sjdp
58433965Sjdp  /* The architecture is encoded in various ways in various a.out variants,
58533965Sjdp     or is not encoded at all in some of them.  The relocation size depends
58633965Sjdp     on the architecture and the a.out variant.  Finally, the return value
58733965Sjdp     is the bfd_target vector in use.  If an error occurs, return zero and
58833965Sjdp     set bfd_error to the appropriate error code.
58933965Sjdp
59033965Sjdp     Formats such as b.out, which have additional fields in the a.out
59133965Sjdp     header, should cope with them in this callback as well.  */
59233965Sjdp#endif				/* DOCUMENTATION */
59333965Sjdp
59433965Sjdp  result = (*callback_to_real_object_p)(abfd);
59533965Sjdp
59633965Sjdp  /* Now that the segment addresses have been worked out, take a better
59733965Sjdp     guess at whether the file is executable.  If the entry point
59833965Sjdp     is within the text segment, assume it is.  (This makes files
59933965Sjdp     executable even if their entry point address is 0, as long as
60033965Sjdp     their text starts at zero.).
60133965Sjdp
60233965Sjdp     This test had to be changed to deal with systems where the text segment
60333965Sjdp     runs at a different location than the default.  The problem is that the
60433965Sjdp     entry address can appear to be outside the text segment, thus causing an
60533965Sjdp     erroneous conclusion that the file isn't executable.
60633965Sjdp
60733965Sjdp     To fix this, we now accept any non-zero entry point as an indication of
60833965Sjdp     executability.  This will work most of the time, since only the linker
60933965Sjdp     sets the entry point, and that is likely to be non-zero for most systems. */
61033965Sjdp
61133965Sjdp  if (execp->a_entry != 0
61233965Sjdp      || (execp->a_entry >= obj_textsec(abfd)->vma
61333965Sjdp	  && execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
61433965Sjdp    abfd->flags |= EXEC_P;
61533965Sjdp#ifdef STAT_FOR_EXEC
61633965Sjdp  else
61733965Sjdp    {
61833965Sjdp      struct stat stat_buf;
61933965Sjdp
62033965Sjdp      /* The original heuristic doesn't work in some important cases.
62133965Sjdp        The a.out file has no information about the text start
62233965Sjdp        address.  For files (like kernels) linked to non-standard
62333965Sjdp        addresses (ld -Ttext nnn) the entry point may not be between
62433965Sjdp        the default text start (obj_textsec(abfd)->vma) and
62533965Sjdp        (obj_textsec(abfd)->vma) + text size.  This is not just a mach
62633965Sjdp        issue.  Many kernels are loaded at non standard addresses.  */
62733965Sjdp      if (abfd->iostream != NULL
62833965Sjdp	  && (abfd->flags & BFD_IN_MEMORY) == 0
62933965Sjdp	  && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
63033965Sjdp	  && ((stat_buf.st_mode & 0111) != 0))
63133965Sjdp	abfd->flags |= EXEC_P;
63233965Sjdp    }
63333965Sjdp#endif /* STAT_FOR_EXEC */
63433965Sjdp
63533965Sjdp  if (result)
63633965Sjdp    {
63733965Sjdp#if 0 /* These should be set correctly anyways.  */
63833965Sjdp      abfd->sections = obj_textsec (abfd);
63933965Sjdp      obj_textsec (abfd)->next = obj_datasec (abfd);
64033965Sjdp      obj_datasec (abfd)->next = obj_bsssec (abfd);
64133965Sjdp#endif
64233965Sjdp    }
64333965Sjdp  else
64433965Sjdp    {
64533965Sjdp      free (rawptr);
64633965Sjdp      abfd->tdata.aout_data = oldrawptr;
64733965Sjdp    }
64833965Sjdp  return result;
64933965Sjdp}
65033965Sjdp
65133965Sjdp/*
65233965SjdpFUNCTION
65333965Sjdp	aout_@var{size}_mkobject
65433965Sjdp
65533965SjdpSYNOPSIS
65633965Sjdp	boolean aout_@var{size}_mkobject, (bfd *abfd);
65733965Sjdp
65833965SjdpDESCRIPTION
65933965Sjdp	Initialize BFD @var{abfd} for use with a.out files.
66033965Sjdp*/
66133965Sjdp
66233965Sjdpboolean
66333965SjdpNAME(aout,mkobject) (abfd)
66433965Sjdp     bfd *abfd;
66533965Sjdp{
66633965Sjdp  struct aout_data_struct  *rawptr;
66733965Sjdp
66833965Sjdp  bfd_set_error (bfd_error_system_call);
66933965Sjdp
67033965Sjdp  /* Use an intermediate variable for clarity */
67133965Sjdp  rawptr = (struct aout_data_struct *)bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
67233965Sjdp
67333965Sjdp  if (rawptr == NULL)
67433965Sjdp    return false;
67533965Sjdp
67633965Sjdp  abfd->tdata.aout_data = rawptr;
67733965Sjdp  exec_hdr (abfd) = &(rawptr->e);
67833965Sjdp
67933965Sjdp  obj_textsec (abfd) = (asection *)NULL;
68033965Sjdp  obj_datasec (abfd) = (asection *)NULL;
68133965Sjdp  obj_bsssec (abfd) = (asection *)NULL;
68233965Sjdp
68333965Sjdp  return true;
68433965Sjdp}
68533965Sjdp
68633965Sjdp
68733965Sjdp/*
68833965SjdpFUNCTION
68933965Sjdp	aout_@var{size}_machine_type
69033965Sjdp
69133965SjdpSYNOPSIS
69233965Sjdp	enum machine_type  aout_@var{size}_machine_type
69333965Sjdp	 (enum bfd_architecture arch,
69433965Sjdp	  unsigned long machine));
69533965Sjdp
69633965SjdpDESCRIPTION
69733965Sjdp	Keep track of machine architecture and machine type for
69833965Sjdp	a.out's. Return the <<machine_type>> for a particular
69933965Sjdp	architecture and machine, or <<M_UNKNOWN>> if that exact architecture
70033965Sjdp	and machine can't be represented in a.out format.
70133965Sjdp
70233965Sjdp	If the architecture is understood, machine type 0 (default)
70333965Sjdp	is always understood.
70433965Sjdp*/
70533965Sjdp
70633965Sjdpenum machine_type
70733965SjdpNAME(aout,machine_type) (arch, machine, unknown)
70833965Sjdp     enum bfd_architecture arch;
70933965Sjdp     unsigned long machine;
71033965Sjdp     boolean *unknown;
71133965Sjdp{
71233965Sjdp  enum machine_type arch_flags;
71333965Sjdp
71433965Sjdp  arch_flags = M_UNKNOWN;
71533965Sjdp  *unknown = true;
71633965Sjdp
71733965Sjdp  switch (arch) {
71833965Sjdp  case bfd_arch_sparc:
71933965Sjdp    if (machine == 0
72033965Sjdp	|| machine == bfd_mach_sparc
72133965Sjdp	|| machine == bfd_mach_sparc_sparclite
72260484Sobrien	|| machine == bfd_mach_sparc_sparclite_le
72333965Sjdp	|| machine == bfd_mach_sparc_v9)
72433965Sjdp      arch_flags = M_SPARC;
72533965Sjdp    else if (machine == bfd_mach_sparc_sparclet)
72633965Sjdp      arch_flags = M_SPARCLET;
72733965Sjdp    break;
72833965Sjdp
72933965Sjdp  case bfd_arch_m68k:
73033965Sjdp    switch (machine) {
73138889Sjdp    case 0:		  arch_flags = M_68010; break;
73238889Sjdp    case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = false; break;
73338889Sjdp    case bfd_mach_m68010: arch_flags = M_68010; break;
73438889Sjdp    case bfd_mach_m68020: arch_flags = M_68020; break;
73538889Sjdp    default:		  arch_flags = M_UNKNOWN; break;
73633965Sjdp    }
73733965Sjdp    break;
73833965Sjdp
73933965Sjdp  case bfd_arch_i386:
74033965Sjdp    if (machine == 0)	arch_flags = M_386;
74133965Sjdp    break;
74233965Sjdp
74333965Sjdp  case bfd_arch_a29k:
74433965Sjdp    if (machine == 0)	arch_flags = M_29K;
74533965Sjdp    break;
74633965Sjdp
74733965Sjdp  case bfd_arch_arm:
74833965Sjdp    if (machine == 0)	arch_flags = M_ARM;
74933965Sjdp    break;
75033965Sjdp
75133965Sjdp  case bfd_arch_mips:
75233965Sjdp    switch (machine) {
75333965Sjdp    case 0:
75460484Sobrien    case bfd_mach_mips3000:
75560484Sobrien    case bfd_mach_mips3900:
75660484Sobrien      arch_flags = M_MIPS1;
75760484Sobrien      break;
75860484Sobrien    case bfd_mach_mips6000:
75960484Sobrien      arch_flags = M_MIPS2;
76060484Sobrien      break;
76160484Sobrien    case bfd_mach_mips4000:
76260484Sobrien    case bfd_mach_mips4010:
76360484Sobrien    case bfd_mach_mips4100:
76460484Sobrien    case bfd_mach_mips4300:
76560484Sobrien    case bfd_mach_mips4400:
76660484Sobrien    case bfd_mach_mips4600:
76760484Sobrien    case bfd_mach_mips4650:
76860484Sobrien    case bfd_mach_mips8000:
76960484Sobrien    case bfd_mach_mips10000:
77060484Sobrien    case bfd_mach_mips16:
77160484Sobrien      /* FIXME: These should be MIPS3 or MIPS4.  */
77260484Sobrien      arch_flags = M_MIPS2;
77360484Sobrien      break;
77460484Sobrien    default:
77560484Sobrien      arch_flags = M_UNKNOWN;
77660484Sobrien      break;
77733965Sjdp    }
77833965Sjdp    break;
77933965Sjdp
78033965Sjdp  case bfd_arch_ns32k:
78133965Sjdp    switch (machine) {
78233965Sjdp    case 0:    		arch_flags = M_NS32532; break;
78333965Sjdp    case 32032:		arch_flags = M_NS32032; break;
78433965Sjdp    case 32532:		arch_flags = M_NS32532; break;
78533965Sjdp    default:		arch_flags = M_UNKNOWN; break;
78633965Sjdp    }
78733965Sjdp    break;
78833965Sjdp
78933965Sjdp  case bfd_arch_vax:
79033965Sjdp    *unknown = false;
79133965Sjdp    break;
79233965Sjdp
79333965Sjdp  default:
79433965Sjdp    arch_flags = M_UNKNOWN;
79533965Sjdp  }
79633965Sjdp
79733965Sjdp  if (arch_flags != M_UNKNOWN)
79833965Sjdp    *unknown = false;
79933965Sjdp
80033965Sjdp  return arch_flags;
80133965Sjdp}
80233965Sjdp
80333965Sjdp
80433965Sjdp/*
80533965SjdpFUNCTION
80633965Sjdp	aout_@var{size}_set_arch_mach
80733965Sjdp
80833965SjdpSYNOPSIS
80933965Sjdp	boolean aout_@var{size}_set_arch_mach,
81033965Sjdp	 (bfd *,
81133965Sjdp	  enum bfd_architecture arch,
81233965Sjdp	  unsigned long machine));
81333965Sjdp
81433965SjdpDESCRIPTION
81533965Sjdp	Set the architecture and the machine of the BFD @var{abfd} to the
81633965Sjdp	values @var{arch} and @var{machine}.  Verify that @var{abfd}'s format
81733965Sjdp	can support the architecture required.
81833965Sjdp*/
81933965Sjdp
82033965Sjdpboolean
82133965SjdpNAME(aout,set_arch_mach) (abfd, arch, machine)
82233965Sjdp     bfd *abfd;
82333965Sjdp     enum bfd_architecture arch;
82433965Sjdp     unsigned long machine;
82533965Sjdp{
82633965Sjdp  if (! bfd_default_set_arch_mach (abfd, arch, machine))
82733965Sjdp    return false;
82833965Sjdp
82933965Sjdp  if (arch != bfd_arch_unknown)
83033965Sjdp    {
83133965Sjdp      boolean unknown;
83233965Sjdp
83333965Sjdp      NAME(aout,machine_type) (arch, machine, &unknown);
83433965Sjdp      if (unknown)
83533965Sjdp	return false;
83633965Sjdp    }
83733965Sjdp
83833965Sjdp  /* Determine the size of a relocation entry */
83933965Sjdp  switch (arch) {
84033965Sjdp  case bfd_arch_sparc:
84133965Sjdp  case bfd_arch_a29k:
84233965Sjdp  case bfd_arch_mips:
84333965Sjdp    obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
84433965Sjdp    break;
84533965Sjdp  default:
84633965Sjdp    obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
84733965Sjdp    break;
84833965Sjdp  }
84933965Sjdp
85033965Sjdp  return (*aout_backend_info(abfd)->set_sizes) (abfd);
85133965Sjdp}
85233965Sjdp
85333965Sjdpstatic void
85433965Sjdpadjust_o_magic (abfd, execp)
85533965Sjdp     bfd *abfd;
85633965Sjdp     struct internal_exec *execp;
85733965Sjdp{
85833965Sjdp  file_ptr pos = adata (abfd).exec_bytes_size;
85933965Sjdp  bfd_vma vma = 0;
86033965Sjdp  int pad = 0;
86133965Sjdp
86233965Sjdp  /* Text.  */
86333965Sjdp  obj_textsec(abfd)->filepos = pos;
86433965Sjdp  if (!obj_textsec(abfd)->user_set_vma)
86533965Sjdp    obj_textsec(abfd)->vma = vma;
86633965Sjdp  else
86733965Sjdp    vma = obj_textsec(abfd)->vma;
86833965Sjdp
86933965Sjdp  pos += obj_textsec(abfd)->_raw_size;
87033965Sjdp  vma += obj_textsec(abfd)->_raw_size;
87133965Sjdp
87233965Sjdp  /* Data.  */
87333965Sjdp  if (!obj_datasec(abfd)->user_set_vma)
87433965Sjdp    {
87533965Sjdp#if 0	    /* ?? Does alignment in the file image really matter? */
87633965Sjdp      pad = align_power (vma, obj_datasec(abfd)->alignment_power) - vma;
87733965Sjdp#endif
87833965Sjdp      obj_textsec(abfd)->_raw_size += pad;
87933965Sjdp      pos += pad;
88033965Sjdp      vma += pad;
88133965Sjdp      obj_datasec(abfd)->vma = vma;
88233965Sjdp    }
88333965Sjdp  else
88433965Sjdp    vma = obj_datasec(abfd)->vma;
88533965Sjdp  obj_datasec(abfd)->filepos = pos;
88633965Sjdp  pos += obj_datasec(abfd)->_raw_size;
88733965Sjdp  vma += obj_datasec(abfd)->_raw_size;
88833965Sjdp
88933965Sjdp  /* BSS.  */
89033965Sjdp  if (!obj_bsssec(abfd)->user_set_vma)
89133965Sjdp    {
89233965Sjdp#if 0
89333965Sjdp      pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma;
89433965Sjdp#endif
89533965Sjdp      obj_datasec(abfd)->_raw_size += pad;
89633965Sjdp      pos += pad;
89733965Sjdp      vma += pad;
89833965Sjdp      obj_bsssec(abfd)->vma = vma;
89933965Sjdp    }
90033965Sjdp  else
90133965Sjdp    {
90233965Sjdp      /* The VMA of the .bss section is set by the the VMA of the
90333965Sjdp         .data section plus the size of the .data section.  We may
90433965Sjdp         need to add padding bytes to make this true.  */
90533965Sjdp      pad = obj_bsssec (abfd)->vma - vma;
90633965Sjdp      if (pad > 0)
90733965Sjdp	{
90833965Sjdp	  obj_datasec (abfd)->_raw_size += pad;
90933965Sjdp	  pos += pad;
91033965Sjdp	}
91133965Sjdp    }
91233965Sjdp  obj_bsssec(abfd)->filepos = pos;
91333965Sjdp
91433965Sjdp  /* Fix up the exec header.  */
91533965Sjdp  execp->a_text = obj_textsec(abfd)->_raw_size;
91633965Sjdp  execp->a_data = obj_datasec(abfd)->_raw_size;
91733965Sjdp  execp->a_bss = obj_bsssec(abfd)->_raw_size;
91833965Sjdp  N_SET_MAGIC (*execp, OMAGIC);
91933965Sjdp}
92033965Sjdp
92133965Sjdpstatic void
92233965Sjdpadjust_z_magic (abfd, execp)
92333965Sjdp     bfd *abfd;
92433965Sjdp     struct internal_exec *execp;
92533965Sjdp{
92633965Sjdp  bfd_size_type data_pad, text_pad;
92733965Sjdp  file_ptr text_end;
92833965Sjdp  CONST struct aout_backend_data *abdp;
92933965Sjdp  int ztih;			/* Nonzero if text includes exec header.  */
93033965Sjdp
93133965Sjdp  abdp = aout_backend_info (abfd);
93233965Sjdp
93333965Sjdp  /* Text.  */
93433965Sjdp  ztih = (abdp != NULL
93533965Sjdp	  && (abdp->text_includes_header
93633965Sjdp	      || obj_aout_subformat (abfd) == q_magic_format));
93733965Sjdp  obj_textsec(abfd)->filepos = (ztih
93833965Sjdp				? adata(abfd).exec_bytes_size
93933965Sjdp				: adata(abfd).zmagic_disk_block_size);
94033965Sjdp  if (! obj_textsec(abfd)->user_set_vma)
94133965Sjdp    {
94233965Sjdp      /* ?? Do we really need to check for relocs here?  */
94333965Sjdp      obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC)
94433965Sjdp				? 0
94533965Sjdp				: (ztih
94633965Sjdp				   ? (abdp->default_text_vma
94733965Sjdp				      + adata(abfd).exec_bytes_size)
94833965Sjdp				   : abdp->default_text_vma));
94933965Sjdp      text_pad = 0;
95033965Sjdp    }
95133965Sjdp  else
95233965Sjdp    {
95333965Sjdp      /* The .text section is being loaded at an unusual address.  We
95433965Sjdp         may need to pad it such that the .data section starts at a page
95533965Sjdp         boundary.  */
95633965Sjdp      if (ztih)
95733965Sjdp	text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma)
95833965Sjdp		    & (adata (abfd).page_size - 1));
95933965Sjdp      else
96033965Sjdp	text_pad = ((- obj_textsec (abfd)->vma)
96133965Sjdp		    & (adata (abfd).page_size - 1));
96233965Sjdp    }
96333965Sjdp
96433965Sjdp  /* Find start of data.  */
96533965Sjdp  if (ztih)
96633965Sjdp    {
96733965Sjdp      text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size;
96833965Sjdp      text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
96933965Sjdp    }
97033965Sjdp  else
97133965Sjdp    {
97233965Sjdp      /* Note that if page_size == zmagic_disk_block_size, then
97333965Sjdp	 filepos == page_size, and this case is the same as the ztih
97433965Sjdp	 case.  */
97533965Sjdp      text_end = obj_textsec (abfd)->_raw_size;
97633965Sjdp      text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
97733965Sjdp      text_end += obj_textsec (abfd)->filepos;
97833965Sjdp    }
97933965Sjdp  obj_textsec(abfd)->_raw_size += text_pad;
98033965Sjdp  text_end += text_pad;
98133965Sjdp
98233965Sjdp  /* Data.  */
98333965Sjdp  if (!obj_datasec(abfd)->user_set_vma)
98433965Sjdp    {
98533965Sjdp      bfd_vma vma;
98633965Sjdp      vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size;
98733965Sjdp      obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
98833965Sjdp    }
98933965Sjdp  if (abdp && abdp->zmagic_mapped_contiguous)
99033965Sjdp    {
99133965Sjdp      text_pad = (obj_datasec(abfd)->vma
99233965Sjdp		  - obj_textsec(abfd)->vma
99333965Sjdp		  - obj_textsec(abfd)->_raw_size);
99433965Sjdp      obj_textsec(abfd)->_raw_size += text_pad;
99533965Sjdp    }
99633965Sjdp  obj_datasec(abfd)->filepos = (obj_textsec(abfd)->filepos
99733965Sjdp				+ obj_textsec(abfd)->_raw_size);
99833965Sjdp
99933965Sjdp  /* Fix up exec header while we're at it.  */
100033965Sjdp  execp->a_text = obj_textsec(abfd)->_raw_size;
100133965Sjdp  if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
100233965Sjdp    execp->a_text += adata(abfd).exec_bytes_size;
100333965Sjdp  if (obj_aout_subformat (abfd) == q_magic_format)
100433965Sjdp    N_SET_MAGIC (*execp, QMAGIC);
100533965Sjdp  else
100633965Sjdp    N_SET_MAGIC (*execp, ZMAGIC);
100733965Sjdp
100833965Sjdp  /* Spec says data section should be rounded up to page boundary.  */
100933965Sjdp  obj_datasec(abfd)->_raw_size
101033965Sjdp    = align_power (obj_datasec(abfd)->_raw_size,
101133965Sjdp		   obj_bsssec(abfd)->alignment_power);
101233965Sjdp  execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size,
101333965Sjdp			     adata(abfd).page_size);
101433965Sjdp  data_pad = execp->a_data - obj_datasec(abfd)->_raw_size;
101533965Sjdp
101633965Sjdp  /* BSS.  */
101733965Sjdp  if (!obj_bsssec(abfd)->user_set_vma)
101833965Sjdp    obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma
101933965Sjdp			     + obj_datasec(abfd)->_raw_size);
102033965Sjdp  /* If the BSS immediately follows the data section and extra space
102133965Sjdp     in the page is left after the data section, fudge data
102233965Sjdp     in the header so that the bss section looks smaller by that
102333965Sjdp     amount.  We'll start the bss section there, and lie to the OS.
102433965Sjdp     (Note that a linker script, as well as the above assignment,
102533965Sjdp     could have explicitly set the BSS vma to immediately follow
102633965Sjdp     the data section.)  */
102733965Sjdp  if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power)
102833965Sjdp      == obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size)
102933965Sjdp    execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 :
103033965Sjdp      obj_bsssec(abfd)->_raw_size - data_pad;
103133965Sjdp  else
103233965Sjdp    execp->a_bss = obj_bsssec(abfd)->_raw_size;
103333965Sjdp}
103433965Sjdp
103533965Sjdpstatic void
103633965Sjdpadjust_n_magic (abfd, execp)
103733965Sjdp     bfd *abfd;
103833965Sjdp     struct internal_exec *execp;
103933965Sjdp{
104033965Sjdp  file_ptr pos = adata(abfd).exec_bytes_size;
104133965Sjdp  bfd_vma vma = 0;
104233965Sjdp  int pad;
104333965Sjdp
104433965Sjdp  /* Text.  */
104533965Sjdp  obj_textsec(abfd)->filepos = pos;
104633965Sjdp  if (!obj_textsec(abfd)->user_set_vma)
104733965Sjdp    obj_textsec(abfd)->vma = vma;
104833965Sjdp  else
104933965Sjdp    vma = obj_textsec(abfd)->vma;
105033965Sjdp  pos += obj_textsec(abfd)->_raw_size;
105133965Sjdp  vma += obj_textsec(abfd)->_raw_size;
105233965Sjdp
105333965Sjdp  /* Data.  */
105433965Sjdp  obj_datasec(abfd)->filepos = pos;
105533965Sjdp  if (!obj_datasec(abfd)->user_set_vma)
105633965Sjdp    obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
105733965Sjdp  vma = obj_datasec(abfd)->vma;
105833965Sjdp
105933965Sjdp  /* Since BSS follows data immediately, see if it needs alignment.  */
106033965Sjdp  vma += obj_datasec(abfd)->_raw_size;
106133965Sjdp  pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma;
106233965Sjdp  obj_datasec(abfd)->_raw_size += pad;
106333965Sjdp  pos += obj_datasec(abfd)->_raw_size;
106433965Sjdp
106533965Sjdp  /* BSS.  */
106633965Sjdp  if (!obj_bsssec(abfd)->user_set_vma)
106733965Sjdp    obj_bsssec(abfd)->vma = vma;
106833965Sjdp  else
106933965Sjdp    vma = obj_bsssec(abfd)->vma;
107033965Sjdp
107133965Sjdp  /* Fix up exec header.  */
107233965Sjdp  execp->a_text = obj_textsec(abfd)->_raw_size;
107333965Sjdp  execp->a_data = obj_datasec(abfd)->_raw_size;
107433965Sjdp  execp->a_bss = obj_bsssec(abfd)->_raw_size;
107533965Sjdp  N_SET_MAGIC (*execp, NMAGIC);
107633965Sjdp}
107733965Sjdp
107833965Sjdpboolean
107933965SjdpNAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end)
108033965Sjdp     bfd *abfd;
108133965Sjdp     bfd_size_type *text_size;
108260484Sobrien     file_ptr *text_end ATTRIBUTE_UNUSED;
108333965Sjdp{
108433965Sjdp  struct internal_exec *execp = exec_hdr (abfd);
108533965Sjdp
108633965Sjdp  if (! NAME(aout,make_sections) (abfd))
108733965Sjdp    return false;
108833965Sjdp
108933965Sjdp  if (adata(abfd).magic != undecided_magic)
109033965Sjdp    return true;
109133965Sjdp
109233965Sjdp  obj_textsec(abfd)->_raw_size =
109333965Sjdp    align_power(obj_textsec(abfd)->_raw_size,
109433965Sjdp		obj_textsec(abfd)->alignment_power);
109533965Sjdp
109633965Sjdp  *text_size = obj_textsec (abfd)->_raw_size;
109733965Sjdp  /* Rule (heuristic) for when to pad to a new page.  Note that there
109833965Sjdp     are (at least) two ways demand-paged (ZMAGIC) files have been
109933965Sjdp     handled.  Most Berkeley-based systems start the text segment at
110033965Sjdp     (TARGET_PAGE_SIZE).  However, newer versions of SUNOS start the text
110133965Sjdp     segment right after the exec header; the latter is counted in the
110233965Sjdp     text segment size, and is paged in by the kernel with the rest of
110333965Sjdp     the text. */
110433965Sjdp
110533965Sjdp  /* This perhaps isn't the right way to do this, but made it simpler for me
110633965Sjdp     to understand enough to implement it.  Better would probably be to go
110733965Sjdp     right from BFD flags to alignment/positioning characteristics.  But the
110833965Sjdp     old code was sloppy enough about handling the flags, and had enough
110933965Sjdp     other magic, that it was a little hard for me to understand.  I think
111033965Sjdp     I understand it better now, but I haven't time to do the cleanup this
111133965Sjdp     minute.  */
111233965Sjdp
111333965Sjdp  if (abfd->flags & D_PAGED)
111433965Sjdp    /* Whether or not WP_TEXT is set -- let D_PAGED override.  */
111533965Sjdp    adata(abfd).magic = z_magic;
111633965Sjdp  else if (abfd->flags & WP_TEXT)
111733965Sjdp    adata(abfd).magic = n_magic;
111833965Sjdp  else
111933965Sjdp    adata(abfd).magic = o_magic;
112033965Sjdp
112133965Sjdp#ifdef BFD_AOUT_DEBUG /* requires gcc2 */
112233965Sjdp#if __GNUC__ >= 2
112333965Sjdp  fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
112433965Sjdp	   ({ char *str;
112533965Sjdp	      switch (adata(abfd).magic) {
112633965Sjdp	      case n_magic: str = "NMAGIC"; break;
112733965Sjdp	      case o_magic: str = "OMAGIC"; break;
112833965Sjdp	      case z_magic: str = "ZMAGIC"; break;
112933965Sjdp	      default: abort ();
113033965Sjdp	      }
113133965Sjdp	      str;
113233965Sjdp	    }),
113333965Sjdp	   obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size,
113433965Sjdp	   	obj_textsec(abfd)->alignment_power,
113533965Sjdp	   obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size,
113633965Sjdp	   	obj_datasec(abfd)->alignment_power,
113733965Sjdp	   obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size,
113833965Sjdp	   	obj_bsssec(abfd)->alignment_power);
113933965Sjdp#endif
114033965Sjdp#endif
114133965Sjdp
114233965Sjdp  switch (adata(abfd).magic)
114333965Sjdp    {
114433965Sjdp    case o_magic:
114533965Sjdp      adjust_o_magic (abfd, execp);
114633965Sjdp      break;
114733965Sjdp    case z_magic:
114833965Sjdp      adjust_z_magic (abfd, execp);
114933965Sjdp      break;
115033965Sjdp    case n_magic:
115133965Sjdp      adjust_n_magic (abfd, execp);
115233965Sjdp      break;
115333965Sjdp    default:
115433965Sjdp      abort ();
115533965Sjdp    }
115633965Sjdp
115733965Sjdp#ifdef BFD_AOUT_DEBUG
115833965Sjdp  fprintf (stderr, "       text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n",
115933965Sjdp	   obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size,
116033965Sjdp	   	obj_textsec(abfd)->filepos,
116133965Sjdp	   obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size,
116233965Sjdp	   	obj_datasec(abfd)->filepos,
116333965Sjdp	   obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size);
116433965Sjdp#endif
116533965Sjdp
116633965Sjdp  return true;
116733965Sjdp}
116833965Sjdp
116933965Sjdp/*
117033965SjdpFUNCTION
117133965Sjdp	aout_@var{size}_new_section_hook
117233965Sjdp
117333965SjdpSYNOPSIS
117433965Sjdp        boolean aout_@var{size}_new_section_hook,
117533965Sjdp	   (bfd *abfd,
117633965Sjdp	    asection *newsect));
117733965Sjdp
117833965SjdpDESCRIPTION
117933965Sjdp	Called by the BFD in response to a @code{bfd_make_section}
118033965Sjdp	request.
118133965Sjdp*/
118233965Sjdpboolean
118333965SjdpNAME(aout,new_section_hook) (abfd, newsect)
118433965Sjdp     bfd *abfd;
118533965Sjdp     asection *newsect;
118633965Sjdp{
118733965Sjdp  /* align to double at least */
118833965Sjdp  newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power;
118933965Sjdp
119033965Sjdp
119133965Sjdp  if (bfd_get_format (abfd) == bfd_object)
119233965Sjdp  {
119333965Sjdp    if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
119433965Sjdp	obj_textsec(abfd)= newsect;
119533965Sjdp	newsect->target_index = N_TEXT;
119633965Sjdp	return true;
119733965Sjdp      }
119833965Sjdp
119933965Sjdp    if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
120033965Sjdp	obj_datasec(abfd) = newsect;
120133965Sjdp	newsect->target_index = N_DATA;
120233965Sjdp	return true;
120333965Sjdp      }
120433965Sjdp
120533965Sjdp    if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
120633965Sjdp	obj_bsssec(abfd) = newsect;
120733965Sjdp	newsect->target_index = N_BSS;
120833965Sjdp	return true;
120933965Sjdp      }
121033965Sjdp
121133965Sjdp  }
121233965Sjdp
121333965Sjdp  /* We allow more than three sections internally */
121433965Sjdp  return true;
121533965Sjdp}
121633965Sjdp
121733965Sjdpboolean
121833965SjdpNAME(aout,set_section_contents) (abfd, section, location, offset, count)
121933965Sjdp     bfd *abfd;
122033965Sjdp     sec_ptr section;
122133965Sjdp     PTR location;
122233965Sjdp     file_ptr offset;
122333965Sjdp     bfd_size_type count;
122433965Sjdp{
122533965Sjdp  file_ptr text_end;
122633965Sjdp  bfd_size_type text_size;
122733965Sjdp
122833965Sjdp  if (! abfd->output_has_begun)
122933965Sjdp    {
123033965Sjdp      if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
123133965Sjdp	return false;
123233965Sjdp    }
123333965Sjdp
123433965Sjdp  if (section == obj_bsssec (abfd))
123533965Sjdp    {
123633965Sjdp      bfd_set_error (bfd_error_no_contents);
123733965Sjdp      return false;
123833965Sjdp    }
123933965Sjdp
124033965Sjdp  if (section != obj_textsec (abfd)
124133965Sjdp      && section != obj_datasec (abfd))
124233965Sjdp    {
124333965Sjdp      (*_bfd_error_handler)
124460484Sobrien	(_("%s: can not represent section `%s' in a.out object file format"),
124533965Sjdp	 bfd_get_filename (abfd), bfd_get_section_name (abfd, section));
124633965Sjdp      bfd_set_error (bfd_error_nonrepresentable_section);
124733965Sjdp      return false;
124833965Sjdp    }
124933965Sjdp
125033965Sjdp  if (count != 0)
125133965Sjdp    {
125233965Sjdp      if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
125333965Sjdp	  || bfd_write (location, 1, count, abfd) != count)
125433965Sjdp	return false;
125533965Sjdp    }
125633965Sjdp
125733965Sjdp  return true;
125833965Sjdp}
125933965Sjdp
126033965Sjdp/* Read the external symbols from an a.out file.  */
126133965Sjdp
126233965Sjdpstatic boolean
126333965Sjdpaout_get_external_symbols (abfd)
126433965Sjdp     bfd *abfd;
126533965Sjdp{
126633965Sjdp  if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL)
126733965Sjdp    {
126833965Sjdp      bfd_size_type count;
126933965Sjdp      struct external_nlist *syms;
127033965Sjdp
127133965Sjdp      count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
127233965Sjdp
127333965Sjdp#ifdef USE_MMAP
127433965Sjdp      if (bfd_get_file_window (abfd,
127533965Sjdp			       obj_sym_filepos (abfd), exec_hdr (abfd)->a_syms,
127633965Sjdp			       &obj_aout_sym_window (abfd), true) == false)
127733965Sjdp	return false;
127833965Sjdp      syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
127933965Sjdp#else
128033965Sjdp      /* We allocate using malloc to make the values easy to free
128133965Sjdp	 later on.  If we put them on the objalloc it might not be
128233965Sjdp	 possible to free them.  */
128333965Sjdp      syms = ((struct external_nlist *)
128433965Sjdp	      bfd_malloc ((size_t) count * EXTERNAL_NLIST_SIZE));
128533965Sjdp      if (syms == (struct external_nlist *) NULL && count != 0)
128633965Sjdp	return false;
128733965Sjdp
128833965Sjdp      if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
128933965Sjdp	  || (bfd_read (syms, 1, exec_hdr (abfd)->a_syms, abfd)
129033965Sjdp	      != exec_hdr (abfd)->a_syms))
129133965Sjdp	{
129233965Sjdp	  free (syms);
129333965Sjdp	  return false;
129433965Sjdp	}
129533965Sjdp#endif
129633965Sjdp
129733965Sjdp      obj_aout_external_syms (abfd) = syms;
129833965Sjdp      obj_aout_external_sym_count (abfd) = count;
129933965Sjdp    }
130033965Sjdp
130133965Sjdp  if (obj_aout_external_strings (abfd) == NULL
130233965Sjdp      && exec_hdr (abfd)->a_syms != 0)
130333965Sjdp    {
130433965Sjdp      unsigned char string_chars[BYTES_IN_WORD];
130533965Sjdp      bfd_size_type stringsize;
130633965Sjdp      char *strings;
130733965Sjdp
130833965Sjdp      /* Get the size of the strings.  */
130933965Sjdp      if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
131033965Sjdp	  || (bfd_read ((PTR) string_chars, BYTES_IN_WORD, 1, abfd)
131133965Sjdp	      != BYTES_IN_WORD))
131233965Sjdp	return false;
131333965Sjdp      stringsize = GET_WORD (abfd, string_chars);
131433965Sjdp
131533965Sjdp#ifdef USE_MMAP
131633965Sjdp      if (bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize,
131733965Sjdp			       &obj_aout_string_window (abfd), true) == false)
131833965Sjdp	return false;
131933965Sjdp      strings = (char *) obj_aout_string_window (abfd).data;
132033965Sjdp#else
132133965Sjdp      strings = (char *) bfd_malloc ((size_t) stringsize + 1);
132233965Sjdp      if (strings == NULL)
132333965Sjdp	return false;
132433965Sjdp
132533965Sjdp      /* Skip space for the string count in the buffer for convenience
132633965Sjdp	 when using indexes.  */
132733965Sjdp      if (bfd_read (strings + BYTES_IN_WORD, 1, stringsize - BYTES_IN_WORD,
132833965Sjdp		    abfd)
132933965Sjdp	  != stringsize - BYTES_IN_WORD)
133033965Sjdp	{
133133965Sjdp	  free (strings);
133233965Sjdp	  return false;
133333965Sjdp	}
133433965Sjdp#endif
133533965Sjdp
133633965Sjdp      /* Ensure that a zero index yields an empty string.  */
133733965Sjdp      strings[0] = '\0';
133833965Sjdp
133933965Sjdp      strings[stringsize - 1] = 0;
134033965Sjdp
134133965Sjdp      obj_aout_external_strings (abfd) = strings;
134233965Sjdp      obj_aout_external_string_size (abfd) = stringsize;
134333965Sjdp    }
134433965Sjdp
134533965Sjdp  return true;
134633965Sjdp}
134733965Sjdp
134833965Sjdp/* Translate an a.out symbol into a BFD symbol.  The desc, other, type
134933965Sjdp   and symbol->value fields of CACHE_PTR will be set from the a.out
135033965Sjdp   nlist structure.  This function is responsible for setting
135133965Sjdp   symbol->flags and symbol->section, and adjusting symbol->value.  */
135233965Sjdp
135333965Sjdpstatic boolean
135433965Sjdptranslate_from_native_sym_flags (abfd, cache_ptr)
135533965Sjdp     bfd *abfd;
135633965Sjdp     aout_symbol_type *cache_ptr;
135733965Sjdp{
135833965Sjdp  flagword visible;
135933965Sjdp
136033965Sjdp  if ((cache_ptr->type & N_STAB) != 0
136133965Sjdp      || cache_ptr->type == N_FN)
136233965Sjdp    {
136333965Sjdp      asection *sec;
136433965Sjdp
136533965Sjdp      /* This is a debugging symbol.  */
136633965Sjdp
136733965Sjdp      cache_ptr->symbol.flags = BSF_DEBUGGING;
136833965Sjdp
136933965Sjdp      /* Work out the symbol section.  */
137033965Sjdp      switch (cache_ptr->type & N_TYPE)
137133965Sjdp	{
137233965Sjdp	case N_TEXT:
137333965Sjdp	case N_FN:
137433965Sjdp	  sec = obj_textsec (abfd);
137533965Sjdp	  break;
137633965Sjdp	case N_DATA:
137733965Sjdp	  sec = obj_datasec (abfd);
137833965Sjdp	  break;
137933965Sjdp	case N_BSS:
138033965Sjdp	  sec = obj_bsssec (abfd);
138133965Sjdp	  break;
138233965Sjdp	default:
138333965Sjdp	case N_ABS:
138433965Sjdp	  sec = bfd_abs_section_ptr;
138533965Sjdp	  break;
138633965Sjdp	}
138733965Sjdp
138833965Sjdp      cache_ptr->symbol.section = sec;
138933965Sjdp      cache_ptr->symbol.value -= sec->vma;
139033965Sjdp
139133965Sjdp      return true;
139233965Sjdp    }
139333965Sjdp
139433965Sjdp  /* Get the default visibility.  This does not apply to all types, so
139533965Sjdp     we just hold it in a local variable to use if wanted.  */
139633965Sjdp  if ((cache_ptr->type & N_EXT) == 0)
139733965Sjdp    visible = BSF_LOCAL;
139833965Sjdp  else
139933965Sjdp    visible = BSF_GLOBAL;
140033965Sjdp
140133965Sjdp  switch (cache_ptr->type)
140233965Sjdp    {
140333965Sjdp    default:
140433965Sjdp    case N_ABS: case N_ABS | N_EXT:
140533965Sjdp      cache_ptr->symbol.section = bfd_abs_section_ptr;
140633965Sjdp      cache_ptr->symbol.flags = visible;
140733965Sjdp      break;
140833965Sjdp
140933965Sjdp    case N_UNDF | N_EXT:
141033965Sjdp      if (cache_ptr->symbol.value != 0)
141133965Sjdp	{
141233965Sjdp	  /* This is a common symbol.  */
141333965Sjdp	  cache_ptr->symbol.flags = BSF_GLOBAL;
141433965Sjdp	  cache_ptr->symbol.section = bfd_com_section_ptr;
141533965Sjdp	}
141633965Sjdp      else
141733965Sjdp	{
141833965Sjdp	  cache_ptr->symbol.flags = 0;
141933965Sjdp	  cache_ptr->symbol.section = bfd_und_section_ptr;
142033965Sjdp	}
142133965Sjdp      break;
142233965Sjdp
142333965Sjdp    case N_TEXT: case N_TEXT | N_EXT:
142433965Sjdp      cache_ptr->symbol.section = obj_textsec (abfd);
142533965Sjdp      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
142633965Sjdp      cache_ptr->symbol.flags = visible;
142733965Sjdp      break;
142833965Sjdp
142933965Sjdp      /* N_SETV symbols used to represent set vectors placed in the
143033965Sjdp	 data section.  They are no longer generated.  Theoretically,
143133965Sjdp	 it was possible to extract the entries and combine them with
143233965Sjdp	 new ones, although I don't know if that was ever actually
143333965Sjdp	 done.  Unless that feature is restored, treat them as data
143433965Sjdp	 symbols.  */
143533965Sjdp    case N_SETV: case N_SETV | N_EXT:
143633965Sjdp    case N_DATA: case N_DATA | N_EXT:
143733965Sjdp      cache_ptr->symbol.section = obj_datasec (abfd);
143833965Sjdp      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
143933965Sjdp      cache_ptr->symbol.flags = visible;
144033965Sjdp      break;
144133965Sjdp
144233965Sjdp    case N_BSS: case N_BSS | N_EXT:
144333965Sjdp      cache_ptr->symbol.section = obj_bsssec (abfd);
144433965Sjdp      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
144533965Sjdp      cache_ptr->symbol.flags = visible;
144633965Sjdp      break;
144733965Sjdp
144833965Sjdp    case N_SETA: case N_SETA | N_EXT:
144933965Sjdp    case N_SETT: case N_SETT | N_EXT:
145033965Sjdp    case N_SETD: case N_SETD | N_EXT:
145133965Sjdp    case N_SETB: case N_SETB | N_EXT:
145233965Sjdp      {
145333965Sjdp	/* This code is no longer needed.  It used to be used to make
145433965Sjdp           the linker handle set symbols, but they are now handled in
145533965Sjdp           the add_symbols routine instead.  */
145633965Sjdp#if 0
145733965Sjdp	asection *section;
145833965Sjdp	arelent_chain *reloc;
145933965Sjdp	asection *into_section;
146033965Sjdp
146133965Sjdp	/* This is a set symbol.  The name of the symbol is the name
146233965Sjdp	   of the set (e.g., __CTOR_LIST__).  The value of the symbol
146333965Sjdp	   is the value to add to the set.  We create a section with
146433965Sjdp	   the same name as the symbol, and add a reloc to insert the
146533965Sjdp	   appropriate value into the section.
146633965Sjdp
146733965Sjdp	   This action is actually obsolete; it used to make the
146833965Sjdp	   linker do the right thing, but the linker no longer uses
146933965Sjdp	   this function.  */
147033965Sjdp
147133965Sjdp	section = bfd_get_section_by_name (abfd, cache_ptr->symbol.name);
147233965Sjdp	if (section == NULL)
147333965Sjdp	  {
147433965Sjdp	    char *copy;
147533965Sjdp
147633965Sjdp	    copy = bfd_alloc (abfd, strlen (cache_ptr->symbol.name) + 1);
147733965Sjdp	    if (copy == NULL)
147833965Sjdp	      return false;
147933965Sjdp
148033965Sjdp	    strcpy (copy, cache_ptr->symbol.name);
148133965Sjdp	    section = bfd_make_section (abfd, copy);
148233965Sjdp	    if (section == NULL)
148333965Sjdp	      return false;
148433965Sjdp	  }
148533965Sjdp
148633965Sjdp	reloc = (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
148733965Sjdp	if (reloc == NULL)
148833965Sjdp	  return false;
148933965Sjdp
149033965Sjdp	/* Build a relocation entry for the constructor.  */
149133965Sjdp	switch (cache_ptr->type & N_TYPE)
149233965Sjdp	  {
149333965Sjdp	  case N_SETA:
149433965Sjdp	    into_section = bfd_abs_section_ptr;
149533965Sjdp	    cache_ptr->type = N_ABS;
149633965Sjdp	    break;
149733965Sjdp	  case N_SETT:
149833965Sjdp	    into_section = obj_textsec (abfd);
149933965Sjdp	    cache_ptr->type = N_TEXT;
150033965Sjdp	    break;
150133965Sjdp	  case N_SETD:
150233965Sjdp	    into_section = obj_datasec (abfd);
150333965Sjdp	    cache_ptr->type = N_DATA;
150433965Sjdp	    break;
150533965Sjdp	  case N_SETB:
150633965Sjdp	    into_section = obj_bsssec (abfd);
150733965Sjdp	    cache_ptr->type = N_BSS;
150833965Sjdp	    break;
150933965Sjdp	  }
151033965Sjdp
151133965Sjdp	/* Build a relocation pointing into the constructor section
151233965Sjdp	   pointing at the symbol in the set vector specified.  */
151333965Sjdp	reloc->relent.addend = cache_ptr->symbol.value;
151433965Sjdp	cache_ptr->symbol.section = into_section;
151533965Sjdp	reloc->relent.sym_ptr_ptr = into_section->symbol_ptr_ptr;
151633965Sjdp
151733965Sjdp	/* We modify the symbol to belong to a section depending upon
151833965Sjdp	   the name of the symbol, and add to the size of the section
151933965Sjdp	   to contain a pointer to the symbol. Build a reloc entry to
152033965Sjdp	   relocate to this symbol attached to this section.  */
152133965Sjdp	section->flags = SEC_CONSTRUCTOR | SEC_RELOC;
152233965Sjdp
152333965Sjdp	section->reloc_count++;
152433965Sjdp	section->alignment_power = 2;
152533965Sjdp
152633965Sjdp	reloc->next = section->constructor_chain;
152733965Sjdp	section->constructor_chain = reloc;
152833965Sjdp	reloc->relent.address = section->_raw_size;
152933965Sjdp	section->_raw_size += BYTES_IN_WORD;
153033965Sjdp
153133965Sjdp	reloc->relent.howto = CTOR_TABLE_RELOC_HOWTO(abfd);
153233965Sjdp
153333965Sjdp#endif /* 0 */
153433965Sjdp
153533965Sjdp	switch (cache_ptr->type & N_TYPE)
153633965Sjdp	  {
153733965Sjdp	  case N_SETA:
153833965Sjdp	    cache_ptr->symbol.section = bfd_abs_section_ptr;
153933965Sjdp	    break;
154033965Sjdp	  case N_SETT:
154133965Sjdp	    cache_ptr->symbol.section = obj_textsec (abfd);
154233965Sjdp	    break;
154333965Sjdp	  case N_SETD:
154433965Sjdp	    cache_ptr->symbol.section = obj_datasec (abfd);
154533965Sjdp	    break;
154633965Sjdp	  case N_SETB:
154733965Sjdp	    cache_ptr->symbol.section = obj_bsssec (abfd);
154833965Sjdp	    break;
154933965Sjdp	  }
155033965Sjdp
155133965Sjdp	cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
155233965Sjdp      }
155333965Sjdp      break;
155433965Sjdp
155533965Sjdp    case N_WARNING:
155633965Sjdp      /* This symbol is the text of a warning message.  The next
155733965Sjdp	 symbol is the symbol to associate the warning with.  If a
155833965Sjdp	 reference is made to that symbol, a warning is issued.  */
155933965Sjdp      cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
156033965Sjdp      cache_ptr->symbol.section = bfd_abs_section_ptr;
156133965Sjdp      break;
156233965Sjdp
156333965Sjdp    case N_INDR: case N_INDR | N_EXT:
156433965Sjdp      /* An indirect symbol.  This consists of two symbols in a row.
156533965Sjdp	 The first symbol is the name of the indirection.  The second
156633965Sjdp	 symbol is the name of the target.  A reference to the first
156733965Sjdp	 symbol becomes a reference to the second.  */
156833965Sjdp      cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible;
156933965Sjdp      cache_ptr->symbol.section = bfd_ind_section_ptr;
157033965Sjdp      break;
157133965Sjdp
157233965Sjdp    case N_WEAKU:
157333965Sjdp      cache_ptr->symbol.section = bfd_und_section_ptr;
157433965Sjdp      cache_ptr->symbol.flags = BSF_WEAK;
157533965Sjdp      break;
157633965Sjdp
157733965Sjdp    case N_WEAKA:
157833965Sjdp      cache_ptr->symbol.section = bfd_abs_section_ptr;
157933965Sjdp      cache_ptr->symbol.flags = BSF_WEAK;
158033965Sjdp      break;
158133965Sjdp
158233965Sjdp    case N_WEAKT:
158333965Sjdp      cache_ptr->symbol.section = obj_textsec (abfd);
158433965Sjdp      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
158533965Sjdp      cache_ptr->symbol.flags = BSF_WEAK;
158633965Sjdp      break;
158733965Sjdp
158833965Sjdp    case N_WEAKD:
158933965Sjdp      cache_ptr->symbol.section = obj_datasec (abfd);
159033965Sjdp      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
159133965Sjdp      cache_ptr->symbol.flags = BSF_WEAK;
159233965Sjdp      break;
159333965Sjdp
159433965Sjdp    case N_WEAKB:
159533965Sjdp      cache_ptr->symbol.section = obj_bsssec (abfd);
159633965Sjdp      cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
159733965Sjdp      cache_ptr->symbol.flags = BSF_WEAK;
159833965Sjdp      break;
159933965Sjdp    }
160033965Sjdp
160133965Sjdp  return true;
160233965Sjdp}
160333965Sjdp
160433965Sjdp/* Set the fields of SYM_POINTER according to CACHE_PTR.  */
160533965Sjdp
160633965Sjdpstatic boolean
160733965Sjdptranslate_to_native_sym_flags (abfd, cache_ptr, sym_pointer)
160833965Sjdp     bfd *abfd;
160933965Sjdp     asymbol *cache_ptr;
161033965Sjdp     struct external_nlist *sym_pointer;
161133965Sjdp{
161233965Sjdp  bfd_vma value = cache_ptr->value;
161333965Sjdp  asection *sec;
161433965Sjdp  bfd_vma off;
161533965Sjdp
161633965Sjdp  /* Mask out any existing type bits in case copying from one section
161733965Sjdp     to another.  */
161833965Sjdp  sym_pointer->e_type[0] &= ~N_TYPE;
161933965Sjdp
162033965Sjdp  sec = bfd_get_section (cache_ptr);
162133965Sjdp  off = 0;
162233965Sjdp
162333965Sjdp  if (sec == NULL)
162433965Sjdp    {
162533965Sjdp      /* This case occurs, e.g., for the *DEBUG* section of a COFF
162633965Sjdp	 file.  */
162733965Sjdp      (*_bfd_error_handler)
162860484Sobrien	(_("%s: can not represent section for symbol `%s' in a.out object file format"),
162933965Sjdp	 bfd_get_filename (abfd),
163060484Sobrien	 cache_ptr->name != NULL ? cache_ptr->name : _("*unknown*"));
163133965Sjdp      bfd_set_error (bfd_error_nonrepresentable_section);
163233965Sjdp      return false;
163333965Sjdp    }
163433965Sjdp
163533965Sjdp  if (sec->output_section != NULL)
163633965Sjdp    {
163733965Sjdp      off = sec->output_offset;
163833965Sjdp      sec = sec->output_section;
163933965Sjdp    }
164033965Sjdp
164133965Sjdp  if (bfd_is_abs_section (sec))
164233965Sjdp    sym_pointer->e_type[0] |= N_ABS;
164333965Sjdp  else if (sec == obj_textsec (abfd))
164433965Sjdp    sym_pointer->e_type[0] |= N_TEXT;
164533965Sjdp  else if (sec == obj_datasec (abfd))
164633965Sjdp    sym_pointer->e_type[0] |= N_DATA;
164733965Sjdp  else if (sec == obj_bsssec (abfd))
164833965Sjdp    sym_pointer->e_type[0] |= N_BSS;
164933965Sjdp  else if (bfd_is_und_section (sec))
165033965Sjdp    sym_pointer->e_type[0] = N_UNDF | N_EXT;
165133965Sjdp  else if (bfd_is_ind_section (sec))
165233965Sjdp    sym_pointer->e_type[0] = N_INDR;
165333965Sjdp  else if (bfd_is_com_section (sec))
165433965Sjdp    sym_pointer->e_type[0] = N_UNDF | N_EXT;
165533965Sjdp  else
165633965Sjdp    {
165733965Sjdp      (*_bfd_error_handler)
165860484Sobrien	(_("%s: can not represent section `%s' in a.out object file format"),
165933965Sjdp	 bfd_get_filename (abfd), bfd_get_section_name (abfd, sec));
166033965Sjdp      bfd_set_error (bfd_error_nonrepresentable_section);
166133965Sjdp      return false;
166233965Sjdp    }
166333965Sjdp
166433965Sjdp  /* Turn the symbol from section relative to absolute again */
166533965Sjdp  value += sec->vma + off;
166633965Sjdp
166733965Sjdp  if ((cache_ptr->flags & BSF_WARNING) != 0)
166833965Sjdp    sym_pointer->e_type[0] = N_WARNING;
166933965Sjdp
167033965Sjdp  if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
167133965Sjdp    sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
167233965Sjdp  else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
167333965Sjdp    sym_pointer->e_type[0] |= N_EXT;
167433965Sjdp
167533965Sjdp  if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
167633965Sjdp    {
167733965Sjdp      int type = ((aout_symbol_type *) cache_ptr)->type;
167833965Sjdp      switch (type)
167933965Sjdp	{
168033965Sjdp	case N_ABS:	type = N_SETA; break;
168133965Sjdp	case N_TEXT:	type = N_SETT; break;
168233965Sjdp	case N_DATA:	type = N_SETD; break;
168333965Sjdp	case N_BSS:	type = N_SETB; break;
168433965Sjdp	}
168533965Sjdp      sym_pointer->e_type[0] = type;
168633965Sjdp    }
168733965Sjdp
168833965Sjdp  if ((cache_ptr->flags & BSF_WEAK) != 0)
168933965Sjdp    {
169033965Sjdp      int type;
169133965Sjdp
169233965Sjdp      switch (sym_pointer->e_type[0] & N_TYPE)
169333965Sjdp	{
169433965Sjdp	default:
169533965Sjdp	case N_ABS:	type = N_WEAKA; break;
169633965Sjdp	case N_TEXT:	type = N_WEAKT; break;
169733965Sjdp	case N_DATA:	type = N_WEAKD; break;
169833965Sjdp	case N_BSS:	type = N_WEAKB; break;
169933965Sjdp	case N_UNDF:	type = N_WEAKU; break;
170033965Sjdp	}
170133965Sjdp      sym_pointer->e_type[0] = type;
170233965Sjdp    }
170333965Sjdp
170433965Sjdp  PUT_WORD(abfd, value, sym_pointer->e_value);
170533965Sjdp
170633965Sjdp  return true;
170733965Sjdp}
170833965Sjdp
170933965Sjdp/* Native-level interface to symbols. */
171033965Sjdp
171133965Sjdpasymbol *
171233965SjdpNAME(aout,make_empty_symbol) (abfd)
171333965Sjdp     bfd *abfd;
171433965Sjdp{
171533965Sjdp  aout_symbol_type  *new =
171633965Sjdp    (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
171733965Sjdp  if (!new)
171833965Sjdp    return NULL;
171933965Sjdp  new->symbol.the_bfd = abfd;
172033965Sjdp
172133965Sjdp  return &new->symbol;
172233965Sjdp}
172333965Sjdp
172433965Sjdp/* Translate a set of internal symbols into external symbols.  */
172533965Sjdp
172633965Sjdpboolean
172733965SjdpNAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic)
172833965Sjdp     bfd *abfd;
172933965Sjdp     aout_symbol_type *in;
173033965Sjdp     struct external_nlist *ext;
173133965Sjdp     bfd_size_type count;
173233965Sjdp     char *str;
173333965Sjdp     bfd_size_type strsize;
173433965Sjdp     boolean dynamic;
173533965Sjdp{
173633965Sjdp  struct external_nlist *ext_end;
173733965Sjdp
173833965Sjdp  ext_end = ext + count;
173933965Sjdp  for (; ext < ext_end; ext++, in++)
174033965Sjdp    {
174133965Sjdp      bfd_vma x;
174233965Sjdp
174333965Sjdp      x = GET_WORD (abfd, ext->e_strx);
174433965Sjdp      in->symbol.the_bfd = abfd;
174533965Sjdp
174633965Sjdp      /* For the normal symbols, the zero index points at the number
174733965Sjdp	 of bytes in the string table but is to be interpreted as the
174833965Sjdp	 null string.  For the dynamic symbols, the number of bytes in
174933965Sjdp	 the string table is stored in the __DYNAMIC structure and the
175033965Sjdp	 zero index points at an actual string.  */
175133965Sjdp      if (x == 0 && ! dynamic)
175233965Sjdp	in->symbol.name = "";
175333965Sjdp      else if (x < strsize)
175433965Sjdp	in->symbol.name = str + x;
175533965Sjdp      else
175633965Sjdp	return false;
175733965Sjdp
175833965Sjdp      in->symbol.value = GET_SWORD (abfd,  ext->e_value);
175933965Sjdp      in->desc = bfd_h_get_16 (abfd, ext->e_desc);
176033965Sjdp      in->other = bfd_h_get_8 (abfd, ext->e_other);
176133965Sjdp      in->type = bfd_h_get_8 (abfd,  ext->e_type);
176233965Sjdp      in->symbol.udata.p = NULL;
176333965Sjdp
176433965Sjdp      if (! translate_from_native_sym_flags (abfd, in))
176533965Sjdp	return false;
176633965Sjdp
176733965Sjdp      if (dynamic)
176833965Sjdp	in->symbol.flags |= BSF_DYNAMIC;
176933965Sjdp    }
177033965Sjdp
177133965Sjdp  return true;
177233965Sjdp}
177333965Sjdp
177433965Sjdp/* We read the symbols into a buffer, which is discarded when this
177533965Sjdp   function exits.  We read the strings into a buffer large enough to
177633965Sjdp   hold them all plus all the cached symbol entries. */
177733965Sjdp
177833965Sjdpboolean
177933965SjdpNAME(aout,slurp_symbol_table) (abfd)
178033965Sjdp     bfd *abfd;
178133965Sjdp{
178233965Sjdp  struct external_nlist *old_external_syms;
178333965Sjdp  aout_symbol_type *cached;
178433965Sjdp  size_t cached_size;
178533965Sjdp
178633965Sjdp  /* If there's no work to be done, don't do any */
178733965Sjdp  if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
178833965Sjdp    return true;
178933965Sjdp
179033965Sjdp  old_external_syms = obj_aout_external_syms (abfd);
179133965Sjdp
179233965Sjdp  if (! aout_get_external_symbols (abfd))
179333965Sjdp    return false;
179433965Sjdp
179533965Sjdp  cached_size = (obj_aout_external_sym_count (abfd)
179633965Sjdp		 * sizeof (aout_symbol_type));
179733965Sjdp  cached = (aout_symbol_type *) bfd_malloc (cached_size);
179833965Sjdp  if (cached == NULL && cached_size != 0)
179933965Sjdp    return false;
180033965Sjdp  if (cached_size != 0)
180133965Sjdp    memset (cached, 0, cached_size);
180233965Sjdp
180333965Sjdp  /* Convert from external symbol information to internal.  */
180433965Sjdp  if (! (NAME(aout,translate_symbol_table)
180533965Sjdp	 (abfd, cached,
180633965Sjdp	  obj_aout_external_syms (abfd),
180733965Sjdp	  obj_aout_external_sym_count (abfd),
180833965Sjdp	  obj_aout_external_strings (abfd),
180933965Sjdp	  obj_aout_external_string_size (abfd),
181033965Sjdp	  false)))
181133965Sjdp    {
181233965Sjdp      free (cached);
181333965Sjdp      return false;
181433965Sjdp    }
181533965Sjdp
181633965Sjdp  bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
181733965Sjdp
181833965Sjdp  obj_aout_symbols (abfd) = cached;
181933965Sjdp
182033965Sjdp  /* It is very likely that anybody who calls this function will not
182133965Sjdp     want the external symbol information, so if it was allocated
182233965Sjdp     because of our call to aout_get_external_symbols, we free it up
182333965Sjdp     right away to save space.  */
182433965Sjdp  if (old_external_syms == (struct external_nlist *) NULL
182533965Sjdp      && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
182633965Sjdp    {
182733965Sjdp#ifdef USE_MMAP
182833965Sjdp      bfd_free_window (&obj_aout_sym_window (abfd));
182933965Sjdp#else
183033965Sjdp      free (obj_aout_external_syms (abfd));
183133965Sjdp#endif
183233965Sjdp      obj_aout_external_syms (abfd) = NULL;
183333965Sjdp    }
183433965Sjdp
183533965Sjdp  return true;
183633965Sjdp}
183733965Sjdp
183833965Sjdp/* We use a hash table when writing out symbols so that we only write
183933965Sjdp   out a particular string once.  This helps particularly when the
184033965Sjdp   linker writes out stabs debugging entries, because each different
184133965Sjdp   contributing object file tends to have many duplicate stabs
184233965Sjdp   strings.
184333965Sjdp
184433965Sjdp   This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
184533965Sjdp   if BFD_TRADITIONAL_FORMAT is set.  */
184633965Sjdp
184733965Sjdpstatic bfd_size_type add_to_stringtab
184833965Sjdp  PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, boolean));
184933965Sjdpstatic boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *));
185033965Sjdp
185133965Sjdp/* Get the index of a string in a strtab, adding it if it is not
185233965Sjdp   already present.  */
185333965Sjdp
185433965Sjdpstatic INLINE bfd_size_type
185533965Sjdpadd_to_stringtab (abfd, tab, str, copy)
185633965Sjdp     bfd *abfd;
185733965Sjdp     struct bfd_strtab_hash *tab;
185833965Sjdp     const char *str;
185933965Sjdp     boolean copy;
186033965Sjdp{
186133965Sjdp  boolean hash;
186233965Sjdp  bfd_size_type index;
186333965Sjdp
186433965Sjdp  /* An index of 0 always means the empty string.  */
186533965Sjdp  if (str == 0 || *str == '\0')
186633965Sjdp    return 0;
186733965Sjdp
186833965Sjdp  /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx
186933965Sjdp     doesn't understand a hashed string table.  */
187033965Sjdp  hash = true;
187133965Sjdp  if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
187233965Sjdp    hash = false;
187333965Sjdp
187433965Sjdp  index = _bfd_stringtab_add (tab, str, hash, copy);
187533965Sjdp
187633965Sjdp  if (index != (bfd_size_type) -1)
187733965Sjdp    {
187833965Sjdp      /* Add BYTES_IN_WORD to the return value to account for the
187933965Sjdp	 space taken up by the string table size.  */
188033965Sjdp      index += BYTES_IN_WORD;
188133965Sjdp    }
188233965Sjdp
188333965Sjdp  return index;
188433965Sjdp}
188533965Sjdp
188633965Sjdp/* Write out a strtab.  ABFD is already at the right location in the
188733965Sjdp   file.  */
188833965Sjdp
188933965Sjdpstatic boolean
189033965Sjdpemit_stringtab (abfd, tab)
189133965Sjdp     register bfd *abfd;
189233965Sjdp     struct bfd_strtab_hash *tab;
189333965Sjdp{
189433965Sjdp  bfd_byte buffer[BYTES_IN_WORD];
189533965Sjdp
189633965Sjdp  /* The string table starts with the size.  */
189733965Sjdp  PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer);
189833965Sjdp  if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD)
189933965Sjdp    return false;
190033965Sjdp
190133965Sjdp  return _bfd_stringtab_emit (abfd, tab);
190233965Sjdp}
190333965Sjdp
190433965Sjdpboolean
190533965SjdpNAME(aout,write_syms) (abfd)
190633965Sjdp     bfd *abfd;
190733965Sjdp{
190833965Sjdp  unsigned int count ;
190933965Sjdp  asymbol **generic = bfd_get_outsymbols (abfd);
191033965Sjdp  struct bfd_strtab_hash *strtab;
191133965Sjdp
191233965Sjdp  strtab = _bfd_stringtab_init ();
191333965Sjdp  if (strtab == NULL)
191433965Sjdp    return false;
191533965Sjdp
191633965Sjdp  for (count = 0; count < bfd_get_symcount (abfd); count++)
191733965Sjdp    {
191833965Sjdp      asymbol *g = generic[count];
191933965Sjdp      bfd_size_type indx;
192033965Sjdp      struct external_nlist nsp;
192133965Sjdp
192233965Sjdp      indx = add_to_stringtab (abfd, strtab, g->name, false);
192333965Sjdp      if (indx == (bfd_size_type) -1)
192433965Sjdp	goto error_return;
192533965Sjdp      PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx);
192633965Sjdp
192733965Sjdp      if (bfd_asymbol_flavour(g) == abfd->xvec->flavour)
192833965Sjdp	{
192933965Sjdp	  bfd_h_put_16(abfd, aout_symbol(g)->desc,  nsp.e_desc);
193033965Sjdp	  bfd_h_put_8(abfd, aout_symbol(g)->other,  nsp.e_other);
193133965Sjdp	  bfd_h_put_8(abfd, aout_symbol(g)->type,  nsp.e_type);
193233965Sjdp	}
193333965Sjdp      else
193433965Sjdp	{
193533965Sjdp	  bfd_h_put_16(abfd,0, nsp.e_desc);
193633965Sjdp	  bfd_h_put_8(abfd, 0, nsp.e_other);
193733965Sjdp	  bfd_h_put_8(abfd, 0, nsp.e_type);
193833965Sjdp	}
193933965Sjdp
194033965Sjdp      if (! translate_to_native_sym_flags (abfd, g, &nsp))
194133965Sjdp	goto error_return;
194233965Sjdp
194333965Sjdp      if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd)
194433965Sjdp	  != EXTERNAL_NLIST_SIZE)
194533965Sjdp	goto error_return;
194633965Sjdp
194733965Sjdp      /* NB: `KEEPIT' currently overlays `udata.p', so set this only
194833965Sjdp	 here, at the end.  */
194933965Sjdp      g->KEEPIT = count;
195033965Sjdp    }
195133965Sjdp
195233965Sjdp  if (! emit_stringtab (abfd, strtab))
195333965Sjdp    goto error_return;
195433965Sjdp
195533965Sjdp  _bfd_stringtab_free (strtab);
195633965Sjdp
195733965Sjdp  return true;
195833965Sjdp
195933965Sjdperror_return:
196033965Sjdp  _bfd_stringtab_free (strtab);
196133965Sjdp  return false;
196233965Sjdp}
196333965Sjdp
196433965Sjdp
196533965Sjdplong
196633965SjdpNAME(aout,get_symtab) (abfd, location)
196733965Sjdp     bfd *abfd;
196833965Sjdp     asymbol **location;
196933965Sjdp{
197033965Sjdp    unsigned int counter = 0;
197133965Sjdp    aout_symbol_type *symbase;
197233965Sjdp
197333965Sjdp    if (!NAME(aout,slurp_symbol_table)(abfd))
197433965Sjdp      return -1;
197533965Sjdp
197633965Sjdp    for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
197733965Sjdp      *(location++) = (asymbol *)( symbase++);
197833965Sjdp    *location++ =0;
197933965Sjdp    return bfd_get_symcount (abfd);
198033965Sjdp}
198133965Sjdp
198233965Sjdp
198333965Sjdp/* Standard reloc stuff */
198433965Sjdp/* Output standard relocation information to a file in target byte order. */
198533965Sjdp
198633965Sjdpextern void  NAME(aout,swap_std_reloc_out)
198733965Sjdp  PARAMS ((bfd *, arelent *, struct reloc_std_external *));
198833965Sjdp
198933965Sjdpvoid
199033965SjdpNAME(aout,swap_std_reloc_out) (abfd, g, natptr)
199133965Sjdp     bfd *abfd;
199233965Sjdp     arelent *g;
199333965Sjdp     struct reloc_std_external *natptr;
199433965Sjdp{
199533965Sjdp  int r_index;
199633965Sjdp  asymbol *sym = *(g->sym_ptr_ptr);
199733965Sjdp  int r_extern;
199833965Sjdp  unsigned int r_length;
199933965Sjdp  int r_pcrel;
200033965Sjdp  int r_baserel, r_jmptable, r_relative;
200133965Sjdp  asection *output_section = sym->section->output_section;
200233965Sjdp
200333965Sjdp  PUT_WORD(abfd, g->address, natptr->r_address);
200433965Sjdp
200533965Sjdp  r_length = g->howto->size ;	/* Size as a power of two */
200633965Sjdp  r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC? */
200733965Sjdp  /* XXX This relies on relocs coming from a.out files.  */
200833965Sjdp  r_baserel = (g->howto->type & 8) != 0;
200933965Sjdp  r_jmptable = (g->howto->type & 16) != 0;
201033965Sjdp  r_relative = (g->howto->type & 32) != 0;
201133965Sjdp
201233965Sjdp#if 0
201333965Sjdp  /* For a standard reloc, the addend is in the object file.  */
201433965Sjdp  r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
201533965Sjdp#endif
201633965Sjdp
201733965Sjdp  /* name was clobbered by aout_write_syms to be symbol index */
201833965Sjdp
201933965Sjdp  /* If this relocation is relative to a symbol then set the
202033965Sjdp     r_index to the symbols index, and the r_extern bit.
202133965Sjdp
202233965Sjdp     Absolute symbols can come in in two ways, either as an offset
202333965Sjdp     from the abs section, or as a symbol which has an abs value.
202433965Sjdp     check for that here
202533965Sjdp     */
202633965Sjdp
202733965Sjdp
202833965Sjdp  if (bfd_is_com_section (output_section)
202933965Sjdp      || bfd_is_abs_section (output_section)
203033965Sjdp      || bfd_is_und_section (output_section))
203133965Sjdp    {
203233965Sjdp      if (bfd_abs_section_ptr->symbol == sym)
203333965Sjdp      {
203433965Sjdp	/* Whoops, looked like an abs symbol, but is really an offset
203533965Sjdp	   from the abs section */
203633965Sjdp	r_index = N_ABS;
203733965Sjdp	r_extern = 0;
203833965Sjdp       }
203933965Sjdp      else
204033965Sjdp      {
204133965Sjdp	/* Fill in symbol */
204233965Sjdp	r_extern = 1;
204333965Sjdp	r_index = (*(g->sym_ptr_ptr))->KEEPIT;
204433965Sjdp
204533965Sjdp      }
204633965Sjdp    }
204733965Sjdp  else
204833965Sjdp    {
204933965Sjdp      /* Just an ordinary section */
205033965Sjdp      r_extern = 0;
205133965Sjdp      r_index  = output_section->target_index;
205233965Sjdp    }
205333965Sjdp
205433965Sjdp  /* now the fun stuff */
205533965Sjdp  if (bfd_header_big_endian (abfd)) {
205633965Sjdp      natptr->r_index[0] = r_index >> 16;
205733965Sjdp      natptr->r_index[1] = r_index >> 8;
205833965Sjdp      natptr->r_index[2] = r_index;
205933965Sjdp      natptr->r_type[0] =
206033965Sjdp       (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
206133965Sjdp	| (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
206233965Sjdp	 | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
206333965Sjdp	  | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
206433965Sjdp	   | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
206533965Sjdp	    | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG);
206633965Sjdp    } else {
206733965Sjdp	natptr->r_index[2] = r_index >> 16;
206833965Sjdp	natptr->r_index[1] = r_index >> 8;
206933965Sjdp	natptr->r_index[0] = r_index;
207033965Sjdp	natptr->r_type[0] =
207133965Sjdp	 (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
207233965Sjdp	  | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
207333965Sjdp	   | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
207433965Sjdp	    | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
207533965Sjdp	     | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
207633965Sjdp	      | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
207733965Sjdp      }
207833965Sjdp}
207933965Sjdp
208033965Sjdp
208133965Sjdp/* Extended stuff */
208233965Sjdp/* Output extended relocation information to a file in target byte order. */
208333965Sjdp
208433965Sjdpextern void NAME(aout,swap_ext_reloc_out)
208533965Sjdp  PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
208633965Sjdp
208733965Sjdpvoid
208833965SjdpNAME(aout,swap_ext_reloc_out) (abfd, g, natptr)
208933965Sjdp     bfd *abfd;
209033965Sjdp     arelent *g;
209133965Sjdp     register struct reloc_ext_external *natptr;
209233965Sjdp{
209333965Sjdp  int r_index;
209433965Sjdp  int r_extern;
209533965Sjdp  unsigned int r_type;
209633965Sjdp  unsigned int r_addend;
209733965Sjdp  asymbol *sym = *(g->sym_ptr_ptr);
209833965Sjdp  asection *output_section = sym->section->output_section;
209933965Sjdp
210033965Sjdp  PUT_WORD (abfd, g->address, natptr->r_address);
210133965Sjdp
210233965Sjdp  r_type = (unsigned int) g->howto->type;
210333965Sjdp
210433965Sjdp  r_addend = g->addend;
210533965Sjdp  if ((sym->flags & BSF_SECTION_SYM) != 0)
210633965Sjdp    r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma;
210733965Sjdp
210833965Sjdp  /* If this relocation is relative to a symbol then set the
210933965Sjdp     r_index to the symbols index, and the r_extern bit.
211033965Sjdp
211133965Sjdp     Absolute symbols can come in in two ways, either as an offset
211233965Sjdp     from the abs section, or as a symbol which has an abs value.
211333965Sjdp     check for that here.  */
211433965Sjdp
211533965Sjdp  if (bfd_is_abs_section (bfd_get_section (sym)))
211633965Sjdp    {
211733965Sjdp      r_extern = 0;
211833965Sjdp      r_index = N_ABS;
211933965Sjdp    }
212033965Sjdp  else if ((sym->flags & BSF_SECTION_SYM) == 0)
212133965Sjdp    {
212233965Sjdp      if (bfd_is_und_section (bfd_get_section (sym))
212333965Sjdp	  || (sym->flags & BSF_GLOBAL) != 0)
212433965Sjdp	r_extern = 1;
212533965Sjdp      else
212633965Sjdp	r_extern = 0;
212733965Sjdp      r_index = (*(g->sym_ptr_ptr))->KEEPIT;
212833965Sjdp    }
212933965Sjdp  else
213033965Sjdp    {
213133965Sjdp      /* Just an ordinary section */
213233965Sjdp      r_extern = 0;
213333965Sjdp      r_index = output_section->target_index;
213433965Sjdp    }
213533965Sjdp
213633965Sjdp  /* now the fun stuff */
213733965Sjdp  if (bfd_header_big_endian (abfd)) {
213833965Sjdp    natptr->r_index[0] = r_index >> 16;
213933965Sjdp    natptr->r_index[1] = r_index >> 8;
214033965Sjdp    natptr->r_index[2] = r_index;
214133965Sjdp    natptr->r_type[0] =
214233965Sjdp      ((r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
214333965Sjdp       | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG));
214433965Sjdp  } else {
214533965Sjdp    natptr->r_index[2] = r_index >> 16;
214633965Sjdp    natptr->r_index[1] = r_index >> 8;
214733965Sjdp    natptr->r_index[0] = r_index;
214833965Sjdp    natptr->r_type[0] =
214933965Sjdp     (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
215033965Sjdp      | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
215133965Sjdp  }
215233965Sjdp
215333965Sjdp  PUT_WORD (abfd, r_addend, natptr->r_addend);
215433965Sjdp}
215533965Sjdp
215633965Sjdp/* BFD deals internally with all things based from the section they're
215733965Sjdp   in. so, something in 10 bytes into a text section  with a base of
215833965Sjdp   50 would have a symbol (.text+10) and know .text vma was 50.
215933965Sjdp
216033965Sjdp   Aout keeps all it's symbols based from zero, so the symbol would
216133965Sjdp   contain 60. This macro subs the base of each section from the value
216233965Sjdp   to give the true offset from the section */
216333965Sjdp
216433965Sjdp
216533965Sjdp#define MOVE_ADDRESS(ad)       						\
216633965Sjdp  if (r_extern) {							\
216733965Sjdp   /* undefined symbol */						\
216833965Sjdp     cache_ptr->sym_ptr_ptr = symbols + r_index;			\
216933965Sjdp     cache_ptr->addend = ad;						\
217033965Sjdp     } else {								\
217133965Sjdp    /* defined, section relative. replace symbol with pointer to    	\
217233965Sjdp       symbol which points to section  */				\
217333965Sjdp    switch (r_index) {							\
217433965Sjdp    case N_TEXT:							\
217533965Sjdp    case N_TEXT | N_EXT:						\
217633965Sjdp      cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;	\
217733965Sjdp      cache_ptr->addend = ad  - su->textsec->vma;			\
217833965Sjdp      break;								\
217933965Sjdp    case N_DATA:							\
218033965Sjdp    case N_DATA | N_EXT:						\
218133965Sjdp      cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;	\
218233965Sjdp      cache_ptr->addend = ad - su->datasec->vma;			\
218333965Sjdp      break;								\
218433965Sjdp    case N_BSS:								\
218533965Sjdp    case N_BSS | N_EXT:							\
218633965Sjdp      cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;	\
218733965Sjdp      cache_ptr->addend = ad - su->bsssec->vma;				\
218833965Sjdp      break;								\
218933965Sjdp    default:								\
219033965Sjdp    case N_ABS:								\
219133965Sjdp    case N_ABS | N_EXT:							\
219233965Sjdp     cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
219333965Sjdp      cache_ptr->addend = ad;						\
219433965Sjdp      break;								\
219533965Sjdp    }									\
219633965Sjdp  }     								\
219733965Sjdp
219833965Sjdpvoid
219933965SjdpNAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
220033965Sjdp     bfd *abfd;
220133965Sjdp     struct reloc_ext_external *bytes;
220233965Sjdp     arelent *cache_ptr;
220333965Sjdp     asymbol **symbols;
220433965Sjdp     bfd_size_type symcount;
220533965Sjdp{
220633965Sjdp  unsigned int r_index;
220733965Sjdp  int r_extern;
220833965Sjdp  unsigned int r_type;
220933965Sjdp  struct aoutdata *su = &(abfd->tdata.aout_data->a);
221033965Sjdp
221133965Sjdp  cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
221233965Sjdp
221333965Sjdp  /* now the fun stuff */
221433965Sjdp  if (bfd_header_big_endian (abfd)) {
221533965Sjdp    r_index =  (bytes->r_index[0] << 16)
221633965Sjdp	     | (bytes->r_index[1] << 8)
221733965Sjdp	     |  bytes->r_index[2];
221833965Sjdp    r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
221933965Sjdp    r_type   =       (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
222033965Sjdp				      >> RELOC_EXT_BITS_TYPE_SH_BIG;
222133965Sjdp  } else {
222233965Sjdp    r_index =  (bytes->r_index[2] << 16)
222333965Sjdp	     | (bytes->r_index[1] << 8)
222433965Sjdp	     |  bytes->r_index[0];
222533965Sjdp    r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
222633965Sjdp    r_type   =       (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
222733965Sjdp				      >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
222833965Sjdp  }
222933965Sjdp
223033965Sjdp  cache_ptr->howto =  howto_table_ext + r_type;
223133965Sjdp
223233965Sjdp  /* Base relative relocs are always against the symbol table,
223333965Sjdp     regardless of the setting of r_extern.  r_extern just reflects
223433965Sjdp     whether the symbol the reloc is against is local or global.  */
223533965Sjdp  if (r_type == RELOC_BASE10
223633965Sjdp      || r_type == RELOC_BASE13
223733965Sjdp      || r_type == RELOC_BASE22)
223833965Sjdp    r_extern = 1;
223933965Sjdp
224033965Sjdp  if (r_extern && r_index > symcount)
224133965Sjdp    {
224233965Sjdp      /* We could arrange to return an error, but it might be useful
224333965Sjdp         to see the file even if it is bad.  */
224433965Sjdp      r_extern = 0;
224533965Sjdp      r_index = N_ABS;
224633965Sjdp    }
224733965Sjdp
224833965Sjdp  MOVE_ADDRESS(GET_SWORD(abfd, bytes->r_addend));
224933965Sjdp}
225033965Sjdp
225133965Sjdpvoid
225233965SjdpNAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
225333965Sjdp     bfd *abfd;
225433965Sjdp     struct reloc_std_external *bytes;
225533965Sjdp     arelent *cache_ptr;
225633965Sjdp     asymbol **symbols;
225733965Sjdp     bfd_size_type symcount;
225833965Sjdp{
225933965Sjdp  unsigned int r_index;
226033965Sjdp  int r_extern;
226133965Sjdp  unsigned int r_length;
226233965Sjdp  int r_pcrel;
226333965Sjdp  int r_baserel, r_jmptable, r_relative;
226433965Sjdp  struct aoutdata  *su = &(abfd->tdata.aout_data->a);
226533965Sjdp  unsigned int howto_idx;
226633965Sjdp
226733965Sjdp  cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
226833965Sjdp
226933965Sjdp  /* now the fun stuff */
227033965Sjdp  if (bfd_header_big_endian (abfd)) {
227133965Sjdp    r_index =  (bytes->r_index[0] << 16)
227233965Sjdp      | (bytes->r_index[1] << 8)
227333965Sjdp	|  bytes->r_index[2];
227433965Sjdp    r_extern  = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
227533965Sjdp    r_pcrel   = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
227633965Sjdp    r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
227733965Sjdp    r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
227833965Sjdp    r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
227933965Sjdp    r_length  =       (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
228033965Sjdp      			>> RELOC_STD_BITS_LENGTH_SH_BIG;
228133965Sjdp  } else {
228233965Sjdp    r_index =  (bytes->r_index[2] << 16)
228333965Sjdp      | (bytes->r_index[1] << 8)
228433965Sjdp	|  bytes->r_index[0];
228533965Sjdp    r_extern  = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
228633965Sjdp    r_pcrel   = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
228733965Sjdp    r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
228833965Sjdp    r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
228933965Sjdp    r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
229033965Sjdp    r_length  =       (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
229133965Sjdp      			>> RELOC_STD_BITS_LENGTH_SH_LITTLE;
229233965Sjdp  }
229333965Sjdp
229433965Sjdp  howto_idx = r_length + 4 * r_pcrel + 8 * r_baserel
229533965Sjdp	      + 16 * r_jmptable + 32 * r_relative;
229633965Sjdp  BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
229733965Sjdp  cache_ptr->howto =  howto_table_std + howto_idx;
229833965Sjdp  BFD_ASSERT (cache_ptr->howto->type != (unsigned int) -1);
229933965Sjdp
230033965Sjdp  /* Base relative relocs are always against the symbol table,
230133965Sjdp     regardless of the setting of r_extern.  r_extern just reflects
230233965Sjdp     whether the symbol the reloc is against is local or global.  */
230333965Sjdp  if (r_baserel)
230433965Sjdp    r_extern = 1;
230533965Sjdp
230633965Sjdp  if (r_extern && r_index > symcount)
230733965Sjdp    {
230833965Sjdp      /* We could arrange to return an error, but it might be useful
230933965Sjdp         to see the file even if it is bad.  */
231033965Sjdp      r_extern = 0;
231133965Sjdp      r_index = N_ABS;
231233965Sjdp    }
231333965Sjdp
231433965Sjdp  MOVE_ADDRESS(0);
231533965Sjdp}
231633965Sjdp
231733965Sjdp/* Read and swap the relocs for a section.  */
231833965Sjdp
231933965Sjdpboolean
232033965SjdpNAME(aout,slurp_reloc_table) (abfd, asect, symbols)
232133965Sjdp     bfd *abfd;
232233965Sjdp     sec_ptr asect;
232333965Sjdp     asymbol **symbols;
232433965Sjdp{
232533965Sjdp  unsigned int count;
232633965Sjdp  bfd_size_type reloc_size;
232733965Sjdp  PTR relocs;
232833965Sjdp  arelent *reloc_cache;
232933965Sjdp  size_t each_size;
233033965Sjdp  unsigned int counter = 0;
233133965Sjdp  arelent *cache_ptr;
233233965Sjdp
233333965Sjdp  if (asect->relocation)
233433965Sjdp    return true;
233533965Sjdp
233633965Sjdp  if (asect->flags & SEC_CONSTRUCTOR)
233733965Sjdp    return true;
233833965Sjdp
233933965Sjdp  if (asect == obj_datasec (abfd))
234033965Sjdp    reloc_size = exec_hdr(abfd)->a_drsize;
234133965Sjdp  else if (asect == obj_textsec (abfd))
234233965Sjdp    reloc_size = exec_hdr(abfd)->a_trsize;
234333965Sjdp  else if (asect == obj_bsssec (abfd))
234433965Sjdp    reloc_size = 0;
234533965Sjdp  else
234633965Sjdp    {
234733965Sjdp      bfd_set_error (bfd_error_invalid_operation);
234833965Sjdp      return false;
234933965Sjdp    }
235033965Sjdp
235133965Sjdp  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
235233965Sjdp    return false;
235333965Sjdp
235433965Sjdp  each_size = obj_reloc_entry_size (abfd);
235533965Sjdp
235633965Sjdp  count = reloc_size / each_size;
235733965Sjdp
235833965Sjdp  reloc_cache = (arelent *) bfd_malloc ((size_t) (count * sizeof (arelent)));
235933965Sjdp  if (reloc_cache == NULL && count != 0)
236033965Sjdp    return false;
236133965Sjdp  memset (reloc_cache, 0, count * sizeof (arelent));
236233965Sjdp
236333965Sjdp  relocs = bfd_malloc ((size_t) reloc_size);
236433965Sjdp  if (relocs == NULL && reloc_size != 0)
236533965Sjdp    {
236633965Sjdp      free (reloc_cache);
236733965Sjdp      return false;
236833965Sjdp    }
236933965Sjdp
237033965Sjdp  if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
237133965Sjdp    {
237233965Sjdp      free (relocs);
237333965Sjdp      free (reloc_cache);
237433965Sjdp      return false;
237533965Sjdp    }
237633965Sjdp
237733965Sjdp  cache_ptr = reloc_cache;
237833965Sjdp  if (each_size == RELOC_EXT_SIZE)
237933965Sjdp    {
238033965Sjdp      register struct reloc_ext_external *rptr =
238133965Sjdp	(struct reloc_ext_external *) relocs;
238233965Sjdp
238333965Sjdp      for (; counter < count; counter++, rptr++, cache_ptr++)
238433965Sjdp	NAME(aout,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
238533965Sjdp				      bfd_get_symcount (abfd));
238633965Sjdp    }
238733965Sjdp  else
238833965Sjdp    {
238933965Sjdp      register struct reloc_std_external *rptr =
239033965Sjdp	(struct reloc_std_external *) relocs;
239133965Sjdp
239233965Sjdp      for (; counter < count; counter++, rptr++, cache_ptr++)
239333965Sjdp	MY_swap_std_reloc_in (abfd, rptr, cache_ptr, symbols,
239433965Sjdp			      bfd_get_symcount (abfd));
239533965Sjdp    }
239633965Sjdp
239733965Sjdp  free (relocs);
239833965Sjdp
239933965Sjdp  asect->relocation = reloc_cache;
240033965Sjdp  asect->reloc_count = cache_ptr - reloc_cache;
240133965Sjdp
240233965Sjdp  return true;
240333965Sjdp}
240433965Sjdp
240533965Sjdp/* Write out a relocation section into an object file.  */
240633965Sjdp
240733965Sjdpboolean
240833965SjdpNAME(aout,squirt_out_relocs) (abfd, section)
240933965Sjdp     bfd *abfd;
241033965Sjdp     asection *section;
241133965Sjdp{
241233965Sjdp  arelent **generic;
241333965Sjdp  unsigned char *native, *natptr;
241433965Sjdp  size_t each_size;
241533965Sjdp
241633965Sjdp  unsigned int count = section->reloc_count;
241733965Sjdp  size_t natsize;
241833965Sjdp
241933965Sjdp  if (count == 0 || section->orelocation == NULL)
242033965Sjdp    return true;
242133965Sjdp
242233965Sjdp  each_size = obj_reloc_entry_size (abfd);
242333965Sjdp  natsize = each_size * count;
242433965Sjdp  native = (unsigned char *) bfd_zalloc (abfd, natsize);
242533965Sjdp  if (!native)
242633965Sjdp    return false;
242733965Sjdp
242833965Sjdp  generic = section->orelocation;
242933965Sjdp
243033965Sjdp  if (each_size == RELOC_EXT_SIZE)
243133965Sjdp    {
243233965Sjdp      for (natptr = native;
243333965Sjdp	   count != 0;
243433965Sjdp	   --count, natptr += each_size, ++generic)
243533965Sjdp	NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
243633965Sjdp    }
243733965Sjdp  else
243833965Sjdp    {
243933965Sjdp      for (natptr = native;
244033965Sjdp	   count != 0;
244133965Sjdp	   --count, natptr += each_size, ++generic)
244233965Sjdp	MY_swap_std_reloc_out(abfd, *generic, (struct reloc_std_external *)natptr);
244333965Sjdp    }
244433965Sjdp
244533965Sjdp  if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
244633965Sjdp    bfd_release(abfd, native);
244733965Sjdp    return false;
244833965Sjdp  }
244933965Sjdp  bfd_release (abfd, native);
245033965Sjdp
245133965Sjdp  return true;
245233965Sjdp}
245333965Sjdp
245433965Sjdp/* This is stupid.  This function should be a boolean predicate */
245533965Sjdplong
245633965SjdpNAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
245733965Sjdp     bfd *abfd;
245833965Sjdp     sec_ptr section;
245933965Sjdp     arelent **relptr;
246033965Sjdp     asymbol **symbols;
246133965Sjdp{
246233965Sjdp  arelent *tblptr = section->relocation;
246333965Sjdp  unsigned int count;
246433965Sjdp
246533965Sjdp  if (section == obj_bsssec (abfd))
246633965Sjdp    {
246733965Sjdp      *relptr = NULL;
246833965Sjdp      return 0;
246933965Sjdp    }
247033965Sjdp
247133965Sjdp  if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
247233965Sjdp    return -1;
247333965Sjdp
247433965Sjdp  if (section->flags & SEC_CONSTRUCTOR) {
247533965Sjdp    arelent_chain *chain = section->constructor_chain;
247633965Sjdp    for (count = 0; count < section->reloc_count; count ++) {
247733965Sjdp      *relptr ++ = &chain->relent;
247833965Sjdp      chain = chain->next;
247933965Sjdp    }
248033965Sjdp  }
248133965Sjdp  else {
248233965Sjdp    tblptr = section->relocation;
248333965Sjdp
248433965Sjdp    for (count = 0; count++ < section->reloc_count;)
248533965Sjdp      {
248633965Sjdp	*relptr++ = tblptr++;
248733965Sjdp      }
248833965Sjdp  }
248933965Sjdp  *relptr = 0;
249033965Sjdp
249133965Sjdp  return section->reloc_count;
249233965Sjdp}
249333965Sjdp
249433965Sjdplong
249533965SjdpNAME(aout,get_reloc_upper_bound) (abfd, asect)
249633965Sjdp     bfd *abfd;
249733965Sjdp     sec_ptr asect;
249833965Sjdp{
249933965Sjdp  if (bfd_get_format (abfd) != bfd_object) {
250033965Sjdp    bfd_set_error (bfd_error_invalid_operation);
250133965Sjdp    return -1;
250233965Sjdp  }
250333965Sjdp  if (asect->flags & SEC_CONSTRUCTOR) {
250433965Sjdp    return (sizeof (arelent *) * (asect->reloc_count+1));
250533965Sjdp  }
250633965Sjdp
250733965Sjdp  if (asect == obj_datasec (abfd))
250833965Sjdp    return (sizeof (arelent *)
250933965Sjdp	    * ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
251033965Sjdp	       + 1));
251133965Sjdp
251233965Sjdp  if (asect == obj_textsec (abfd))
251333965Sjdp    return (sizeof (arelent *)
251433965Sjdp	    * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
251533965Sjdp	       + 1));
251633965Sjdp
251733965Sjdp  if (asect == obj_bsssec (abfd))
251833965Sjdp    return sizeof (arelent *);
251933965Sjdp
252033965Sjdp  if (asect == obj_bsssec (abfd))
252133965Sjdp    return 0;
252233965Sjdp
252333965Sjdp  bfd_set_error (bfd_error_invalid_operation);
252433965Sjdp  return -1;
252533965Sjdp}
252633965Sjdp
252733965Sjdp
252833965Sjdplong
252933965SjdpNAME(aout,get_symtab_upper_bound) (abfd)
253033965Sjdp     bfd *abfd;
253133965Sjdp{
253233965Sjdp  if (!NAME(aout,slurp_symbol_table)(abfd))
253333965Sjdp    return -1;
253433965Sjdp
253533965Sjdp  return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
253633965Sjdp}
253733965Sjdp
253833965Sjdp/*ARGSUSED*/
253933965Sjdp alent *
254033965SjdpNAME(aout,get_lineno) (ignore_abfd, ignore_symbol)
254160484Sobrien     bfd *ignore_abfd ATTRIBUTE_UNUSED;
254260484Sobrien     asymbol *ignore_symbol ATTRIBUTE_UNUSED;
254333965Sjdp{
254460484Sobrien  return (alent *)NULL;
254533965Sjdp}
254633965Sjdp
254733965Sjdp/*ARGSUSED*/
254833965Sjdpvoid
254933965SjdpNAME(aout,get_symbol_info) (ignore_abfd, symbol, ret)
255060484Sobrien     bfd *ignore_abfd ATTRIBUTE_UNUSED;
255133965Sjdp     asymbol *symbol;
255233965Sjdp     symbol_info *ret;
255333965Sjdp{
255433965Sjdp  bfd_symbol_info (symbol, ret);
255533965Sjdp
255633965Sjdp  if (ret->type == '?')
255733965Sjdp    {
255833965Sjdp      int type_code = aout_symbol(symbol)->type & 0xff;
255933965Sjdp      const char *stab_name = bfd_get_stab_name (type_code);
256033965Sjdp      static char buf[10];
256133965Sjdp
256233965Sjdp      if (stab_name == NULL)
256333965Sjdp	{
256433965Sjdp	  sprintf(buf, "(%d)", type_code);
256533965Sjdp	  stab_name = buf;
256633965Sjdp	}
256733965Sjdp      ret->type = '-';
256833965Sjdp      ret->stab_type = type_code;
256933965Sjdp      ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff);
257033965Sjdp      ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff);
257133965Sjdp      ret->stab_name = stab_name;
257233965Sjdp    }
257333965Sjdp}
257433965Sjdp
257533965Sjdp/*ARGSUSED*/
257633965Sjdpvoid
257733965SjdpNAME(aout,print_symbol) (ignore_abfd, afile, symbol, how)
257860484Sobrien     bfd *ignore_abfd ATTRIBUTE_UNUSED;
257933965Sjdp     PTR afile;
258033965Sjdp     asymbol *symbol;
258133965Sjdp     bfd_print_symbol_type how;
258233965Sjdp{
258333965Sjdp  FILE *file = (FILE *)afile;
258433965Sjdp
258533965Sjdp  switch (how) {
258633965Sjdp  case bfd_print_symbol_name:
258733965Sjdp    if (symbol->name)
258833965Sjdp      fprintf(file,"%s", symbol->name);
258933965Sjdp    break;
259033965Sjdp  case bfd_print_symbol_more:
259133965Sjdp    fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
259233965Sjdp	    (unsigned)(aout_symbol(symbol)->other & 0xff),
259333965Sjdp	    (unsigned)(aout_symbol(symbol)->type));
259433965Sjdp    break;
259533965Sjdp  case bfd_print_symbol_all:
259633965Sjdp    {
259733965Sjdp   CONST char *section_name = symbol->section->name;
259833965Sjdp
259933965Sjdp
260033965Sjdp      bfd_print_symbol_vandf((PTR)file,symbol);
260133965Sjdp
260233965Sjdp      fprintf(file," %-5s %04x %02x %02x",
260333965Sjdp	      section_name,
260433965Sjdp	      (unsigned)(aout_symbol(symbol)->desc & 0xffff),
260533965Sjdp	      (unsigned)(aout_symbol(symbol)->other & 0xff),
260633965Sjdp	      (unsigned)(aout_symbol(symbol)->type  & 0xff));
260733965Sjdp      if (symbol->name)
260833965Sjdp        fprintf(file," %s", symbol->name);
260933965Sjdp    }
261033965Sjdp    break;
261133965Sjdp  }
261233965Sjdp}
261333965Sjdp
261433965Sjdp/* If we don't have to allocate more than 1MB to hold the generic
261533965Sjdp   symbols, we use the generic minisymbol methord: it's faster, since
261633965Sjdp   it only translates the symbols once, not multiple times.  */
261733965Sjdp#define MINISYM_THRESHOLD (1000000 / sizeof (asymbol))
261833965Sjdp
261933965Sjdp/* Read minisymbols.  For minisymbols, we use the unmodified a.out
262033965Sjdp   symbols.  The minisymbol_to_symbol function translates these into
262133965Sjdp   BFD asymbol structures.  */
262233965Sjdp
262333965Sjdplong
262433965SjdpNAME(aout,read_minisymbols) (abfd, dynamic, minisymsp, sizep)
262533965Sjdp     bfd *abfd;
262633965Sjdp     boolean dynamic;
262733965Sjdp     PTR *minisymsp;
262833965Sjdp     unsigned int *sizep;
262933965Sjdp{
263033965Sjdp  if (dynamic)
263133965Sjdp    {
263233965Sjdp      /* We could handle the dynamic symbols here as well, but it's
263333965Sjdp         easier to hand them off.  */
263433965Sjdp      return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
263533965Sjdp    }
263633965Sjdp
263733965Sjdp  if (! aout_get_external_symbols (abfd))
263833965Sjdp    return -1;
263933965Sjdp
264033965Sjdp  if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
264133965Sjdp    return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
264233965Sjdp
264333965Sjdp  *minisymsp = (PTR) obj_aout_external_syms (abfd);
264433965Sjdp
264533965Sjdp  /* By passing the external symbols back from this routine, we are
264633965Sjdp     giving up control over the memory block.  Clear
264733965Sjdp     obj_aout_external_syms, so that we do not try to free it
264833965Sjdp     ourselves.  */
264933965Sjdp  obj_aout_external_syms (abfd) = NULL;
265033965Sjdp
265133965Sjdp  *sizep = EXTERNAL_NLIST_SIZE;
265233965Sjdp  return obj_aout_external_sym_count (abfd);
265333965Sjdp}
265433965Sjdp
265533965Sjdp/* Convert a minisymbol to a BFD asymbol.  A minisymbol is just an
265633965Sjdp   unmodified a.out symbol.  The SYM argument is a structure returned
265733965Sjdp   by bfd_make_empty_symbol, which we fill in here.  */
265833965Sjdp
265933965Sjdpasymbol *
266033965SjdpNAME(aout,minisymbol_to_symbol) (abfd, dynamic, minisym, sym)
266133965Sjdp     bfd *abfd;
266233965Sjdp     boolean dynamic;
266333965Sjdp     const PTR minisym;
266433965Sjdp     asymbol *sym;
266533965Sjdp{
266633965Sjdp  if (dynamic
266733965Sjdp      || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
266833965Sjdp    return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym);
266933965Sjdp
267033965Sjdp  memset (sym, 0, sizeof (aout_symbol_type));
267133965Sjdp
267233965Sjdp  /* We call translate_symbol_table to translate a single symbol.  */
267333965Sjdp  if (! (NAME(aout,translate_symbol_table)
267433965Sjdp	 (abfd,
267533965Sjdp	  (aout_symbol_type *) sym,
267633965Sjdp	  (struct external_nlist *) minisym,
267733965Sjdp	  (bfd_size_type) 1,
267833965Sjdp	  obj_aout_external_strings (abfd),
267933965Sjdp	  obj_aout_external_string_size (abfd),
268033965Sjdp	  false)))
268133965Sjdp    return NULL;
268233965Sjdp
268333965Sjdp  return sym;
268433965Sjdp}
268533965Sjdp
268633965Sjdp/*
268733965Sjdp provided a BFD, a section and an offset into the section, calculate
268833965Sjdp and return the name of the source file and the line nearest to the
268933965Sjdp wanted location.
269033965Sjdp*/
269133965Sjdp
269233965Sjdpboolean
269333965SjdpNAME(aout,find_nearest_line)
269433965Sjdp     (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr)
269533965Sjdp     bfd *abfd;
269633965Sjdp     asection *section;
269733965Sjdp     asymbol **symbols;
269833965Sjdp     bfd_vma offset;
269933965Sjdp     CONST char **filename_ptr;
270033965Sjdp     CONST char **functionname_ptr;
270133965Sjdp     unsigned int *line_ptr;
270233965Sjdp{
270333965Sjdp  /* Run down the file looking for the filename, function and linenumber */
270433965Sjdp  asymbol **p;
270533965Sjdp  CONST char *directory_name = NULL;
270633965Sjdp  CONST char *main_file_name = NULL;
270733965Sjdp  CONST char *current_file_name = NULL;
270833965Sjdp  CONST char *line_file_name = NULL; /* Value of current_file_name at line number. */
270960484Sobrien  CONST char *line_directory_name = NULL; /* Value of directory_name at line number. */
271033965Sjdp  bfd_vma low_line_vma = 0;
271133965Sjdp  bfd_vma low_func_vma = 0;
271233965Sjdp  asymbol *func = 0;
271333965Sjdp  size_t filelen, funclen;
271433965Sjdp  char *buf;
271533965Sjdp
271633965Sjdp  *filename_ptr = abfd->filename;
271733965Sjdp  *functionname_ptr = 0;
271833965Sjdp  *line_ptr = 0;
271933965Sjdp  if (symbols != (asymbol **)NULL) {
272033965Sjdp    for (p = symbols; *p; p++) {
272133965Sjdp      aout_symbol_type  *q = (aout_symbol_type *)(*p);
272233965Sjdp    next:
272333965Sjdp      switch (q->type){
272433965Sjdp      case N_TEXT:
272533965Sjdp	/* If this looks like a file name symbol, and it comes after
272633965Sjdp           the line number we have found so far, but before the
272733965Sjdp           offset, then we have probably not found the right line
272833965Sjdp           number.  */
272933965Sjdp	if (q->symbol.value <= offset
273033965Sjdp	    && ((q->symbol.value > low_line_vma
273133965Sjdp		 && (line_file_name != NULL
273233965Sjdp		     || *line_ptr != 0))
273333965Sjdp		|| (q->symbol.value > low_func_vma
273433965Sjdp		    && func != NULL)))
273533965Sjdp	  {
273633965Sjdp	    const char *symname;
273733965Sjdp
273833965Sjdp	    symname = q->symbol.name;
273933965Sjdp	    if (strcmp (symname + strlen (symname) - 2, ".o") == 0)
274033965Sjdp	      {
274133965Sjdp		if (q->symbol.value > low_line_vma)
274233965Sjdp		  {
274333965Sjdp		    *line_ptr = 0;
274433965Sjdp		    line_file_name = NULL;
274533965Sjdp		  }
274633965Sjdp		if (q->symbol.value > low_func_vma)
274733965Sjdp		  func = NULL;
274833965Sjdp	      }
274933965Sjdp	  }
275033965Sjdp	break;
275133965Sjdp
275233965Sjdp      case N_SO:
275333965Sjdp	/* If this symbol is less than the offset, but greater than
275433965Sjdp           the line number we have found so far, then we have not
275533965Sjdp           found the right line number.  */
275633965Sjdp	if (q->symbol.value <= offset)
275733965Sjdp	  {
275833965Sjdp	    if (q->symbol.value > low_line_vma)
275933965Sjdp	      {
276033965Sjdp		*line_ptr = 0;
276133965Sjdp		line_file_name = NULL;
276233965Sjdp	      }
276333965Sjdp	    if (q->symbol.value > low_func_vma)
276433965Sjdp	      func = NULL;
276533965Sjdp	  }
276633965Sjdp
276733965Sjdp	main_file_name = current_file_name = q->symbol.name;
276833965Sjdp	/* Look ahead to next symbol to check if that too is an N_SO. */
276933965Sjdp	p++;
277033965Sjdp	if (*p == NULL)
277133965Sjdp	  break;
277233965Sjdp	q = (aout_symbol_type *)(*p);
277333965Sjdp	if (q->type != (int)N_SO)
277433965Sjdp	  goto next;
277533965Sjdp
277633965Sjdp	/* Found a second N_SO  First is directory; second is filename. */
277733965Sjdp	directory_name = current_file_name;
277833965Sjdp	main_file_name = current_file_name = q->symbol.name;
277933965Sjdp	if (obj_textsec(abfd) != section)
278033965Sjdp	  goto done;
278133965Sjdp	break;
278233965Sjdp      case N_SOL:
278333965Sjdp	current_file_name = q->symbol.name;
278433965Sjdp	break;
278533965Sjdp
278633965Sjdp      case N_SLINE:
278733965Sjdp
278833965Sjdp      case N_DSLINE:
278933965Sjdp      case N_BSLINE:
279033965Sjdp	/* We'll keep this if it resolves nearer than the one we have
279133965Sjdp           already.  */
279233965Sjdp	if (q->symbol.value >= low_line_vma
279333965Sjdp	    && q->symbol.value <= offset)
279433965Sjdp	  {
279533965Sjdp	    *line_ptr = q->desc;
279633965Sjdp	    low_line_vma = q->symbol.value;
279733965Sjdp	    line_file_name = current_file_name;
279860484Sobrien	    line_directory_name = directory_name;
279933965Sjdp	  }
280033965Sjdp	break;
280133965Sjdp      case N_FUN:
280233965Sjdp	{
280333965Sjdp	  /* We'll keep this if it is nearer than the one we have already */
280433965Sjdp	  if (q->symbol.value >= low_func_vma &&
280533965Sjdp	      q->symbol.value <= offset) {
280633965Sjdp	    low_func_vma = q->symbol.value;
280733965Sjdp	    func = (asymbol *)q;
280833965Sjdp	  }
280933965Sjdp	  else if (q->symbol.value > offset)
281033965Sjdp	    goto done;
281133965Sjdp	}
281233965Sjdp	break;
281333965Sjdp      }
281433965Sjdp    }
281533965Sjdp  }
281633965Sjdp
281733965Sjdp done:
281833965Sjdp  if (*line_ptr != 0)
281960484Sobrien    {
282060484Sobrien      main_file_name = line_file_name;
282160484Sobrien      directory_name = line_directory_name;
282260484Sobrien    }
282333965Sjdp
282433965Sjdp  if (main_file_name == NULL
282561843Sobrien      || IS_ABSOLUTE_PATH (main_file_name)
282633965Sjdp      || directory_name == NULL)
282733965Sjdp    filelen = 0;
282833965Sjdp  else
282933965Sjdp    filelen = strlen (directory_name) + strlen (main_file_name);
283033965Sjdp  if (func == NULL)
283133965Sjdp    funclen = 0;
283233965Sjdp  else
283333965Sjdp    funclen = strlen (bfd_asymbol_name (func));
283433965Sjdp
283533965Sjdp  if (adata (abfd).line_buf != NULL)
283633965Sjdp    free (adata (abfd).line_buf);
283733965Sjdp  if (filelen + funclen == 0)
283833965Sjdp    adata (abfd).line_buf = buf = NULL;
283933965Sjdp  else
284033965Sjdp    {
284133965Sjdp      buf = (char *) bfd_malloc (filelen + funclen + 3);
284233965Sjdp      adata (abfd).line_buf = buf;
284333965Sjdp      if (buf == NULL)
284433965Sjdp	return false;
284533965Sjdp    }
284633965Sjdp
284733965Sjdp  if (main_file_name != NULL)
284833965Sjdp    {
284961843Sobrien      if (IS_ABSOLUTE_PATH (main_file_name) || directory_name == NULL)
285033965Sjdp	*filename_ptr = main_file_name;
285133965Sjdp      else
285233965Sjdp	{
285333965Sjdp	  sprintf (buf, "%s%s", directory_name, main_file_name);
285433965Sjdp	  *filename_ptr = buf;
285533965Sjdp	  buf += filelen + 1;
285633965Sjdp	}
285733965Sjdp    }
285833965Sjdp
285933965Sjdp  if (func)
286033965Sjdp    {
286133965Sjdp      const char *function = func->name;
286233965Sjdp      char *p;
286333965Sjdp
286433965Sjdp      /* The caller expects a symbol name.  We actually have a
286533965Sjdp	 function name, without the leading underscore.  Put the
286633965Sjdp	 underscore back in, so that the caller gets a symbol name.  */
286733965Sjdp      if (bfd_get_symbol_leading_char (abfd) == '\0')
286833965Sjdp	strcpy (buf, function);
286933965Sjdp      else
287033965Sjdp	{
287133965Sjdp	  buf[0] = bfd_get_symbol_leading_char (abfd);
287233965Sjdp	  strcpy (buf + 1, function);
287333965Sjdp	}
287433965Sjdp      /* Have to remove : stuff */
287533965Sjdp      p = strchr (buf, ':');
287633965Sjdp      if (p != NULL)
287733965Sjdp	*p = '\0';
287833965Sjdp      *functionname_ptr = buf;
287933965Sjdp    }
288033965Sjdp
288133965Sjdp  return true;
288233965Sjdp}
288333965Sjdp
288433965Sjdp/*ARGSUSED*/
288533965Sjdpint
288633965SjdpNAME(aout,sizeof_headers) (abfd, execable)
288733965Sjdp     bfd *abfd;
288860484Sobrien     boolean execable ATTRIBUTE_UNUSED;
288933965Sjdp{
289033965Sjdp  return adata(abfd).exec_bytes_size;
289133965Sjdp}
289233965Sjdp
289333965Sjdp/* Free all information we have cached for this BFD.  We can always
289433965Sjdp   read it again later if we need it.  */
289533965Sjdp
289633965Sjdpboolean
289733965SjdpNAME(aout,bfd_free_cached_info) (abfd)
289833965Sjdp     bfd *abfd;
289933965Sjdp{
290033965Sjdp  asection *o;
290133965Sjdp
290233965Sjdp  if (bfd_get_format (abfd) != bfd_object)
290333965Sjdp    return true;
290433965Sjdp
290533965Sjdp#define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; }
290633965Sjdp  BFCI_FREE (obj_aout_symbols (abfd));
290733965Sjdp#ifdef USE_MMAP
290833965Sjdp  obj_aout_external_syms (abfd) = 0;
290933965Sjdp  bfd_free_window (&obj_aout_sym_window (abfd));
291033965Sjdp  bfd_free_window (&obj_aout_string_window (abfd));
291133965Sjdp  obj_aout_external_strings (abfd) = 0;
291233965Sjdp#else
291333965Sjdp  BFCI_FREE (obj_aout_external_syms (abfd));
291433965Sjdp  BFCI_FREE (obj_aout_external_strings (abfd));
291533965Sjdp#endif
291633965Sjdp  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
291733965Sjdp    BFCI_FREE (o->relocation);
291833965Sjdp#undef BFCI_FREE
291933965Sjdp
292033965Sjdp  return true;
292133965Sjdp}
292233965Sjdp
292333965Sjdp/* a.out link code.  */
292433965Sjdp
292533965Sjdpstatic boolean aout_link_add_object_symbols
292633965Sjdp  PARAMS ((bfd *, struct bfd_link_info *));
292733965Sjdpstatic boolean aout_link_check_archive_element
292833965Sjdp  PARAMS ((bfd *, struct bfd_link_info *, boolean *));
292933965Sjdpstatic boolean aout_link_free_symbols PARAMS ((bfd *));
293033965Sjdpstatic boolean aout_link_check_ar_symbols
293133965Sjdp  PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded));
293233965Sjdpstatic boolean aout_link_add_symbols
293333965Sjdp  PARAMS ((bfd *, struct bfd_link_info *));
293433965Sjdp
293533965Sjdp/* Routine to create an entry in an a.out link hash table.  */
293633965Sjdp
293733965Sjdpstruct bfd_hash_entry *
293833965SjdpNAME(aout,link_hash_newfunc) (entry, table, string)
293933965Sjdp     struct bfd_hash_entry *entry;
294033965Sjdp     struct bfd_hash_table *table;
294133965Sjdp     const char *string;
294233965Sjdp{
294333965Sjdp  struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry;
294433965Sjdp
294533965Sjdp  /* Allocate the structure if it has not already been allocated by a
294633965Sjdp     subclass.  */
294733965Sjdp  if (ret == (struct aout_link_hash_entry *) NULL)
294833965Sjdp    ret = ((struct aout_link_hash_entry *)
294933965Sjdp	   bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry)));
295033965Sjdp  if (ret == (struct aout_link_hash_entry *) NULL)
295133965Sjdp    return (struct bfd_hash_entry *) ret;
295233965Sjdp
295333965Sjdp  /* Call the allocation method of the superclass.  */
295433965Sjdp  ret = ((struct aout_link_hash_entry *)
295533965Sjdp	 _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
295633965Sjdp				 table, string));
295733965Sjdp  if (ret)
295833965Sjdp    {
295933965Sjdp      /* Set local fields.  */
296033965Sjdp      ret->written = false;
296133965Sjdp      ret->indx = -1;
296233965Sjdp    }
296333965Sjdp
296433965Sjdp  return (struct bfd_hash_entry *) ret;
296533965Sjdp}
296633965Sjdp
296733965Sjdp/* Initialize an a.out link hash table.  */
296833965Sjdp
296933965Sjdpboolean
297033965SjdpNAME(aout,link_hash_table_init) (table, abfd, newfunc)
297133965Sjdp     struct aout_link_hash_table *table;
297233965Sjdp     bfd *abfd;
297333965Sjdp     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
297433965Sjdp						struct bfd_hash_table *,
297533965Sjdp						const char *));
297633965Sjdp{
297733965Sjdp  return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
297833965Sjdp}
297933965Sjdp
298033965Sjdp/* Create an a.out link hash table.  */
298133965Sjdp
298233965Sjdpstruct bfd_link_hash_table *
298333965SjdpNAME(aout,link_hash_table_create) (abfd)
298433965Sjdp     bfd *abfd;
298533965Sjdp{
298633965Sjdp  struct aout_link_hash_table *ret;
298733965Sjdp
298833965Sjdp  ret = ((struct aout_link_hash_table *)
298933965Sjdp	 bfd_alloc (abfd, sizeof (struct aout_link_hash_table)));
299033965Sjdp  if (ret == NULL)
299133965Sjdp    return (struct bfd_link_hash_table *) NULL;
299233965Sjdp  if (! NAME(aout,link_hash_table_init) (ret, abfd,
299333965Sjdp					 NAME(aout,link_hash_newfunc)))
299433965Sjdp    {
299533965Sjdp      free (ret);
299633965Sjdp      return (struct bfd_link_hash_table *) NULL;
299733965Sjdp    }
299833965Sjdp  return &ret->root;
299933965Sjdp}
300033965Sjdp
300133965Sjdp/* Given an a.out BFD, add symbols to the global hash table as
300233965Sjdp   appropriate.  */
300333965Sjdp
300433965Sjdpboolean
300533965SjdpNAME(aout,link_add_symbols) (abfd, info)
300633965Sjdp     bfd *abfd;
300733965Sjdp     struct bfd_link_info *info;
300833965Sjdp{
300933965Sjdp  switch (bfd_get_format (abfd))
301033965Sjdp    {
301133965Sjdp    case bfd_object:
301233965Sjdp      return aout_link_add_object_symbols (abfd, info);
301333965Sjdp    case bfd_archive:
301433965Sjdp      return _bfd_generic_link_add_archive_symbols
301533965Sjdp	(abfd, info, aout_link_check_archive_element);
301633965Sjdp    default:
301733965Sjdp      bfd_set_error (bfd_error_wrong_format);
301833965Sjdp      return false;
301933965Sjdp    }
302033965Sjdp}
302133965Sjdp
302233965Sjdp/* Add symbols from an a.out object file.  */
302333965Sjdp
302433965Sjdpstatic boolean
302533965Sjdpaout_link_add_object_symbols (abfd, info)
302633965Sjdp     bfd *abfd;
302733965Sjdp     struct bfd_link_info *info;
302833965Sjdp{
302933965Sjdp  if (! aout_get_external_symbols (abfd))
303033965Sjdp    return false;
303133965Sjdp  if (! aout_link_add_symbols (abfd, info))
303233965Sjdp    return false;
303333965Sjdp  if (! info->keep_memory)
303433965Sjdp    {
303533965Sjdp      if (! aout_link_free_symbols (abfd))
303633965Sjdp	return false;
303733965Sjdp    }
303833965Sjdp  return true;
303933965Sjdp}
304033965Sjdp
304133965Sjdp/* Check a single archive element to see if we need to include it in
304233965Sjdp   the link.  *PNEEDED is set according to whether this element is
304333965Sjdp   needed in the link or not.  This is called from
304433965Sjdp   _bfd_generic_link_add_archive_symbols.  */
304533965Sjdp
304633965Sjdpstatic boolean
304733965Sjdpaout_link_check_archive_element (abfd, info, pneeded)
304833965Sjdp     bfd *abfd;
304933965Sjdp     struct bfd_link_info *info;
305033965Sjdp     boolean *pneeded;
305133965Sjdp{
305233965Sjdp  if (! aout_get_external_symbols (abfd))
305333965Sjdp    return false;
305433965Sjdp
305533965Sjdp  if (! aout_link_check_ar_symbols (abfd, info, pneeded))
305633965Sjdp    return false;
305733965Sjdp
305833965Sjdp  if (*pneeded)
305933965Sjdp    {
306033965Sjdp      if (! aout_link_add_symbols (abfd, info))
306133965Sjdp	return false;
306233965Sjdp    }
306333965Sjdp
306433965Sjdp  if (! info->keep_memory || ! *pneeded)
306533965Sjdp    {
306633965Sjdp      if (! aout_link_free_symbols (abfd))
306733965Sjdp	return false;
306833965Sjdp    }
306933965Sjdp
307033965Sjdp  return true;
307133965Sjdp}
307233965Sjdp
307333965Sjdp/* Free up the internal symbols read from an a.out file.  */
307433965Sjdp
307533965Sjdpstatic boolean
307633965Sjdpaout_link_free_symbols (abfd)
307733965Sjdp     bfd *abfd;
307833965Sjdp{
307933965Sjdp  if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
308033965Sjdp    {
308133965Sjdp#ifdef USE_MMAP
308233965Sjdp      bfd_free_window (&obj_aout_sym_window (abfd));
308333965Sjdp#else
308433965Sjdp      free ((PTR) obj_aout_external_syms (abfd));
308533965Sjdp#endif
308633965Sjdp      obj_aout_external_syms (abfd) = (struct external_nlist *) NULL;
308733965Sjdp    }
308833965Sjdp  if (obj_aout_external_strings (abfd) != (char *) NULL)
308933965Sjdp    {
309033965Sjdp#ifdef USE_MMAP
309133965Sjdp      bfd_free_window (&obj_aout_string_window (abfd));
309233965Sjdp#else
309333965Sjdp      free ((PTR) obj_aout_external_strings (abfd));
309433965Sjdp#endif
309533965Sjdp      obj_aout_external_strings (abfd) = (char *) NULL;
309633965Sjdp    }
309733965Sjdp  return true;
309833965Sjdp}
309933965Sjdp
310033965Sjdp/* Look through the internal symbols to see if this object file should
310133965Sjdp   be included in the link.  We should include this object file if it
310233965Sjdp   defines any symbols which are currently undefined.  If this object
310333965Sjdp   file defines a common symbol, then we may adjust the size of the
310433965Sjdp   known symbol but we do not include the object file in the link
310533965Sjdp   (unless there is some other reason to include it).  */
310633965Sjdp
310733965Sjdpstatic boolean
310833965Sjdpaout_link_check_ar_symbols (abfd, info, pneeded)
310933965Sjdp     bfd *abfd;
311033965Sjdp     struct bfd_link_info *info;
311133965Sjdp     boolean *pneeded;
311233965Sjdp{
311333965Sjdp  register struct external_nlist *p;
311433965Sjdp  struct external_nlist *pend;
311533965Sjdp  char *strings;
311633965Sjdp
311733965Sjdp  *pneeded = false;
311833965Sjdp
311933965Sjdp  /* Look through all the symbols.  */
312033965Sjdp  p = obj_aout_external_syms (abfd);
312133965Sjdp  pend = p + obj_aout_external_sym_count (abfd);
312233965Sjdp  strings = obj_aout_external_strings (abfd);
312333965Sjdp  for (; p < pend; p++)
312433965Sjdp    {
312533965Sjdp      int type = bfd_h_get_8 (abfd, p->e_type);
312633965Sjdp      const char *name;
312733965Sjdp      struct bfd_link_hash_entry *h;
312833965Sjdp
312933965Sjdp      /* Ignore symbols that are not externally visible.  This is an
313033965Sjdp	 optimization only, as we check the type more thoroughly
313133965Sjdp	 below.  */
313233965Sjdp      if (((type & N_EXT) == 0
313333965Sjdp	   || (type & N_STAB) != 0
313433965Sjdp	   || type == N_FN)
313533965Sjdp	  && type != N_WEAKA
313633965Sjdp	  && type != N_WEAKT
313733965Sjdp	  && type != N_WEAKD
313833965Sjdp	  && type != N_WEAKB)
313933965Sjdp	{
314033965Sjdp	  if (type == N_WARNING
314133965Sjdp	      || type == N_INDR)
314233965Sjdp	    ++p;
314333965Sjdp	  continue;
314433965Sjdp	}
314533965Sjdp
314633965Sjdp      name = strings + GET_WORD (abfd, p->e_strx);
314733965Sjdp      h = bfd_link_hash_lookup (info->hash, name, false, false, true);
314833965Sjdp
314933965Sjdp      /* We are only interested in symbols that are currently
315033965Sjdp	 undefined or common.  */
315133965Sjdp      if (h == (struct bfd_link_hash_entry *) NULL
315233965Sjdp	  || (h->type != bfd_link_hash_undefined
315333965Sjdp	      && h->type != bfd_link_hash_common))
315433965Sjdp	{
315533965Sjdp	  if (type == (N_INDR | N_EXT))
315633965Sjdp	    ++p;
315733965Sjdp	  continue;
315833965Sjdp	}
315933965Sjdp
316033965Sjdp      if (type == (N_TEXT | N_EXT)
316133965Sjdp	  || type == (N_DATA | N_EXT)
316233965Sjdp	  || type == (N_BSS | N_EXT)
316333965Sjdp	  || type == (N_ABS | N_EXT)
316433965Sjdp	  || type == (N_INDR | N_EXT))
316533965Sjdp	{
316633965Sjdp	  /* This object file defines this symbol.  We must link it
316733965Sjdp	     in.  This is true regardless of whether the current
316833965Sjdp	     definition of the symbol is undefined or common.  If the
316933965Sjdp	     current definition is common, we have a case in which we
317033965Sjdp	     have already seen an object file including
317133965Sjdp	         int a;
317233965Sjdp	     and this object file from the archive includes
317333965Sjdp	         int a = 5;
317433965Sjdp	     In such a case we must include this object file.
317533965Sjdp
317633965Sjdp	     FIXME: The SunOS 4.1.3 linker will pull in the archive
317733965Sjdp	     element if the symbol is defined in the .data section,
317833965Sjdp	     but not if it is defined in the .text section.  That
317933965Sjdp	     seems a bit crazy to me, and I haven't implemented it.
318033965Sjdp	     However, it might be correct.  */
318133965Sjdp	  if (! (*info->callbacks->add_archive_element) (info, abfd, name))
318233965Sjdp	    return false;
318333965Sjdp	  *pneeded = true;
318433965Sjdp	  return true;
318533965Sjdp	}
318633965Sjdp
318733965Sjdp      if (type == (N_UNDF | N_EXT))
318833965Sjdp	{
318933965Sjdp	  bfd_vma value;
319033965Sjdp
319133965Sjdp	  value = GET_WORD (abfd, p->e_value);
319233965Sjdp	  if (value != 0)
319333965Sjdp	    {
319433965Sjdp	      /* This symbol is common in the object from the archive
319533965Sjdp		 file.  */
319633965Sjdp	      if (h->type == bfd_link_hash_undefined)
319733965Sjdp		{
319833965Sjdp		  bfd *symbfd;
319933965Sjdp		  unsigned int power;
320033965Sjdp
320133965Sjdp		  symbfd = h->u.undef.abfd;
320233965Sjdp		  if (symbfd == (bfd *) NULL)
320333965Sjdp		    {
320433965Sjdp		      /* This symbol was created as undefined from
320533965Sjdp			 outside BFD.  We assume that we should link
320633965Sjdp			 in the object file.  This is done for the -u
320733965Sjdp			 option in the linker.  */
320833965Sjdp		      if (! (*info->callbacks->add_archive_element) (info,
320933965Sjdp								     abfd,
321033965Sjdp								     name))
321133965Sjdp			return false;
321233965Sjdp		      *pneeded = true;
321333965Sjdp		      return true;
321433965Sjdp		    }
321533965Sjdp		  /* Turn the current link symbol into a common
321633965Sjdp		     symbol.  It is already on the undefs list.  */
321733965Sjdp		  h->type = bfd_link_hash_common;
321833965Sjdp		  h->u.c.p = ((struct bfd_link_hash_common_entry *)
321933965Sjdp			      bfd_hash_allocate (&info->hash->table,
322033965Sjdp				  sizeof (struct bfd_link_hash_common_entry)));
322133965Sjdp		  if (h->u.c.p == NULL)
322233965Sjdp		    return false;
322333965Sjdp
322433965Sjdp		  h->u.c.size = value;
322533965Sjdp
322633965Sjdp		  /* FIXME: This isn't quite right.  The maximum
322733965Sjdp		     alignment of a common symbol should be set by the
322833965Sjdp		     architecture of the output file, not of the input
322933965Sjdp		     file.  */
323033965Sjdp		  power = bfd_log2 (value);
323133965Sjdp		  if (power > bfd_get_arch_info (abfd)->section_align_power)
323233965Sjdp		    power = bfd_get_arch_info (abfd)->section_align_power;
323333965Sjdp		  h->u.c.p->alignment_power = power;
323433965Sjdp
323533965Sjdp		  h->u.c.p->section = bfd_make_section_old_way (symbfd,
323633965Sjdp								"COMMON");
323733965Sjdp		}
323833965Sjdp	      else
323933965Sjdp		{
324033965Sjdp		  /* Adjust the size of the common symbol if
324133965Sjdp		     necessary.  */
324233965Sjdp		  if (value > h->u.c.size)
324333965Sjdp		    h->u.c.size = value;
324433965Sjdp		}
324533965Sjdp	    }
324633965Sjdp	}
324733965Sjdp
324833965Sjdp      if (type == N_WEAKA
324933965Sjdp	  || type == N_WEAKT
325033965Sjdp	  || type == N_WEAKD
325133965Sjdp	  || type == N_WEAKB)
325233965Sjdp	{
325333965Sjdp	  /* This symbol is weak but defined.  We must pull it in if
325433965Sjdp	     the current link symbol is undefined, but we don't want
325533965Sjdp	     it if the current link symbol is common.  */
325633965Sjdp	  if (h->type == bfd_link_hash_undefined)
325733965Sjdp	    {
325833965Sjdp	      if (! (*info->callbacks->add_archive_element) (info, abfd, name))
325933965Sjdp		return false;
326033965Sjdp	      *pneeded = true;
326133965Sjdp	      return true;
326233965Sjdp	    }
326333965Sjdp	}
326433965Sjdp    }
326533965Sjdp
326633965Sjdp  /* We do not need this object file.  */
326733965Sjdp  return true;
326833965Sjdp}
326933965Sjdp
327033965Sjdp/* Add all symbols from an object file to the hash table.  */
327133965Sjdp
327233965Sjdpstatic boolean
327333965Sjdpaout_link_add_symbols (abfd, info)
327433965Sjdp     bfd *abfd;
327533965Sjdp     struct bfd_link_info *info;
327633965Sjdp{
327733965Sjdp  boolean (*add_one_symbol) PARAMS ((struct bfd_link_info *, bfd *,
327833965Sjdp				     const char *, flagword, asection *,
327933965Sjdp				     bfd_vma, const char *, boolean,
328033965Sjdp				     boolean,
328133965Sjdp				     struct bfd_link_hash_entry **));
328233965Sjdp  struct external_nlist *syms;
328333965Sjdp  bfd_size_type sym_count;
328433965Sjdp  char *strings;
328533965Sjdp  boolean copy;
328633965Sjdp  struct aout_link_hash_entry **sym_hash;
328733965Sjdp  register struct external_nlist *p;
328833965Sjdp  struct external_nlist *pend;
328933965Sjdp
329033965Sjdp  syms = obj_aout_external_syms (abfd);
329133965Sjdp  sym_count = obj_aout_external_sym_count (abfd);
329233965Sjdp  strings = obj_aout_external_strings (abfd);
329333965Sjdp  if (info->keep_memory)
329433965Sjdp    copy = false;
329533965Sjdp  else
329633965Sjdp    copy = true;
329733965Sjdp
329833965Sjdp  if (aout_backend_info (abfd)->add_dynamic_symbols != NULL)
329933965Sjdp    {
330033965Sjdp      if (! ((*aout_backend_info (abfd)->add_dynamic_symbols)
330133965Sjdp	     (abfd, info, &syms, &sym_count, &strings)))
330233965Sjdp	return false;
330333965Sjdp    }
330433965Sjdp
330533965Sjdp  /* We keep a list of the linker hash table entries that correspond
330633965Sjdp     to particular symbols.  We could just look them up in the hash
330733965Sjdp     table, but keeping the list is more efficient.  Perhaps this
330833965Sjdp     should be conditional on info->keep_memory.  */
330933965Sjdp  sym_hash = ((struct aout_link_hash_entry **)
331033965Sjdp	      bfd_alloc (abfd,
331133965Sjdp			 ((size_t) sym_count
331233965Sjdp			  * sizeof (struct aout_link_hash_entry *))));
331333965Sjdp  if (sym_hash == NULL && sym_count != 0)
331433965Sjdp    return false;
331533965Sjdp  obj_aout_sym_hashes (abfd) = sym_hash;
331633965Sjdp
331733965Sjdp  add_one_symbol = aout_backend_info (abfd)->add_one_symbol;
331833965Sjdp  if (add_one_symbol == NULL)
331933965Sjdp    add_one_symbol = _bfd_generic_link_add_one_symbol;
332033965Sjdp
332133965Sjdp  p = syms;
332233965Sjdp  pend = p + sym_count;
332333965Sjdp  for (; p < pend; p++, sym_hash++)
332433965Sjdp    {
332533965Sjdp      int type;
332633965Sjdp      const char *name;
332733965Sjdp      bfd_vma value;
332833965Sjdp      asection *section;
332933965Sjdp      flagword flags;
333033965Sjdp      const char *string;
333133965Sjdp
333233965Sjdp      *sym_hash = NULL;
333333965Sjdp
333433965Sjdp      type = bfd_h_get_8 (abfd, p->e_type);
333533965Sjdp
333633965Sjdp      /* Ignore debugging symbols.  */
333733965Sjdp      if ((type & N_STAB) != 0)
333833965Sjdp	continue;
333933965Sjdp
334033965Sjdp      name = strings + GET_WORD (abfd, p->e_strx);
334133965Sjdp      value = GET_WORD (abfd, p->e_value);
334233965Sjdp      flags = BSF_GLOBAL;
334333965Sjdp      string = NULL;
334433965Sjdp      switch (type)
334533965Sjdp	{
334633965Sjdp	default:
334733965Sjdp	  abort ();
334833965Sjdp
334933965Sjdp	case N_UNDF:
335033965Sjdp	case N_ABS:
335133965Sjdp	case N_TEXT:
335233965Sjdp	case N_DATA:
335333965Sjdp	case N_BSS:
335433965Sjdp	case N_FN_SEQ:
335533965Sjdp	case N_COMM:
335633965Sjdp	case N_SETV:
335733965Sjdp	case N_FN:
335833965Sjdp	  /* Ignore symbols that are not externally visible.  */
335933965Sjdp	  continue;
336033965Sjdp	case N_INDR:
336133965Sjdp	  /* Ignore local indirect symbol.  */
336233965Sjdp	  ++p;
336333965Sjdp	  ++sym_hash;
336433965Sjdp	  continue;
336533965Sjdp
336633965Sjdp	case N_UNDF | N_EXT:
336733965Sjdp	  if (value == 0)
336833965Sjdp	    {
336933965Sjdp	      section = bfd_und_section_ptr;
337033965Sjdp	      flags = 0;
337133965Sjdp	    }
337233965Sjdp	  else
337333965Sjdp	    section = bfd_com_section_ptr;
337433965Sjdp	  break;
337533965Sjdp	case N_ABS | N_EXT:
337633965Sjdp	  section = bfd_abs_section_ptr;
337733965Sjdp	  break;
337833965Sjdp	case N_TEXT | N_EXT:
337933965Sjdp	  section = obj_textsec (abfd);
338033965Sjdp	  value -= bfd_get_section_vma (abfd, section);
338133965Sjdp	  break;
338233965Sjdp	case N_DATA | N_EXT:
338333965Sjdp	case N_SETV | N_EXT:
338433965Sjdp	  /* Treat N_SETV symbols as N_DATA symbol; see comment in
338533965Sjdp	     translate_from_native_sym_flags.  */
338633965Sjdp	  section = obj_datasec (abfd);
338733965Sjdp	  value -= bfd_get_section_vma (abfd, section);
338833965Sjdp	  break;
338933965Sjdp	case N_BSS | N_EXT:
339033965Sjdp	  section = obj_bsssec (abfd);
339133965Sjdp	  value -= bfd_get_section_vma (abfd, section);
339233965Sjdp	  break;
339333965Sjdp	case N_INDR | N_EXT:
339433965Sjdp	  /* An indirect symbol.  The next symbol is the symbol
339533965Sjdp	     which this one really is.  */
339633965Sjdp	  BFD_ASSERT (p + 1 < pend);
339733965Sjdp	  ++p;
339833965Sjdp	  string = strings + GET_WORD (abfd, p->e_strx);
339933965Sjdp	  section = bfd_ind_section_ptr;
340033965Sjdp	  flags |= BSF_INDIRECT;
340133965Sjdp	  break;
340233965Sjdp	case N_COMM | N_EXT:
340333965Sjdp	  section = bfd_com_section_ptr;
340433965Sjdp	  break;
340533965Sjdp	case N_SETA: case N_SETA | N_EXT:
340633965Sjdp	  section = bfd_abs_section_ptr;
340733965Sjdp	  flags |= BSF_CONSTRUCTOR;
340833965Sjdp	  break;
340933965Sjdp	case N_SETT: case N_SETT | N_EXT:
341033965Sjdp	  section = obj_textsec (abfd);
341133965Sjdp	  flags |= BSF_CONSTRUCTOR;
341233965Sjdp	  value -= bfd_get_section_vma (abfd, section);
341333965Sjdp	  break;
341433965Sjdp	case N_SETD: case N_SETD | N_EXT:
341533965Sjdp	  section = obj_datasec (abfd);
341633965Sjdp	  flags |= BSF_CONSTRUCTOR;
341733965Sjdp	  value -= bfd_get_section_vma (abfd, section);
341833965Sjdp	  break;
341933965Sjdp	case N_SETB: case N_SETB | N_EXT:
342033965Sjdp	  section = obj_bsssec (abfd);
342133965Sjdp	  flags |= BSF_CONSTRUCTOR;
342233965Sjdp	  value -= bfd_get_section_vma (abfd, section);
342333965Sjdp	  break;
342433965Sjdp	case N_WARNING:
342533965Sjdp	  /* A warning symbol.  The next symbol is the one to warn
342633965Sjdp	     about.  */
342733965Sjdp	  BFD_ASSERT (p + 1 < pend);
342833965Sjdp	  ++p;
342933965Sjdp	  string = name;
343033965Sjdp	  name = strings + GET_WORD (abfd, p->e_strx);
343133965Sjdp	  section = bfd_und_section_ptr;
343233965Sjdp	  flags |= BSF_WARNING;
343333965Sjdp	  break;
343433965Sjdp	case N_WEAKU:
343533965Sjdp	  section = bfd_und_section_ptr;
343633965Sjdp	  flags = BSF_WEAK;
343733965Sjdp	  break;
343833965Sjdp	case N_WEAKA:
343933965Sjdp	  section = bfd_abs_section_ptr;
344033965Sjdp	  flags = BSF_WEAK;
344133965Sjdp	  break;
344233965Sjdp	case N_WEAKT:
344333965Sjdp	  section = obj_textsec (abfd);
344433965Sjdp	  value -= bfd_get_section_vma (abfd, section);
344533965Sjdp	  flags = BSF_WEAK;
344633965Sjdp	  break;
344733965Sjdp	case N_WEAKD:
344833965Sjdp	  section = obj_datasec (abfd);
344933965Sjdp	  value -= bfd_get_section_vma (abfd, section);
345033965Sjdp	  flags = BSF_WEAK;
345133965Sjdp	  break;
345233965Sjdp	case N_WEAKB:
345333965Sjdp	  section = obj_bsssec (abfd);
345433965Sjdp	  value -= bfd_get_section_vma (abfd, section);
345533965Sjdp	  flags = BSF_WEAK;
345633965Sjdp	  break;
345733965Sjdp	}
345833965Sjdp
345933965Sjdp      if (! ((*add_one_symbol)
346033965Sjdp	     (info, abfd, name, flags, section, value, string, copy, false,
346133965Sjdp	      (struct bfd_link_hash_entry **) sym_hash)))
346233965Sjdp	return false;
346333965Sjdp
346433965Sjdp      /* Restrict the maximum alignment of a common symbol based on
346533965Sjdp	 the architecture, since a.out has no way to represent
346633965Sjdp	 alignment requirements of a section in a .o file.  FIXME:
346733965Sjdp	 This isn't quite right: it should use the architecture of the
346833965Sjdp	 output file, not the input files.  */
346933965Sjdp      if ((*sym_hash)->root.type == bfd_link_hash_common
347033965Sjdp	  && ((*sym_hash)->root.u.c.p->alignment_power >
347133965Sjdp	      bfd_get_arch_info (abfd)->section_align_power))
347233965Sjdp	(*sym_hash)->root.u.c.p->alignment_power =
347333965Sjdp	  bfd_get_arch_info (abfd)->section_align_power;
347433965Sjdp
347533965Sjdp      /* If this is a set symbol, and we are not building sets, then
347633965Sjdp	 it is possible for the hash entry to not have been set.  In
347733965Sjdp	 such a case, treat the symbol as not globally defined.  */
347833965Sjdp      if ((*sym_hash)->root.type == bfd_link_hash_new)
347933965Sjdp	{
348033965Sjdp	  BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0);
348133965Sjdp	  *sym_hash = NULL;
348233965Sjdp	}
348333965Sjdp
348433965Sjdp      if (type == (N_INDR | N_EXT) || type == N_WARNING)
348533965Sjdp	++sym_hash;
348633965Sjdp    }
348733965Sjdp
348833965Sjdp  return true;
348933965Sjdp}
349033965Sjdp
349133965Sjdp/* A hash table used for header files with N_BINCL entries.  */
349233965Sjdp
349333965Sjdpstruct aout_link_includes_table
349433965Sjdp{
349533965Sjdp  struct bfd_hash_table root;
349633965Sjdp};
349733965Sjdp
349833965Sjdp/* A linked list of totals that we have found for a particular header
349933965Sjdp   file.  */
350033965Sjdp
350133965Sjdpstruct aout_link_includes_totals
350233965Sjdp{
350333965Sjdp  struct aout_link_includes_totals *next;
350433965Sjdp  bfd_vma total;
350533965Sjdp};
350633965Sjdp
350733965Sjdp/* An entry in the header file hash table.  */
350833965Sjdp
350933965Sjdpstruct aout_link_includes_entry
351033965Sjdp{
351133965Sjdp  struct bfd_hash_entry root;
351233965Sjdp  /* List of totals we have found for this file.  */
351333965Sjdp  struct aout_link_includes_totals *totals;
351433965Sjdp};
351533965Sjdp
351633965Sjdp/* Look up an entry in an the header file hash table.  */
351733965Sjdp
351833965Sjdp#define aout_link_includes_lookup(table, string, create, copy) \
351933965Sjdp  ((struct aout_link_includes_entry *) \
352033965Sjdp   bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
352133965Sjdp
352233965Sjdp/* During the final link step we need to pass around a bunch of
352333965Sjdp   information, so we do it in an instance of this structure.  */
352433965Sjdp
352533965Sjdpstruct aout_final_link_info
352633965Sjdp{
352733965Sjdp  /* General link information.  */
352833965Sjdp  struct bfd_link_info *info;
352933965Sjdp  /* Output bfd.  */
353033965Sjdp  bfd *output_bfd;
353133965Sjdp  /* Reloc file positions.  */
353233965Sjdp  file_ptr treloff, dreloff;
353333965Sjdp  /* File position of symbols.  */
353433965Sjdp  file_ptr symoff;
353533965Sjdp  /* String table.  */
353633965Sjdp  struct bfd_strtab_hash *strtab;
353733965Sjdp  /* Header file hash table.  */
353833965Sjdp  struct aout_link_includes_table includes;
353933965Sjdp  /* A buffer large enough to hold the contents of any section.  */
354033965Sjdp  bfd_byte *contents;
354133965Sjdp  /* A buffer large enough to hold the relocs of any section.  */
354233965Sjdp  PTR relocs;
354333965Sjdp  /* A buffer large enough to hold the symbol map of any input BFD.  */
354433965Sjdp  int *symbol_map;
354533965Sjdp  /* A buffer large enough to hold output symbols of any input BFD.  */
354633965Sjdp  struct external_nlist *output_syms;
354733965Sjdp};
354833965Sjdp
354933965Sjdpstatic struct bfd_hash_entry *aout_link_includes_newfunc
355033965Sjdp  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
355133965Sjdpstatic boolean aout_link_input_bfd
355233965Sjdp  PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
355333965Sjdpstatic boolean aout_link_write_symbols
355433965Sjdp  PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
355533965Sjdpstatic boolean aout_link_write_other_symbol
355633965Sjdp  PARAMS ((struct aout_link_hash_entry *, PTR));
355733965Sjdpstatic boolean aout_link_input_section
355833965Sjdp  PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
355933965Sjdp	   asection *input_section, file_ptr *reloff_ptr,
356033965Sjdp	   bfd_size_type rel_size));
356133965Sjdpstatic boolean aout_link_input_section_std
356233965Sjdp  PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
356333965Sjdp	   asection *input_section, struct reloc_std_external *,
356433965Sjdp	   bfd_size_type rel_size, bfd_byte *contents));
356533965Sjdpstatic boolean aout_link_input_section_ext
356633965Sjdp  PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
356733965Sjdp	   asection *input_section, struct reloc_ext_external *,
356833965Sjdp	   bfd_size_type rel_size, bfd_byte *contents));
356933965Sjdpstatic INLINE asection *aout_reloc_index_to_section
357033965Sjdp  PARAMS ((bfd *, int));
357133965Sjdpstatic boolean aout_link_reloc_link_order
357233965Sjdp  PARAMS ((struct aout_final_link_info *, asection *,
357333965Sjdp	   struct bfd_link_order *));
357433965Sjdp
357533965Sjdp/* The function to create a new entry in the header file hash table.  */
357633965Sjdp
357733965Sjdpstatic struct bfd_hash_entry *
357833965Sjdpaout_link_includes_newfunc (entry, table, string)
357933965Sjdp     struct bfd_hash_entry *entry;
358033965Sjdp     struct bfd_hash_table *table;
358133965Sjdp     const char *string;
358233965Sjdp{
358333965Sjdp  struct aout_link_includes_entry *ret =
358433965Sjdp    (struct aout_link_includes_entry *) entry;
358533965Sjdp
358633965Sjdp  /* Allocate the structure if it has not already been allocated by a
358733965Sjdp     subclass.  */
358833965Sjdp  if (ret == (struct aout_link_includes_entry *) NULL)
358933965Sjdp    ret = ((struct aout_link_includes_entry *)
359033965Sjdp	   bfd_hash_allocate (table,
359133965Sjdp			      sizeof (struct aout_link_includes_entry)));
359233965Sjdp  if (ret == (struct aout_link_includes_entry *) NULL)
359333965Sjdp    return (struct bfd_hash_entry *) ret;
359433965Sjdp
359533965Sjdp  /* Call the allocation method of the superclass.  */
359633965Sjdp  ret = ((struct aout_link_includes_entry *)
359733965Sjdp	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
359833965Sjdp  if (ret)
359933965Sjdp    {
360033965Sjdp      /* Set local fields.  */
360133965Sjdp      ret->totals = NULL;
360233965Sjdp    }
360333965Sjdp
360433965Sjdp  return (struct bfd_hash_entry *) ret;
360533965Sjdp}
360633965Sjdp
360733965Sjdp/* Do the final link step.  This is called on the output BFD.  The
360833965Sjdp   INFO structure should point to a list of BFDs linked through the
360933965Sjdp   link_next field which can be used to find each BFD which takes part
361033965Sjdp   in the output.  Also, each section in ABFD should point to a list
361133965Sjdp   of bfd_link_order structures which list all the input sections for
361233965Sjdp   the output section.  */
361333965Sjdp
361433965Sjdpboolean
361533965SjdpNAME(aout,final_link) (abfd, info, callback)
361633965Sjdp     bfd *abfd;
361733965Sjdp     struct bfd_link_info *info;
361833965Sjdp     void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
361933965Sjdp{
362033965Sjdp  struct aout_final_link_info aout_info;
362133965Sjdp  boolean includes_hash_initialized = false;
362233965Sjdp  register bfd *sub;
362333965Sjdp  bfd_size_type trsize, drsize;
362433965Sjdp  size_t max_contents_size;
362533965Sjdp  size_t max_relocs_size;
362633965Sjdp  size_t max_sym_count;
362733965Sjdp  bfd_size_type text_size;
362833965Sjdp  file_ptr text_end;
362933965Sjdp  register struct bfd_link_order *p;
363033965Sjdp  asection *o;
363133965Sjdp  boolean have_link_order_relocs;
363233965Sjdp
363333965Sjdp  if (info->shared)
363433965Sjdp    abfd->flags |= DYNAMIC;
363533965Sjdp
363633965Sjdp  aout_info.info = info;
363733965Sjdp  aout_info.output_bfd = abfd;
363833965Sjdp  aout_info.contents = NULL;
363933965Sjdp  aout_info.relocs = NULL;
364033965Sjdp  aout_info.symbol_map = NULL;
364133965Sjdp  aout_info.output_syms = NULL;
364233965Sjdp
364333965Sjdp  if (! bfd_hash_table_init_n (&aout_info.includes.root,
364433965Sjdp			       aout_link_includes_newfunc,
364533965Sjdp			       251))
364633965Sjdp    goto error_return;
364733965Sjdp  includes_hash_initialized = true;
364833965Sjdp
364933965Sjdp  /* Figure out the largest section size.  Also, if generating
365033965Sjdp     relocateable output, count the relocs.  */
365133965Sjdp  trsize = 0;
365233965Sjdp  drsize = 0;
365333965Sjdp  max_contents_size = 0;
365433965Sjdp  max_relocs_size = 0;
365533965Sjdp  max_sym_count = 0;
365633965Sjdp  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
365733965Sjdp    {
365833965Sjdp      size_t sz;
365933965Sjdp
366033965Sjdp      if (info->relocateable)
366133965Sjdp	{
366233965Sjdp	  if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
366333965Sjdp	    {
366433965Sjdp	      trsize += exec_hdr (sub)->a_trsize;
366533965Sjdp	      drsize += exec_hdr (sub)->a_drsize;
366633965Sjdp	    }
366733965Sjdp	  else
366833965Sjdp	    {
366933965Sjdp	      /* FIXME: We need to identify the .text and .data sections
367033965Sjdp		 and call get_reloc_upper_bound and canonicalize_reloc to
367133965Sjdp		 work out the number of relocs needed, and then multiply
367233965Sjdp		 by the reloc size.  */
367333965Sjdp	      (*_bfd_error_handler)
367460484Sobrien		(_("%s: relocateable link from %s to %s not supported"),
367533965Sjdp		 bfd_get_filename (abfd),
367633965Sjdp		 sub->xvec->name, abfd->xvec->name);
367733965Sjdp	      bfd_set_error (bfd_error_invalid_operation);
367833965Sjdp	      goto error_return;
367933965Sjdp	    }
368033965Sjdp	}
368133965Sjdp
368233965Sjdp      if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
368333965Sjdp	{
368433965Sjdp	  sz = bfd_section_size (sub, obj_textsec (sub));
368533965Sjdp	  if (sz > max_contents_size)
368633965Sjdp	    max_contents_size = sz;
368733965Sjdp	  sz = bfd_section_size (sub, obj_datasec (sub));
368833965Sjdp	  if (sz > max_contents_size)
368933965Sjdp	    max_contents_size = sz;
369033965Sjdp
369133965Sjdp	  sz = exec_hdr (sub)->a_trsize;
369233965Sjdp	  if (sz > max_relocs_size)
369333965Sjdp	    max_relocs_size = sz;
369433965Sjdp	  sz = exec_hdr (sub)->a_drsize;
369533965Sjdp	  if (sz > max_relocs_size)
369633965Sjdp	    max_relocs_size = sz;
369733965Sjdp
369833965Sjdp	  sz = obj_aout_external_sym_count (sub);
369933965Sjdp	  if (sz > max_sym_count)
370033965Sjdp	    max_sym_count = sz;
370133965Sjdp	}
370233965Sjdp    }
370333965Sjdp
370433965Sjdp  if (info->relocateable)
370533965Sjdp    {
370633965Sjdp      if (obj_textsec (abfd) != (asection *) NULL)
370733965Sjdp	trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
370833965Sjdp						 ->link_order_head)
370933965Sjdp		   * obj_reloc_entry_size (abfd));
371033965Sjdp      if (obj_datasec (abfd) != (asection *) NULL)
371133965Sjdp	drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
371233965Sjdp						 ->link_order_head)
371333965Sjdp		   * obj_reloc_entry_size (abfd));
371433965Sjdp    }
371533965Sjdp
371633965Sjdp  exec_hdr (abfd)->a_trsize = trsize;
371733965Sjdp  exec_hdr (abfd)->a_drsize = drsize;
371833965Sjdp
371933965Sjdp  exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
372033965Sjdp
372133965Sjdp  /* Adjust the section sizes and vmas according to the magic number.
372233965Sjdp     This sets a_text, a_data and a_bss in the exec_hdr and sets the
372333965Sjdp     filepos for each section.  */
372433965Sjdp  if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
372533965Sjdp    goto error_return;
372633965Sjdp
372733965Sjdp  /* The relocation and symbol file positions differ among a.out
372833965Sjdp     targets.  We are passed a callback routine from the backend
372933965Sjdp     specific code to handle this.
373033965Sjdp     FIXME: At this point we do not know how much space the symbol
373133965Sjdp     table will require.  This will not work for any (nonstandard)
373233965Sjdp     a.out target that needs to know the symbol table size before it
373333965Sjdp     can compute the relocation file positions.  This may or may not
373433965Sjdp     be the case for the hp300hpux target, for example.  */
373533965Sjdp  (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff,
373633965Sjdp	       &aout_info.symoff);
373733965Sjdp  obj_textsec (abfd)->rel_filepos = aout_info.treloff;
373833965Sjdp  obj_datasec (abfd)->rel_filepos = aout_info.dreloff;
373933965Sjdp  obj_sym_filepos (abfd) = aout_info.symoff;
374033965Sjdp
374133965Sjdp  /* We keep a count of the symbols as we output them.  */
374233965Sjdp  obj_aout_external_sym_count (abfd) = 0;
374333965Sjdp
374433965Sjdp  /* We accumulate the string table as we write out the symbols.  */
374533965Sjdp  aout_info.strtab = _bfd_stringtab_init ();
374633965Sjdp  if (aout_info.strtab == NULL)
374733965Sjdp    goto error_return;
374833965Sjdp
374933965Sjdp  /* Allocate buffers to hold section contents and relocs.  */
375033965Sjdp  aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size);
375133965Sjdp  aout_info.relocs = (PTR) bfd_malloc (max_relocs_size);
375233965Sjdp  aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int *));
375333965Sjdp  aout_info.output_syms = ((struct external_nlist *)
375433965Sjdp			   bfd_malloc ((max_sym_count + 1)
375533965Sjdp				       * sizeof (struct external_nlist)));
375633965Sjdp  if ((aout_info.contents == NULL && max_contents_size != 0)
375733965Sjdp      || (aout_info.relocs == NULL && max_relocs_size != 0)
375833965Sjdp      || (aout_info.symbol_map == NULL && max_sym_count != 0)
375933965Sjdp      || aout_info.output_syms == NULL)
376033965Sjdp    goto error_return;
376133965Sjdp
376233965Sjdp  /* If we have a symbol named __DYNAMIC, force it out now.  This is
376333965Sjdp     required by SunOS.  Doing this here rather than in sunos.c is a
376433965Sjdp     hack, but it's easier than exporting everything which would be
376533965Sjdp     needed.  */
376633965Sjdp  {
376733965Sjdp    struct aout_link_hash_entry *h;
376833965Sjdp
376933965Sjdp    h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
377033965Sjdp			       false, false, false);
377133965Sjdp    if (h != NULL)
377233965Sjdp      aout_link_write_other_symbol (h, &aout_info);
377333965Sjdp  }
377433965Sjdp
377533965Sjdp  /* The most time efficient way to do the link would be to read all
377633965Sjdp     the input object files into memory and then sort out the
377733965Sjdp     information into the output file.  Unfortunately, that will
377833965Sjdp     probably use too much memory.  Another method would be to step
377933965Sjdp     through everything that composes the text section and write it
378033965Sjdp     out, and then everything that composes the data section and write
378133965Sjdp     it out, and then write out the relocs, and then write out the
378233965Sjdp     symbols.  Unfortunately, that requires reading stuff from each
378333965Sjdp     input file several times, and we will not be able to keep all the
378433965Sjdp     input files open simultaneously, and reopening them will be slow.
378533965Sjdp
378633965Sjdp     What we do is basically process one input file at a time.  We do
378733965Sjdp     everything we need to do with an input file once--copy over the
378833965Sjdp     section contents, handle the relocation information, and write
378933965Sjdp     out the symbols--and then we throw away the information we read
379033965Sjdp     from it.  This approach requires a lot of lseeks of the output
379133965Sjdp     file, which is unfortunate but still faster than reopening a lot
379233965Sjdp     of files.
379333965Sjdp
379433965Sjdp     We use the output_has_begun field of the input BFDs to see
379533965Sjdp     whether we have already handled it.  */
379633965Sjdp  for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
379733965Sjdp    sub->output_has_begun = false;
379833965Sjdp
379933965Sjdp  /* Mark all sections which are to be included in the link.  This
380033965Sjdp     will normally be every section.  We need to do this so that we
380133965Sjdp     can identify any sections which the linker has decided to not
380233965Sjdp     include.  */
380333965Sjdp  for (o = abfd->sections; o != NULL; o = o->next)
380433965Sjdp    {
380533965Sjdp      for (p = o->link_order_head; p != NULL; p = p->next)
380633965Sjdp	{
380733965Sjdp	  if (p->type == bfd_indirect_link_order)
380833965Sjdp	    p->u.indirect.section->linker_mark = true;
380933965Sjdp	}
381033965Sjdp    }
381133965Sjdp
381233965Sjdp  have_link_order_relocs = false;
381333965Sjdp  for (o = abfd->sections; o != (asection *) NULL; o = o->next)
381433965Sjdp    {
381533965Sjdp      for (p = o->link_order_head;
381633965Sjdp	   p != (struct bfd_link_order *) NULL;
381733965Sjdp	   p = p->next)
381833965Sjdp	{
381933965Sjdp	  if (p->type == bfd_indirect_link_order
382033965Sjdp	      && (bfd_get_flavour (p->u.indirect.section->owner)
382133965Sjdp		  == bfd_target_aout_flavour))
382233965Sjdp	    {
382333965Sjdp	      bfd *input_bfd;
382433965Sjdp
382533965Sjdp	      input_bfd = p->u.indirect.section->owner;
382633965Sjdp	      if (! input_bfd->output_has_begun)
382733965Sjdp		{
382833965Sjdp		  if (! aout_link_input_bfd (&aout_info, input_bfd))
382933965Sjdp		    goto error_return;
383033965Sjdp		  input_bfd->output_has_begun = true;
383133965Sjdp		}
383233965Sjdp	    }
383333965Sjdp	  else if (p->type == bfd_section_reloc_link_order
383433965Sjdp		   || p->type == bfd_symbol_reloc_link_order)
383533965Sjdp	    {
383633965Sjdp	      /* These are handled below.  */
383733965Sjdp	      have_link_order_relocs = true;
383833965Sjdp	    }
383933965Sjdp	  else
384033965Sjdp	    {
384133965Sjdp	      if (! _bfd_default_link_order (abfd, info, o, p))
384233965Sjdp		goto error_return;
384333965Sjdp	    }
384433965Sjdp	}
384533965Sjdp    }
384633965Sjdp
384733965Sjdp  /* Write out any symbols that we have not already written out.  */
384833965Sjdp  aout_link_hash_traverse (aout_hash_table (info),
384933965Sjdp			   aout_link_write_other_symbol,
385033965Sjdp			   (PTR) &aout_info);
385133965Sjdp
385233965Sjdp  /* Now handle any relocs we were asked to create by the linker.
385333965Sjdp     These did not come from any input file.  We must do these after
385433965Sjdp     we have written out all the symbols, so that we know the symbol
385533965Sjdp     indices to use.  */
385633965Sjdp  if (have_link_order_relocs)
385733965Sjdp    {
385833965Sjdp      for (o = abfd->sections; o != (asection *) NULL; o = o->next)
385933965Sjdp	{
386033965Sjdp	  for (p = o->link_order_head;
386133965Sjdp	       p != (struct bfd_link_order *) NULL;
386233965Sjdp	       p = p->next)
386333965Sjdp	    {
386433965Sjdp	      if (p->type == bfd_section_reloc_link_order
386533965Sjdp		  || p->type == bfd_symbol_reloc_link_order)
386633965Sjdp		{
386733965Sjdp		  if (! aout_link_reloc_link_order (&aout_info, o, p))
386833965Sjdp		    goto error_return;
386933965Sjdp		}
387033965Sjdp	    }
387133965Sjdp	}
387233965Sjdp    }
387333965Sjdp
387433965Sjdp  if (aout_info.contents != NULL)
387533965Sjdp    {
387633965Sjdp      free (aout_info.contents);
387733965Sjdp      aout_info.contents = NULL;
387833965Sjdp    }
387933965Sjdp  if (aout_info.relocs != NULL)
388033965Sjdp    {
388133965Sjdp      free (aout_info.relocs);
388233965Sjdp      aout_info.relocs = NULL;
388333965Sjdp    }
388433965Sjdp  if (aout_info.symbol_map != NULL)
388533965Sjdp    {
388633965Sjdp      free (aout_info.symbol_map);
388733965Sjdp      aout_info.symbol_map = NULL;
388833965Sjdp    }
388933965Sjdp  if (aout_info.output_syms != NULL)
389033965Sjdp    {
389133965Sjdp      free (aout_info.output_syms);
389233965Sjdp      aout_info.output_syms = NULL;
389333965Sjdp    }
389433965Sjdp  if (includes_hash_initialized)
389533965Sjdp    {
389633965Sjdp      bfd_hash_table_free (&aout_info.includes.root);
389733965Sjdp      includes_hash_initialized = false;
389833965Sjdp    }
389933965Sjdp
390033965Sjdp  /* Finish up any dynamic linking we may be doing.  */
390133965Sjdp  if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
390233965Sjdp    {
390333965Sjdp      if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
390433965Sjdp	goto error_return;
390533965Sjdp    }
390633965Sjdp
390733965Sjdp  /* Update the header information.  */
390833965Sjdp  abfd->symcount = obj_aout_external_sym_count (abfd);
390933965Sjdp  exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE;
391033965Sjdp  obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms;
391133965Sjdp  obj_textsec (abfd)->reloc_count =
391233965Sjdp    exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
391333965Sjdp  obj_datasec (abfd)->reloc_count =
391433965Sjdp    exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
391533965Sjdp
391638889Sjdp  /* Write out the string table, unless there are no symbols.  */
391738889Sjdp  if (abfd->symcount > 0)
391838889Sjdp    {
391938889Sjdp      if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
392038889Sjdp	  || ! emit_stringtab (abfd, aout_info.strtab))
392138889Sjdp	goto error_return;
392238889Sjdp    }
392338889Sjdp  else if (obj_textsec (abfd)->reloc_count == 0
392438889Sjdp	   && obj_datasec (abfd)->reloc_count == 0)
392538889Sjdp    {
392638889Sjdp      bfd_byte b;
392733965Sjdp
392838889Sjdp      b = 0;
392938889Sjdp      if (bfd_seek (abfd,
393038889Sjdp		    (obj_datasec (abfd)->filepos
393138889Sjdp		     + exec_hdr (abfd)->a_data
393238889Sjdp		     - 1),
393338889Sjdp		    SEEK_SET) != 0
393438889Sjdp	  || bfd_write (&b, 1, 1, abfd) != 1)
393538889Sjdp	goto error_return;
393638889Sjdp    }
393738889Sjdp
393838889Sjdp  return true;
393938889Sjdp
394033965Sjdp error_return:
394133965Sjdp  if (aout_info.contents != NULL)
394233965Sjdp    free (aout_info.contents);
394333965Sjdp  if (aout_info.relocs != NULL)
394433965Sjdp    free (aout_info.relocs);
394533965Sjdp  if (aout_info.symbol_map != NULL)
394633965Sjdp    free (aout_info.symbol_map);
394733965Sjdp  if (aout_info.output_syms != NULL)
394833965Sjdp    free (aout_info.output_syms);
394933965Sjdp  if (includes_hash_initialized)
395033965Sjdp    bfd_hash_table_free (&aout_info.includes.root);
395133965Sjdp  return false;
395233965Sjdp}
395333965Sjdp
395433965Sjdp/* Link an a.out input BFD into the output file.  */
395533965Sjdp
395633965Sjdpstatic boolean
395733965Sjdpaout_link_input_bfd (finfo, input_bfd)
395833965Sjdp     struct aout_final_link_info *finfo;
395933965Sjdp     bfd *input_bfd;
396033965Sjdp{
396133965Sjdp  bfd_size_type sym_count;
396233965Sjdp
396333965Sjdp  BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
396433965Sjdp
396533965Sjdp  /* If this is a dynamic object, it may need special handling.  */
396633965Sjdp  if ((input_bfd->flags & DYNAMIC) != 0
396733965Sjdp      && aout_backend_info (input_bfd)->link_dynamic_object != NULL)
396833965Sjdp    {
396933965Sjdp      return ((*aout_backend_info (input_bfd)->link_dynamic_object)
397033965Sjdp	      (finfo->info, input_bfd));
397133965Sjdp    }
397233965Sjdp
397333965Sjdp  /* Get the symbols.  We probably have them already, unless
397433965Sjdp     finfo->info->keep_memory is false.  */
397533965Sjdp  if (! aout_get_external_symbols (input_bfd))
397633965Sjdp    return false;
397733965Sjdp
397833965Sjdp  sym_count = obj_aout_external_sym_count (input_bfd);
397933965Sjdp
398033965Sjdp  /* Write out the symbols and get a map of the new indices.  The map
398133965Sjdp     is placed into finfo->symbol_map.  */
398233965Sjdp  if (! aout_link_write_symbols (finfo, input_bfd))
398333965Sjdp    return false;
398433965Sjdp
398533965Sjdp  /* Relocate and write out the sections.  These functions use the
398633965Sjdp     symbol map created by aout_link_write_symbols.  The linker_mark
398733965Sjdp     field will be set if these sections are to be included in the
398833965Sjdp     link, which will normally be the case.  */
398933965Sjdp  if (obj_textsec (input_bfd)->linker_mark)
399033965Sjdp    {
399133965Sjdp      if (! aout_link_input_section (finfo, input_bfd,
399233965Sjdp				     obj_textsec (input_bfd),
399333965Sjdp				     &finfo->treloff,
399433965Sjdp				     exec_hdr (input_bfd)->a_trsize))
399533965Sjdp	return false;
399633965Sjdp    }
399733965Sjdp  if (obj_datasec (input_bfd)->linker_mark)
399833965Sjdp    {
399933965Sjdp      if (! aout_link_input_section (finfo, input_bfd,
400033965Sjdp				     obj_datasec (input_bfd),
400133965Sjdp				     &finfo->dreloff,
400233965Sjdp				     exec_hdr (input_bfd)->a_drsize))
400333965Sjdp	return false;
400433965Sjdp    }
400533965Sjdp
400633965Sjdp  /* If we are not keeping memory, we don't need the symbols any
400733965Sjdp     longer.  We still need them if we are keeping memory, because the
400833965Sjdp     strings in the hash table point into them.  */
400933965Sjdp  if (! finfo->info->keep_memory)
401033965Sjdp    {
401133965Sjdp      if (! aout_link_free_symbols (input_bfd))
401233965Sjdp	return false;
401333965Sjdp    }
401433965Sjdp
401533965Sjdp  return true;
401633965Sjdp}
401733965Sjdp
401833965Sjdp/* Adjust and write out the symbols for an a.out file.  Set the new
401933965Sjdp   symbol indices into a symbol_map.  */
402033965Sjdp
402133965Sjdpstatic boolean
402233965Sjdpaout_link_write_symbols (finfo, input_bfd)
402333965Sjdp     struct aout_final_link_info *finfo;
402433965Sjdp     bfd *input_bfd;
402533965Sjdp{
402633965Sjdp  bfd *output_bfd;
402733965Sjdp  bfd_size_type sym_count;
402833965Sjdp  char *strings;
402933965Sjdp  enum bfd_link_strip strip;
403033965Sjdp  enum bfd_link_discard discard;
403133965Sjdp  struct external_nlist *outsym;
403233965Sjdp  bfd_size_type strtab_index;
403333965Sjdp  register struct external_nlist *sym;
403433965Sjdp  struct external_nlist *sym_end;
403533965Sjdp  struct aout_link_hash_entry **sym_hash;
403633965Sjdp  int *symbol_map;
403733965Sjdp  boolean pass;
403833965Sjdp  boolean skip_next;
403933965Sjdp
404033965Sjdp  output_bfd = finfo->output_bfd;
404133965Sjdp  sym_count = obj_aout_external_sym_count (input_bfd);
404233965Sjdp  strings = obj_aout_external_strings (input_bfd);
404333965Sjdp  strip = finfo->info->strip;
404433965Sjdp  discard = finfo->info->discard;
404533965Sjdp  outsym = finfo->output_syms;
404633965Sjdp
404733965Sjdp  /* First write out a symbol for this object file, unless we are
404833965Sjdp     discarding such symbols.  */
404933965Sjdp  if (strip != strip_all
405033965Sjdp      && (strip != strip_some
405133965Sjdp	  || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename,
405233965Sjdp			      false, false) != NULL)
405333965Sjdp      && discard != discard_all)
405433965Sjdp    {
405533965Sjdp      bfd_h_put_8 (output_bfd, N_TEXT, outsym->e_type);
405633965Sjdp      bfd_h_put_8 (output_bfd, 0, outsym->e_other);
405733965Sjdp      bfd_h_put_16 (output_bfd, (bfd_vma) 0, outsym->e_desc);
405833965Sjdp      strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
405933965Sjdp				       input_bfd->filename, false);
406033965Sjdp      if (strtab_index == (bfd_size_type) -1)
406133965Sjdp	return false;
406233965Sjdp      PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
406333965Sjdp      PUT_WORD (output_bfd,
406433965Sjdp		(bfd_get_section_vma (output_bfd,
406533965Sjdp				      obj_textsec (input_bfd)->output_section)
406633965Sjdp		 + obj_textsec (input_bfd)->output_offset),
406733965Sjdp		outsym->e_value);
406833965Sjdp      ++obj_aout_external_sym_count (output_bfd);
406933965Sjdp      ++outsym;
407033965Sjdp    }
407133965Sjdp
407233965Sjdp  pass = false;
407333965Sjdp  skip_next = false;
407433965Sjdp  sym = obj_aout_external_syms (input_bfd);
407533965Sjdp  sym_end = sym + sym_count;
407633965Sjdp  sym_hash = obj_aout_sym_hashes (input_bfd);
407733965Sjdp  symbol_map = finfo->symbol_map;
407833965Sjdp  memset (symbol_map, 0, sym_count * sizeof *symbol_map);
407933965Sjdp  for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
408033965Sjdp    {
408133965Sjdp      const char *name;
408233965Sjdp      int type;
408333965Sjdp      struct aout_link_hash_entry *h;
408433965Sjdp      boolean skip;
408533965Sjdp      asection *symsec;
408633965Sjdp      bfd_vma val = 0;
408733965Sjdp      boolean copy;
408833965Sjdp
408933965Sjdp      /* We set *symbol_map to 0 above for all symbols.  If it has
409033965Sjdp         already been set to -1 for this symbol, it means that we are
409133965Sjdp         discarding it because it appears in a duplicate header file.
409233965Sjdp         See the N_BINCL code below.  */
409333965Sjdp      if (*symbol_map == -1)
409433965Sjdp	continue;
409533965Sjdp
409633965Sjdp      /* Initialize *symbol_map to -1, which means that the symbol was
409733965Sjdp         not copied into the output file.  We will change it later if
409833965Sjdp         we do copy the symbol over.  */
409933965Sjdp      *symbol_map = -1;
410033965Sjdp
410133965Sjdp      type = bfd_h_get_8 (input_bfd, sym->e_type);
410233965Sjdp      name = strings + GET_WORD (input_bfd, sym->e_strx);
410333965Sjdp
410433965Sjdp      h = NULL;
410533965Sjdp
410633965Sjdp      if (pass)
410733965Sjdp	{
410833965Sjdp	  /* Pass this symbol through.  It is the target of an
410933965Sjdp	     indirect or warning symbol.  */
411033965Sjdp	  val = GET_WORD (input_bfd, sym->e_value);
411133965Sjdp	  pass = false;
411233965Sjdp	}
411333965Sjdp      else if (skip_next)
411433965Sjdp	{
411533965Sjdp	  /* Skip this symbol, which is the target of an indirect
411633965Sjdp	     symbol that we have changed to no longer be an indirect
411733965Sjdp	     symbol.  */
411833965Sjdp	  skip_next = false;
411933965Sjdp	  continue;
412033965Sjdp	}
412133965Sjdp      else
412233965Sjdp	{
412333965Sjdp	  struct aout_link_hash_entry *hresolve;
412433965Sjdp
412533965Sjdp	  /* We have saved the hash table entry for this symbol, if
412633965Sjdp	     there is one.  Note that we could just look it up again
412733965Sjdp	     in the hash table, provided we first check that it is an
412833965Sjdp	     external symbol. */
412933965Sjdp	  h = *sym_hash;
413033965Sjdp
413133965Sjdp	  /* Use the name from the hash table, in case the symbol was
413233965Sjdp             wrapped.  */
413333965Sjdp	  if (h != NULL)
413433965Sjdp	    name = h->root.root.string;
413533965Sjdp
413633965Sjdp	  /* If this is an indirect or warning symbol, then change
413733965Sjdp	     hresolve to the base symbol.  We also change *sym_hash so
413833965Sjdp	     that the relocation routines relocate against the real
413933965Sjdp	     symbol.  */
414033965Sjdp	  hresolve = h;
414133965Sjdp	  if (h != (struct aout_link_hash_entry *) NULL
414233965Sjdp	      && (h->root.type == bfd_link_hash_indirect
414333965Sjdp		  || h->root.type == bfd_link_hash_warning))
414433965Sjdp	    {
414533965Sjdp	      hresolve = (struct aout_link_hash_entry *) h->root.u.i.link;
414633965Sjdp	      while (hresolve->root.type == bfd_link_hash_indirect
414733965Sjdp		     || hresolve->root.type == bfd_link_hash_warning)
414833965Sjdp		hresolve = ((struct aout_link_hash_entry *)
414933965Sjdp			    hresolve->root.u.i.link);
415033965Sjdp	      *sym_hash = hresolve;
415133965Sjdp	    }
415233965Sjdp
415333965Sjdp	  /* If the symbol has already been written out, skip it.  */
415433965Sjdp	  if (h != (struct aout_link_hash_entry *) NULL
415533965Sjdp	      && h->root.type != bfd_link_hash_warning
415633965Sjdp	      && h->written)
415733965Sjdp	    {
415833965Sjdp	      if ((type & N_TYPE) == N_INDR
415933965Sjdp		  || type == N_WARNING)
416033965Sjdp		skip_next = true;
416133965Sjdp	      *symbol_map = h->indx;
416233965Sjdp	      continue;
416333965Sjdp	    }
416433965Sjdp
416533965Sjdp	  /* See if we are stripping this symbol.  */
416633965Sjdp	  skip = false;
416733965Sjdp	  switch (strip)
416833965Sjdp	    {
416933965Sjdp	    case strip_none:
417033965Sjdp	      break;
417133965Sjdp	    case strip_debugger:
417233965Sjdp	      if ((type & N_STAB) != 0)
417333965Sjdp		skip = true;
417433965Sjdp	      break;
417533965Sjdp	    case strip_some:
417633965Sjdp	      if (bfd_hash_lookup (finfo->info->keep_hash, name, false, false)
417733965Sjdp		  == NULL)
417833965Sjdp		skip = true;
417933965Sjdp	      break;
418033965Sjdp	    case strip_all:
418133965Sjdp	      skip = true;
418233965Sjdp	      break;
418333965Sjdp	    }
418433965Sjdp	  if (skip)
418533965Sjdp	    {
418633965Sjdp	      if (h != (struct aout_link_hash_entry *) NULL)
418733965Sjdp		h->written = true;
418833965Sjdp	      continue;
418933965Sjdp	    }
419033965Sjdp
419133965Sjdp	  /* Get the value of the symbol.  */
419233965Sjdp	  if ((type & N_TYPE) == N_TEXT
419333965Sjdp	      || type == N_WEAKT)
419433965Sjdp	    symsec = obj_textsec (input_bfd);
419533965Sjdp	  else if ((type & N_TYPE) == N_DATA
419633965Sjdp		   || type == N_WEAKD)
419733965Sjdp	    symsec = obj_datasec (input_bfd);
419833965Sjdp	  else if ((type & N_TYPE) == N_BSS
419933965Sjdp		   || type == N_WEAKB)
420033965Sjdp	    symsec = obj_bsssec (input_bfd);
420133965Sjdp	  else if ((type & N_TYPE) == N_ABS
420233965Sjdp		   || type == N_WEAKA)
420333965Sjdp	    symsec = bfd_abs_section_ptr;
420433965Sjdp	  else if (((type & N_TYPE) == N_INDR
420533965Sjdp		    && (hresolve == (struct aout_link_hash_entry *) NULL
420633965Sjdp			|| (hresolve->root.type != bfd_link_hash_defined
420733965Sjdp			    && hresolve->root.type != bfd_link_hash_defweak
420833965Sjdp			    && hresolve->root.type != bfd_link_hash_common)))
420933965Sjdp		   || type == N_WARNING)
421033965Sjdp	    {
421133965Sjdp	      /* Pass the next symbol through unchanged.  The
421233965Sjdp		 condition above for indirect symbols is so that if
421333965Sjdp		 the indirect symbol was defined, we output it with
421433965Sjdp		 the correct definition so the debugger will
421533965Sjdp		 understand it.  */
421633965Sjdp	      pass = true;
421733965Sjdp	      val = GET_WORD (input_bfd, sym->e_value);
421833965Sjdp	      symsec = NULL;
421933965Sjdp	    }
422033965Sjdp	  else if ((type & N_STAB) != 0)
422133965Sjdp	    {
422233965Sjdp	      val = GET_WORD (input_bfd, sym->e_value);
422333965Sjdp	      symsec = NULL;
422433965Sjdp	    }
422533965Sjdp	  else
422633965Sjdp	    {
422733965Sjdp	      /* If we get here with an indirect symbol, it means that
422833965Sjdp		 we are outputting it with a real definition.  In such
422933965Sjdp		 a case we do not want to output the next symbol,
423033965Sjdp		 which is the target of the indirection.  */
423133965Sjdp	      if ((type & N_TYPE) == N_INDR)
423233965Sjdp		skip_next = true;
423333965Sjdp
423433965Sjdp	      symsec = NULL;
423533965Sjdp
423633965Sjdp	      /* We need to get the value from the hash table.  We use
423733965Sjdp		 hresolve so that if we have defined an indirect
423833965Sjdp		 symbol we output the final definition.  */
423933965Sjdp	      if (h == (struct aout_link_hash_entry *) NULL)
424033965Sjdp		{
424133965Sjdp		  switch (type & N_TYPE)
424233965Sjdp		    {
424333965Sjdp		    case N_SETT:
424433965Sjdp		      symsec = obj_textsec (input_bfd);
424533965Sjdp		      break;
424633965Sjdp		    case N_SETD:
424733965Sjdp		      symsec = obj_datasec (input_bfd);
424833965Sjdp		      break;
424933965Sjdp		    case N_SETB:
425033965Sjdp		      symsec = obj_bsssec (input_bfd);
425133965Sjdp		      break;
425233965Sjdp		    case N_SETA:
425333965Sjdp		      symsec = bfd_abs_section_ptr;
425433965Sjdp		      break;
425533965Sjdp		    default:
425633965Sjdp		      val = 0;
425733965Sjdp		      break;
425833965Sjdp		    }
425933965Sjdp		}
426033965Sjdp	      else if (hresolve->root.type == bfd_link_hash_defined
426133965Sjdp		       || hresolve->root.type == bfd_link_hash_defweak)
426233965Sjdp		{
426333965Sjdp		  asection *input_section;
426433965Sjdp		  asection *output_section;
426533965Sjdp
426633965Sjdp		  /* This case usually means a common symbol which was
426733965Sjdp		     turned into a defined symbol.  */
426833965Sjdp		  input_section = hresolve->root.u.def.section;
426933965Sjdp		  output_section = input_section->output_section;
427033965Sjdp		  BFD_ASSERT (bfd_is_abs_section (output_section)
427133965Sjdp			      || output_section->owner == output_bfd);
427233965Sjdp		  val = (hresolve->root.u.def.value
427333965Sjdp			 + bfd_get_section_vma (output_bfd, output_section)
427433965Sjdp			 + input_section->output_offset);
427533965Sjdp
427633965Sjdp		  /* Get the correct type based on the section.  If
427733965Sjdp		     this is a constructed set, force it to be
427833965Sjdp		     globally visible.  */
427933965Sjdp		  if (type == N_SETT
428033965Sjdp		      || type == N_SETD
428133965Sjdp		      || type == N_SETB
428233965Sjdp		      || type == N_SETA)
428333965Sjdp		    type |= N_EXT;
428433965Sjdp
428533965Sjdp		  type &=~ N_TYPE;
428633965Sjdp
428733965Sjdp		  if (output_section == obj_textsec (output_bfd))
428833965Sjdp		    type |= (hresolve->root.type == bfd_link_hash_defined
428933965Sjdp			     ? N_TEXT
429033965Sjdp			     : N_WEAKT);
429133965Sjdp		  else if (output_section == obj_datasec (output_bfd))
429233965Sjdp		    type |= (hresolve->root.type == bfd_link_hash_defined
429333965Sjdp			     ? N_DATA
429433965Sjdp			     : N_WEAKD);
429533965Sjdp		  else if (output_section == obj_bsssec (output_bfd))
429633965Sjdp		    type |= (hresolve->root.type == bfd_link_hash_defined
429733965Sjdp			     ? N_BSS
429833965Sjdp			     : N_WEAKB);
429933965Sjdp		  else
430033965Sjdp		    type |= (hresolve->root.type == bfd_link_hash_defined
430133965Sjdp			     ? N_ABS
430233965Sjdp			     : N_WEAKA);
430333965Sjdp		}
430433965Sjdp	      else if (hresolve->root.type == bfd_link_hash_common)
430533965Sjdp		val = hresolve->root.u.c.size;
430633965Sjdp	      else if (hresolve->root.type == bfd_link_hash_undefweak)
430733965Sjdp		{
430833965Sjdp		  val = 0;
430933965Sjdp		  type = N_WEAKU;
431033965Sjdp		}
431133965Sjdp	      else
431233965Sjdp		val = 0;
431333965Sjdp	    }
431433965Sjdp	  if (symsec != (asection *) NULL)
431533965Sjdp	    val = (symsec->output_section->vma
431633965Sjdp		   + symsec->output_offset
431733965Sjdp		   + (GET_WORD (input_bfd, sym->e_value)
431833965Sjdp		      - symsec->vma));
431933965Sjdp
432033965Sjdp	  /* If this is a global symbol set the written flag, and if
432133965Sjdp	     it is a local symbol see if we should discard it.  */
432233965Sjdp	  if (h != (struct aout_link_hash_entry *) NULL)
432333965Sjdp	    {
432433965Sjdp	      h->written = true;
432533965Sjdp	      h->indx = obj_aout_external_sym_count (output_bfd);
432633965Sjdp	    }
432733965Sjdp	  else if ((type & N_TYPE) != N_SETT
432833965Sjdp		   && (type & N_TYPE) != N_SETD
432933965Sjdp		   && (type & N_TYPE) != N_SETB
433033965Sjdp		   && (type & N_TYPE) != N_SETA)
433133965Sjdp	    {
433233965Sjdp	      switch (discard)
433333965Sjdp		{
433433965Sjdp		case discard_none:
433533965Sjdp		  break;
433633965Sjdp		case discard_l:
433733965Sjdp		  if ((type & N_STAB) == 0
433833965Sjdp		      && bfd_is_local_label_name (input_bfd, name))
433933965Sjdp		    skip = true;
434033965Sjdp		  break;
434133965Sjdp		case discard_all:
434233965Sjdp		  skip = true;
434333965Sjdp		  break;
434433965Sjdp		}
434533965Sjdp	      if (skip)
434633965Sjdp		{
434733965Sjdp		  pass = false;
434833965Sjdp		  continue;
434933965Sjdp		}
435033965Sjdp	    }
435133965Sjdp
435233965Sjdp	  /* An N_BINCL symbol indicates the start of the stabs
435333965Sjdp	     entries for a header file.  We need to scan ahead to the
435433965Sjdp	     next N_EINCL symbol, ignoring nesting, adding up all the
435533965Sjdp	     characters in the symbol names, not including the file
435633965Sjdp	     numbers in types (the first number after an open
435733965Sjdp	     parenthesis).  */
435833965Sjdp	  if (type == N_BINCL)
435933965Sjdp	    {
436033965Sjdp	      struct external_nlist *incl_sym;
436133965Sjdp	      int nest;
436233965Sjdp	      struct aout_link_includes_entry *incl_entry;
436333965Sjdp	      struct aout_link_includes_totals *t;
436433965Sjdp
436533965Sjdp	      val = 0;
436633965Sjdp	      nest = 0;
436733965Sjdp	      for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
436833965Sjdp		{
436933965Sjdp		  int incl_type;
437033965Sjdp
437133965Sjdp		  incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
437233965Sjdp		  if (incl_type == N_EINCL)
437333965Sjdp		    {
437433965Sjdp		      if (nest == 0)
437533965Sjdp			break;
437633965Sjdp		      --nest;
437733965Sjdp		    }
437833965Sjdp		  else if (incl_type == N_BINCL)
437933965Sjdp		    ++nest;
438033965Sjdp		  else if (nest == 0)
438133965Sjdp		    {
438233965Sjdp		      const char *s;
438333965Sjdp
438433965Sjdp		      s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
438533965Sjdp		      for (; *s != '\0'; s++)
438633965Sjdp			{
438733965Sjdp			  val += *s;
438833965Sjdp			  if (*s == '(')
438933965Sjdp			    {
439033965Sjdp			      /* Skip the file number.  */
439133965Sjdp			      ++s;
439233965Sjdp			      while (isdigit ((unsigned char) *s))
439333965Sjdp				++s;
439433965Sjdp			      --s;
439533965Sjdp			    }
439633965Sjdp			}
439733965Sjdp		    }
439833965Sjdp		}
439933965Sjdp
440033965Sjdp	      /* If we have already included a header file with the
440133965Sjdp                 same value, then replace this one with an N_EXCL
440233965Sjdp                 symbol.  */
440333965Sjdp	      copy = ! finfo->info->keep_memory;
440433965Sjdp	      incl_entry = aout_link_includes_lookup (&finfo->includes,
440533965Sjdp						      name, true, copy);
440633965Sjdp	      if (incl_entry == NULL)
440733965Sjdp		return false;
440833965Sjdp	      for (t = incl_entry->totals; t != NULL; t = t->next)
440933965Sjdp		if (t->total == val)
441033965Sjdp		  break;
441133965Sjdp	      if (t == NULL)
441233965Sjdp		{
441333965Sjdp		  /* This is the first time we have seen this header
441433965Sjdp                     file with this set of stabs strings.  */
441533965Sjdp		  t = ((struct aout_link_includes_totals *)
441633965Sjdp		       bfd_hash_allocate (&finfo->includes.root,
441733965Sjdp					  sizeof *t));
441833965Sjdp		  if (t == NULL)
441933965Sjdp		    return false;
442033965Sjdp		  t->total = val;
442133965Sjdp		  t->next = incl_entry->totals;
442233965Sjdp		  incl_entry->totals = t;
442333965Sjdp		}
442433965Sjdp	      else
442533965Sjdp		{
442633965Sjdp		  int *incl_map;
442733965Sjdp
442833965Sjdp		  /* This is a duplicate header file.  We must change
442933965Sjdp                     it to be an N_EXCL entry, and mark all the
443033965Sjdp                     included symbols to prevent outputting them.  */
443133965Sjdp		  type = N_EXCL;
443233965Sjdp
443333965Sjdp		  nest = 0;
443433965Sjdp		  for (incl_sym = sym + 1, incl_map = symbol_map + 1;
443533965Sjdp		       incl_sym < sym_end;
443633965Sjdp		       incl_sym++, incl_map++)
443733965Sjdp		    {
443833965Sjdp		      int incl_type;
443933965Sjdp
444033965Sjdp		      incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
444133965Sjdp		      if (incl_type == N_EINCL)
444233965Sjdp			{
444333965Sjdp			  if (nest == 0)
444433965Sjdp			    {
444533965Sjdp			      *incl_map = -1;
444633965Sjdp			      break;
444733965Sjdp			    }
444833965Sjdp			  --nest;
444933965Sjdp			}
445033965Sjdp		      else if (incl_type == N_BINCL)
445133965Sjdp			++nest;
445233965Sjdp		      else if (nest == 0)
445333965Sjdp			*incl_map = -1;
445433965Sjdp		    }
445533965Sjdp		}
445633965Sjdp	    }
445733965Sjdp	}
445833965Sjdp
445933965Sjdp      /* Copy this symbol into the list of symbols we are going to
446033965Sjdp	 write out.  */
446133965Sjdp      bfd_h_put_8 (output_bfd, type, outsym->e_type);
446233965Sjdp      bfd_h_put_8 (output_bfd, bfd_h_get_8 (input_bfd, sym->e_other),
446333965Sjdp		   outsym->e_other);
446433965Sjdp      bfd_h_put_16 (output_bfd, bfd_h_get_16 (input_bfd, sym->e_desc),
446533965Sjdp		    outsym->e_desc);
446633965Sjdp      copy = false;
446733965Sjdp      if (! finfo->info->keep_memory)
446833965Sjdp	{
446933965Sjdp	  /* name points into a string table which we are going to
447033965Sjdp	     free.  If there is a hash table entry, use that string.
447133965Sjdp	     Otherwise, copy name into memory.  */
447233965Sjdp	  if (h != (struct aout_link_hash_entry *) NULL)
447333965Sjdp	    name = h->root.root.string;
447433965Sjdp	  else
447533965Sjdp	    copy = true;
447633965Sjdp	}
447733965Sjdp      strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
447833965Sjdp				       name, copy);
447933965Sjdp      if (strtab_index == (bfd_size_type) -1)
448033965Sjdp	return false;
448133965Sjdp      PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
448233965Sjdp      PUT_WORD (output_bfd, val, outsym->e_value);
448333965Sjdp      *symbol_map = obj_aout_external_sym_count (output_bfd);
448433965Sjdp      ++obj_aout_external_sym_count (output_bfd);
448533965Sjdp      ++outsym;
448633965Sjdp    }
448733965Sjdp
448833965Sjdp  /* Write out the output symbols we have just constructed.  */
448933965Sjdp  if (outsym > finfo->output_syms)
449033965Sjdp    {
449133965Sjdp      bfd_size_type outsym_count;
449233965Sjdp
449333965Sjdp      if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
449433965Sjdp	return false;
449533965Sjdp      outsym_count = outsym - finfo->output_syms;
449633965Sjdp      if (bfd_write ((PTR) finfo->output_syms,
449733965Sjdp		     (bfd_size_type) EXTERNAL_NLIST_SIZE,
449833965Sjdp		     (bfd_size_type) outsym_count, output_bfd)
449933965Sjdp	  != outsym_count * EXTERNAL_NLIST_SIZE)
450033965Sjdp	return false;
450133965Sjdp      finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE;
450233965Sjdp    }
450333965Sjdp
450433965Sjdp  return true;
450533965Sjdp}
450633965Sjdp
450733965Sjdp/* Write out a symbol that was not associated with an a.out input
450833965Sjdp   object.  */
450933965Sjdp
451033965Sjdpstatic boolean
451133965Sjdpaout_link_write_other_symbol (h, data)
451233965Sjdp     struct aout_link_hash_entry *h;
451333965Sjdp     PTR data;
451433965Sjdp{
451533965Sjdp  struct aout_final_link_info *finfo = (struct aout_final_link_info *) data;
451633965Sjdp  bfd *output_bfd;
451733965Sjdp  int type;
451833965Sjdp  bfd_vma val;
451933965Sjdp  struct external_nlist outsym;
452033965Sjdp  bfd_size_type indx;
452133965Sjdp
452233965Sjdp  output_bfd = finfo->output_bfd;
452333965Sjdp
452433965Sjdp  if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
452533965Sjdp    {
452633965Sjdp      if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
452733965Sjdp	     (output_bfd, finfo->info, h)))
452833965Sjdp	{
452933965Sjdp	  /* FIXME: No way to handle errors.  */
453033965Sjdp	  abort ();
453133965Sjdp	}
453233965Sjdp    }
453333965Sjdp
453433965Sjdp  if (h->written)
453533965Sjdp    return true;
453633965Sjdp
453733965Sjdp  h->written = true;
453833965Sjdp
453933965Sjdp  /* An indx of -2 means the symbol must be written.  */
454033965Sjdp  if (h->indx != -2
454133965Sjdp      && (finfo->info->strip == strip_all
454233965Sjdp	  || (finfo->info->strip == strip_some
454333965Sjdp	      && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
454433965Sjdp				  false, false) == NULL)))
454533965Sjdp    return true;
454633965Sjdp
454733965Sjdp  switch (h->root.type)
454833965Sjdp    {
454933965Sjdp    default:
455033965Sjdp      abort ();
455133965Sjdp      /* Avoid variable not initialized warnings.  */
455233965Sjdp      return true;
455333965Sjdp    case bfd_link_hash_new:
455433965Sjdp      /* This can happen for set symbols when sets are not being
455533965Sjdp         built.  */
455633965Sjdp      return true;
455733965Sjdp    case bfd_link_hash_undefined:
455833965Sjdp      type = N_UNDF | N_EXT;
455933965Sjdp      val = 0;
456033965Sjdp      break;
456133965Sjdp    case bfd_link_hash_defined:
456233965Sjdp    case bfd_link_hash_defweak:
456333965Sjdp      {
456433965Sjdp	asection *sec;
456533965Sjdp
456633965Sjdp	sec = h->root.u.def.section->output_section;
456733965Sjdp	BFD_ASSERT (bfd_is_abs_section (sec)
456833965Sjdp		    || sec->owner == output_bfd);
456933965Sjdp	if (sec == obj_textsec (output_bfd))
457033965Sjdp	  type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
457133965Sjdp	else if (sec == obj_datasec (output_bfd))
457233965Sjdp	  type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
457333965Sjdp	else if (sec == obj_bsssec (output_bfd))
457433965Sjdp	  type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
457533965Sjdp	else
457633965Sjdp	  type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
457733965Sjdp	type |= N_EXT;
457833965Sjdp	val = (h->root.u.def.value
457933965Sjdp	       + sec->vma
458033965Sjdp	       + h->root.u.def.section->output_offset);
458133965Sjdp      }
458233965Sjdp      break;
458333965Sjdp    case bfd_link_hash_common:
458433965Sjdp      type = N_UNDF | N_EXT;
458533965Sjdp      val = h->root.u.c.size;
458633965Sjdp      break;
458733965Sjdp    case bfd_link_hash_undefweak:
458833965Sjdp      type = N_WEAKU;
458933965Sjdp      val = 0;
459033965Sjdp    case bfd_link_hash_indirect:
459133965Sjdp    case bfd_link_hash_warning:
459233965Sjdp      /* FIXME: Ignore these for now.  The circumstances under which
459333965Sjdp	 they should be written out are not clear to me.  */
459433965Sjdp      return true;
459533965Sjdp    }
459633965Sjdp
459733965Sjdp  bfd_h_put_8 (output_bfd, type, outsym.e_type);
459833965Sjdp  bfd_h_put_8 (output_bfd, 0, outsym.e_other);
459933965Sjdp  bfd_h_put_16 (output_bfd, 0, outsym.e_desc);
460033965Sjdp  indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string,
460133965Sjdp			   false);
460233965Sjdp  if (indx == (bfd_size_type) -1)
460333965Sjdp    {
460433965Sjdp      /* FIXME: No way to handle errors.  */
460533965Sjdp      abort ();
460633965Sjdp    }
460733965Sjdp  PUT_WORD (output_bfd, indx, outsym.e_strx);
460833965Sjdp  PUT_WORD (output_bfd, val, outsym.e_value);
460933965Sjdp
461033965Sjdp  if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0
461133965Sjdp      || bfd_write ((PTR) &outsym, (bfd_size_type) EXTERNAL_NLIST_SIZE,
461233965Sjdp		    (bfd_size_type) 1, output_bfd) != EXTERNAL_NLIST_SIZE)
461333965Sjdp    {
461433965Sjdp      /* FIXME: No way to handle errors.  */
461533965Sjdp      abort ();
461633965Sjdp    }
461733965Sjdp
461833965Sjdp  finfo->symoff += EXTERNAL_NLIST_SIZE;
461933965Sjdp  h->indx = obj_aout_external_sym_count (output_bfd);
462033965Sjdp  ++obj_aout_external_sym_count (output_bfd);
462133965Sjdp
462233965Sjdp  return true;
462333965Sjdp}
462433965Sjdp
462533965Sjdp/* Link an a.out section into the output file.  */
462633965Sjdp
462733965Sjdpstatic boolean
462833965Sjdpaout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
462933965Sjdp			 rel_size)
463033965Sjdp     struct aout_final_link_info *finfo;
463133965Sjdp     bfd *input_bfd;
463233965Sjdp     asection *input_section;
463333965Sjdp     file_ptr *reloff_ptr;
463433965Sjdp     bfd_size_type rel_size;
463533965Sjdp{
463633965Sjdp  bfd_size_type input_size;
463733965Sjdp  PTR relocs;
463833965Sjdp
463933965Sjdp  /* Get the section contents.  */
464033965Sjdp  input_size = bfd_section_size (input_bfd, input_section);
464133965Sjdp  if (! bfd_get_section_contents (input_bfd, input_section,
464233965Sjdp				  (PTR) finfo->contents,
464333965Sjdp				  (file_ptr) 0, input_size))
464433965Sjdp    return false;
464533965Sjdp
464633965Sjdp  /* Read in the relocs if we haven't already done it.  */
464733965Sjdp  if (aout_section_data (input_section) != NULL
464833965Sjdp      && aout_section_data (input_section)->relocs != NULL)
464933965Sjdp    relocs = aout_section_data (input_section)->relocs;
465033965Sjdp  else
465133965Sjdp    {
465233965Sjdp      relocs = finfo->relocs;
465333965Sjdp      if (rel_size > 0)
465433965Sjdp	{
465533965Sjdp	  if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
465633965Sjdp	      || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size)
465733965Sjdp	    return false;
465833965Sjdp	}
465933965Sjdp    }
466033965Sjdp
466133965Sjdp  /* Relocate the section contents.  */
466233965Sjdp  if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
466333965Sjdp    {
466433965Sjdp      if (! aout_link_input_section_std (finfo, input_bfd, input_section,
466533965Sjdp					 (struct reloc_std_external *) relocs,
466633965Sjdp					 rel_size, finfo->contents))
466733965Sjdp	return false;
466833965Sjdp    }
466933965Sjdp  else
467033965Sjdp    {
467133965Sjdp      if (! aout_link_input_section_ext (finfo, input_bfd, input_section,
467233965Sjdp					 (struct reloc_ext_external *) relocs,
467333965Sjdp					 rel_size, finfo->contents))
467433965Sjdp	return false;
467533965Sjdp    }
467633965Sjdp
467733965Sjdp  /* Write out the section contents.  */
467833965Sjdp  if (! bfd_set_section_contents (finfo->output_bfd,
467933965Sjdp				  input_section->output_section,
468033965Sjdp				  (PTR) finfo->contents,
468133965Sjdp				  input_section->output_offset,
468233965Sjdp				  input_size))
468333965Sjdp    return false;
468433965Sjdp
468533965Sjdp  /* If we are producing relocateable output, the relocs were
468633965Sjdp     modified, and we now write them out.  */
468733965Sjdp  if (finfo->info->relocateable && rel_size > 0)
468833965Sjdp    {
468933965Sjdp      if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
469033965Sjdp	return false;
469133965Sjdp      if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd)
469233965Sjdp	  != rel_size)
469333965Sjdp	return false;
469433965Sjdp      *reloff_ptr += rel_size;
469533965Sjdp
469633965Sjdp      /* Assert that the relocs have not run into the symbols, and
469733965Sjdp	 that if these are the text relocs they have not run into the
469833965Sjdp	 data relocs.  */
469933965Sjdp      BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
470033965Sjdp		  && (reloff_ptr != &finfo->treloff
470133965Sjdp		      || (*reloff_ptr
470233965Sjdp			  <= obj_datasec (finfo->output_bfd)->rel_filepos)));
470333965Sjdp    }
470433965Sjdp
470533965Sjdp  return true;
470633965Sjdp}
470733965Sjdp
470833965Sjdp/* Get the section corresponding to a reloc index.  */
470933965Sjdp
471033965Sjdpstatic INLINE asection *
471133965Sjdpaout_reloc_index_to_section (abfd, indx)
471233965Sjdp     bfd *abfd;
471333965Sjdp     int indx;
471433965Sjdp{
471533965Sjdp  switch (indx & N_TYPE)
471633965Sjdp    {
471733965Sjdp    case N_TEXT:
471833965Sjdp      return obj_textsec (abfd);
471933965Sjdp    case N_DATA:
472033965Sjdp      return obj_datasec (abfd);
472133965Sjdp    case N_BSS:
472233965Sjdp      return obj_bsssec (abfd);
472333965Sjdp    case N_ABS:
472433965Sjdp    case N_UNDF:
472533965Sjdp      return bfd_abs_section_ptr;
472633965Sjdp    default:
472733965Sjdp      abort ();
472833965Sjdp    }
472960484Sobrien  /*NOTREACHED*/
473060484Sobrien  return NULL;
473133965Sjdp}
473233965Sjdp
473333965Sjdp/* Relocate an a.out section using standard a.out relocs.  */
473433965Sjdp
473533965Sjdpstatic boolean
473633965Sjdpaout_link_input_section_std (finfo, input_bfd, input_section, relocs,
473733965Sjdp			     rel_size, contents)
473833965Sjdp     struct aout_final_link_info *finfo;
473933965Sjdp     bfd *input_bfd;
474033965Sjdp     asection *input_section;
474133965Sjdp     struct reloc_std_external *relocs;
474233965Sjdp     bfd_size_type rel_size;
474333965Sjdp     bfd_byte *contents;
474433965Sjdp{
474533965Sjdp  boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
474633965Sjdp					  bfd *, asection *,
474733965Sjdp					  struct aout_link_hash_entry *,
474833965Sjdp					  PTR, bfd_byte *, boolean *,
474933965Sjdp					  bfd_vma *));
475033965Sjdp  bfd *output_bfd;
475133965Sjdp  boolean relocateable;
475233965Sjdp  struct external_nlist *syms;
475333965Sjdp  char *strings;
475433965Sjdp  struct aout_link_hash_entry **sym_hashes;
475533965Sjdp  int *symbol_map;
475633965Sjdp  bfd_size_type reloc_count;
475733965Sjdp  register struct reloc_std_external *rel;
475833965Sjdp  struct reloc_std_external *rel_end;
475933965Sjdp
476033965Sjdp  output_bfd = finfo->output_bfd;
476133965Sjdp  check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
476233965Sjdp
476333965Sjdp  BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE);
476433965Sjdp  BFD_ASSERT (input_bfd->xvec->header_byteorder
476533965Sjdp	      == output_bfd->xvec->header_byteorder);
476633965Sjdp
476733965Sjdp  relocateable = finfo->info->relocateable;
476833965Sjdp  syms = obj_aout_external_syms (input_bfd);
476933965Sjdp  strings = obj_aout_external_strings (input_bfd);
477033965Sjdp  sym_hashes = obj_aout_sym_hashes (input_bfd);
477133965Sjdp  symbol_map = finfo->symbol_map;
477233965Sjdp
477333965Sjdp  reloc_count = rel_size / RELOC_STD_SIZE;
477433965Sjdp  rel = relocs;
477533965Sjdp  rel_end = rel + reloc_count;
477633965Sjdp  for (; rel < rel_end; rel++)
477733965Sjdp    {
477833965Sjdp      bfd_vma r_addr;
477933965Sjdp      int r_index;
478033965Sjdp      int r_extern;
478133965Sjdp      int r_pcrel;
478233965Sjdp      int r_baserel = 0;
478333965Sjdp      reloc_howto_type *howto;
478433965Sjdp      struct aout_link_hash_entry *h = NULL;
478533965Sjdp      bfd_vma relocation;
478633965Sjdp      bfd_reloc_status_type r;
478733965Sjdp
478833965Sjdp      r_addr = GET_SWORD (input_bfd, rel->r_address);
478933965Sjdp
479033965Sjdp#ifdef MY_reloc_howto
479133965Sjdp      howto = MY_reloc_howto(input_bfd, rel, r_index, r_extern, r_pcrel);
479233965Sjdp#else
479333965Sjdp      {
479433965Sjdp	int r_jmptable;
479533965Sjdp	int r_relative;
479633965Sjdp	int r_length;
479733965Sjdp	unsigned int howto_idx;
479833965Sjdp
479933965Sjdp	if (bfd_header_big_endian (input_bfd))
480033965Sjdp	  {
480133965Sjdp	    r_index   =  ((rel->r_index[0] << 16)
480233965Sjdp			  | (rel->r_index[1] << 8)
480333965Sjdp			  | rel->r_index[2]);
480433965Sjdp	    r_extern  = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
480533965Sjdp	    r_pcrel   = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
480633965Sjdp	    r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
480733965Sjdp	    r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
480833965Sjdp	    r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
480933965Sjdp	    r_length  = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
481033965Sjdp			 >> RELOC_STD_BITS_LENGTH_SH_BIG);
481133965Sjdp	  }
481233965Sjdp	else
481333965Sjdp	  {
481433965Sjdp	    r_index   = ((rel->r_index[2] << 16)
481533965Sjdp			 | (rel->r_index[1] << 8)
481633965Sjdp			 | rel->r_index[0]);
481733965Sjdp	    r_extern  = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
481833965Sjdp	    r_pcrel   = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
481933965Sjdp	    r_baserel = (0 != (rel->r_type[0]
482033965Sjdp			       & RELOC_STD_BITS_BASEREL_LITTLE));
482133965Sjdp	    r_jmptable= (0 != (rel->r_type[0]
482233965Sjdp			       & RELOC_STD_BITS_JMPTABLE_LITTLE));
482333965Sjdp	    r_relative= (0 != (rel->r_type[0]
482433965Sjdp			       & RELOC_STD_BITS_RELATIVE_LITTLE));
482533965Sjdp	    r_length  = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
482633965Sjdp			 >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
482733965Sjdp	  }
482833965Sjdp
482933965Sjdp	howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel
483033965Sjdp		     + 16 * r_jmptable + 32 * r_relative);
483133965Sjdp	BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_std));
483233965Sjdp	howto = howto_table_std + howto_idx;
483333965Sjdp      }
483433965Sjdp#endif
483533965Sjdp
483633965Sjdp      if (relocateable)
483733965Sjdp	{
483833965Sjdp	  /* We are generating a relocateable output file, and must
483933965Sjdp	     modify the reloc accordingly.  */
484033965Sjdp	  if (r_extern)
484133965Sjdp	    {
484233965Sjdp	      /* If we know the symbol this relocation is against,
484333965Sjdp		 convert it into a relocation against a section.  This
484433965Sjdp		 is what the native linker does.  */
484533965Sjdp	      h = sym_hashes[r_index];
484633965Sjdp	      if (h != (struct aout_link_hash_entry *) NULL
484733965Sjdp		  && (h->root.type == bfd_link_hash_defined
484833965Sjdp		      || h->root.type == bfd_link_hash_defweak))
484933965Sjdp		{
485033965Sjdp		  asection *output_section;
485133965Sjdp
485233965Sjdp		  /* Change the r_extern value.  */
485333965Sjdp		  if (bfd_header_big_endian (output_bfd))
485433965Sjdp		    rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG;
485533965Sjdp		  else
485633965Sjdp		    rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE;
485733965Sjdp
485833965Sjdp		  /* Compute a new r_index.  */
485933965Sjdp		  output_section = h->root.u.def.section->output_section;
486033965Sjdp		  if (output_section == obj_textsec (output_bfd))
486133965Sjdp		    r_index = N_TEXT;
486233965Sjdp		  else if (output_section == obj_datasec (output_bfd))
486333965Sjdp		    r_index = N_DATA;
486433965Sjdp		  else if (output_section == obj_bsssec (output_bfd))
486533965Sjdp		    r_index = N_BSS;
486633965Sjdp		  else
486733965Sjdp		    r_index = N_ABS;
486833965Sjdp
486933965Sjdp		  /* Add the symbol value and the section VMA to the
487033965Sjdp		     addend stored in the contents.  */
487133965Sjdp		  relocation = (h->root.u.def.value
487233965Sjdp				+ output_section->vma
487333965Sjdp				+ h->root.u.def.section->output_offset);
487433965Sjdp		}
487533965Sjdp	      else
487633965Sjdp		{
487733965Sjdp		  /* We must change r_index according to the symbol
487833965Sjdp		     map.  */
487933965Sjdp		  r_index = symbol_map[r_index];
488033965Sjdp
488133965Sjdp		  if (r_index == -1)
488233965Sjdp		    {
488333965Sjdp		      if (h != NULL)
488433965Sjdp			{
488533965Sjdp			  /* We decided to strip this symbol, but it
488633965Sjdp                             turns out that we can't.  Note that we
488733965Sjdp                             lose the other and desc information here.
488833965Sjdp                             I don't think that will ever matter for a
488933965Sjdp                             global symbol.  */
489033965Sjdp			  if (h->indx < 0)
489133965Sjdp			    {
489233965Sjdp			      h->indx = -2;
489333965Sjdp			      h->written = false;
489433965Sjdp			      if (! aout_link_write_other_symbol (h,
489533965Sjdp								  (PTR) finfo))
489633965Sjdp				return false;
489733965Sjdp			    }
489833965Sjdp			  r_index = h->indx;
489933965Sjdp			}
490033965Sjdp		      else
490133965Sjdp			{
490233965Sjdp			  const char *name;
490333965Sjdp
490433965Sjdp			  name = strings + GET_WORD (input_bfd,
490533965Sjdp						     syms[r_index].e_strx);
490633965Sjdp			  if (! ((*finfo->info->callbacks->unattached_reloc)
490733965Sjdp				 (finfo->info, name, input_bfd, input_section,
490833965Sjdp				  r_addr)))
490933965Sjdp			    return false;
491033965Sjdp			  r_index = 0;
491133965Sjdp			}
491233965Sjdp		    }
491333965Sjdp
491433965Sjdp		  relocation = 0;
491533965Sjdp		}
491633965Sjdp
491733965Sjdp	      /* Write out the new r_index value.  */
491833965Sjdp	      if (bfd_header_big_endian (output_bfd))
491933965Sjdp		{
492033965Sjdp		  rel->r_index[0] = r_index >> 16;
492133965Sjdp		  rel->r_index[1] = r_index >> 8;
492233965Sjdp		  rel->r_index[2] = r_index;
492333965Sjdp		}
492433965Sjdp	      else
492533965Sjdp		{
492633965Sjdp		  rel->r_index[2] = r_index >> 16;
492733965Sjdp		  rel->r_index[1] = r_index >> 8;
492833965Sjdp		  rel->r_index[0] = r_index;
492933965Sjdp		}
493033965Sjdp	    }
493133965Sjdp	  else
493233965Sjdp	    {
493333965Sjdp	      asection *section;
493433965Sjdp
493533965Sjdp	      /* This is a relocation against a section.  We must
493633965Sjdp		 adjust by the amount that the section moved.  */
493733965Sjdp	      section = aout_reloc_index_to_section (input_bfd, r_index);
493833965Sjdp	      relocation = (section->output_section->vma
493933965Sjdp			    + section->output_offset
494033965Sjdp			    - section->vma);
494133965Sjdp	    }
494233965Sjdp
494333965Sjdp	  /* Change the address of the relocation.  */
494433965Sjdp	  PUT_WORD (output_bfd,
494533965Sjdp		    r_addr + input_section->output_offset,
494633965Sjdp		    rel->r_address);
494733965Sjdp
494833965Sjdp	  /* Adjust a PC relative relocation by removing the reference
494933965Sjdp	     to the original address in the section and including the
495033965Sjdp	     reference to the new address.  */
495133965Sjdp	  if (r_pcrel)
495233965Sjdp	    relocation -= (input_section->output_section->vma
495333965Sjdp			   + input_section->output_offset
495433965Sjdp			   - input_section->vma);
495533965Sjdp
495633965Sjdp#ifdef MY_relocatable_reloc
495733965Sjdp	  MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr);
495833965Sjdp#endif
495933965Sjdp
496033965Sjdp	  if (relocation == 0)
496133965Sjdp	    r = bfd_reloc_ok;
496233965Sjdp	  else
496333965Sjdp	    r = MY_relocate_contents (howto,
496433965Sjdp					input_bfd, relocation,
496533965Sjdp					contents + r_addr);
496633965Sjdp	}
496733965Sjdp      else
496833965Sjdp	{
496933965Sjdp	  boolean hundef;
497033965Sjdp
497133965Sjdp	  /* We are generating an executable, and must do a full
497233965Sjdp	     relocation.  */
497333965Sjdp	  hundef = false;
497460484Sobrien
497533965Sjdp	  if (r_extern)
497633965Sjdp	    {
497733965Sjdp	      h = sym_hashes[r_index];
497833965Sjdp
497933965Sjdp	      if (h != (struct aout_link_hash_entry *) NULL
498033965Sjdp		  && (h->root.type == bfd_link_hash_defined
498133965Sjdp		      || h->root.type == bfd_link_hash_defweak))
498233965Sjdp		{
498333965Sjdp		  relocation = (h->root.u.def.value
498433965Sjdp				+ h->root.u.def.section->output_section->vma
498533965Sjdp				+ h->root.u.def.section->output_offset);
498633965Sjdp		}
498733965Sjdp	      else if (h != (struct aout_link_hash_entry *) NULL
498833965Sjdp		       && h->root.type == bfd_link_hash_undefweak)
498933965Sjdp		relocation = 0;
499033965Sjdp	      else
499133965Sjdp		{
499233965Sjdp		  hundef = true;
499333965Sjdp		  relocation = 0;
499433965Sjdp		}
499533965Sjdp	    }
499633965Sjdp	  else
499733965Sjdp	    {
499833965Sjdp	      asection *section;
499933965Sjdp
500033965Sjdp	      section = aout_reloc_index_to_section (input_bfd, r_index);
500133965Sjdp	      relocation = (section->output_section->vma
500233965Sjdp			    + section->output_offset
500333965Sjdp			    - section->vma);
500433965Sjdp	      if (r_pcrel)
500533965Sjdp		relocation += input_section->vma;
500633965Sjdp	    }
500733965Sjdp
500833965Sjdp	  if (check_dynamic_reloc != NULL)
500933965Sjdp	    {
501033965Sjdp	      boolean skip;
501133965Sjdp
501233965Sjdp	      if (! ((*check_dynamic_reloc)
501333965Sjdp		     (finfo->info, input_bfd, input_section, h,
501433965Sjdp		      (PTR) rel, contents, &skip, &relocation)))
501533965Sjdp		return false;
501633965Sjdp	      if (skip)
501733965Sjdp		continue;
501833965Sjdp	    }
501933965Sjdp
502033965Sjdp	  /* Now warn if a global symbol is undefined.  We could not
502133965Sjdp             do this earlier, because check_dynamic_reloc might want
502233965Sjdp             to skip this reloc.  */
502333965Sjdp	  if (hundef && ! finfo->info->shared && ! r_baserel)
502433965Sjdp	    {
502533965Sjdp	      const char *name;
502633965Sjdp
502733965Sjdp	      if (h != NULL)
502833965Sjdp		name = h->root.root.string;
502933965Sjdp	      else
503033965Sjdp		name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
503133965Sjdp	      if (! ((*finfo->info->callbacks->undefined_symbol)
503260484Sobrien		     (finfo->info, name, input_bfd, input_section,
503360484Sobrien		     r_addr, true)))
503433965Sjdp		return false;
503533965Sjdp	    }
503633965Sjdp
503733965Sjdp	  r = MY_final_link_relocate (howto,
503833965Sjdp				      input_bfd, input_section,
503933965Sjdp				      contents, r_addr, relocation,
504033965Sjdp				      (bfd_vma) 0);
504133965Sjdp	}
504233965Sjdp
504333965Sjdp      if (r != bfd_reloc_ok)
504433965Sjdp	{
504533965Sjdp	  switch (r)
504633965Sjdp	    {
504733965Sjdp	    default:
504833965Sjdp	    case bfd_reloc_outofrange:
504933965Sjdp	      abort ();
505033965Sjdp	    case bfd_reloc_overflow:
505133965Sjdp	      {
505233965Sjdp		const char *name;
505333965Sjdp
505433965Sjdp		if (h != NULL)
505533965Sjdp		  name = h->root.root.string;
505633965Sjdp		else if (r_extern)
505733965Sjdp		  name = strings + GET_WORD (input_bfd,
505833965Sjdp					     syms[r_index].e_strx);
505933965Sjdp		else
506033965Sjdp		  {
506133965Sjdp		    asection *s;
506233965Sjdp
506333965Sjdp		    s = aout_reloc_index_to_section (input_bfd, r_index);
506433965Sjdp		    name = bfd_section_name (input_bfd, s);
506533965Sjdp		  }
506633965Sjdp		if (! ((*finfo->info->callbacks->reloc_overflow)
506733965Sjdp		       (finfo->info, name, howto->name,
506833965Sjdp			(bfd_vma) 0, input_bfd, input_section, r_addr)))
506933965Sjdp		  return false;
507033965Sjdp	      }
507133965Sjdp	      break;
507233965Sjdp	    }
507333965Sjdp	}
507433965Sjdp    }
507533965Sjdp
507633965Sjdp  return true;
507733965Sjdp}
507833965Sjdp
507933965Sjdp/* Relocate an a.out section using extended a.out relocs.  */
508033965Sjdp
508133965Sjdpstatic boolean
508233965Sjdpaout_link_input_section_ext (finfo, input_bfd, input_section, relocs,
508333965Sjdp			     rel_size, contents)
508433965Sjdp     struct aout_final_link_info *finfo;
508533965Sjdp     bfd *input_bfd;
508633965Sjdp     asection *input_section;
508733965Sjdp     struct reloc_ext_external *relocs;
508833965Sjdp     bfd_size_type rel_size;
508933965Sjdp     bfd_byte *contents;
509033965Sjdp{
509133965Sjdp  boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
509233965Sjdp					  bfd *, asection *,
509333965Sjdp					  struct aout_link_hash_entry *,
509433965Sjdp					  PTR, bfd_byte *, boolean *,
509533965Sjdp					  bfd_vma *));
509633965Sjdp  bfd *output_bfd;
509733965Sjdp  boolean relocateable;
509833965Sjdp  struct external_nlist *syms;
509933965Sjdp  char *strings;
510033965Sjdp  struct aout_link_hash_entry **sym_hashes;
510133965Sjdp  int *symbol_map;
510233965Sjdp  bfd_size_type reloc_count;
510333965Sjdp  register struct reloc_ext_external *rel;
510433965Sjdp  struct reloc_ext_external *rel_end;
510533965Sjdp
510633965Sjdp  output_bfd = finfo->output_bfd;
510733965Sjdp  check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
510833965Sjdp
510933965Sjdp  BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE);
511033965Sjdp  BFD_ASSERT (input_bfd->xvec->header_byteorder
511133965Sjdp	      == output_bfd->xvec->header_byteorder);
511233965Sjdp
511333965Sjdp  relocateable = finfo->info->relocateable;
511433965Sjdp  syms = obj_aout_external_syms (input_bfd);
511533965Sjdp  strings = obj_aout_external_strings (input_bfd);
511633965Sjdp  sym_hashes = obj_aout_sym_hashes (input_bfd);
511733965Sjdp  symbol_map = finfo->symbol_map;
511833965Sjdp
511933965Sjdp  reloc_count = rel_size / RELOC_EXT_SIZE;
512033965Sjdp  rel = relocs;
512133965Sjdp  rel_end = rel + reloc_count;
512233965Sjdp  for (; rel < rel_end; rel++)
512333965Sjdp    {
512433965Sjdp      bfd_vma r_addr;
512533965Sjdp      int r_index;
512633965Sjdp      int r_extern;
512733965Sjdp      unsigned int r_type;
512833965Sjdp      bfd_vma r_addend;
512933965Sjdp      struct aout_link_hash_entry *h = NULL;
513033965Sjdp      asection *r_section = NULL;
513133965Sjdp      bfd_vma relocation;
513233965Sjdp
513333965Sjdp      r_addr = GET_SWORD (input_bfd, rel->r_address);
513433965Sjdp
513533965Sjdp      if (bfd_header_big_endian (input_bfd))
513633965Sjdp	{
513733965Sjdp	  r_index  = ((rel->r_index[0] << 16)
513833965Sjdp		      | (rel->r_index[1] << 8)
513933965Sjdp		      | rel->r_index[2]);
514033965Sjdp	  r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
514133965Sjdp	  r_type   = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
514233965Sjdp		      >> RELOC_EXT_BITS_TYPE_SH_BIG);
514333965Sjdp	}
514433965Sjdp      else
514533965Sjdp	{
514633965Sjdp	  r_index  = ((rel->r_index[2] << 16)
514733965Sjdp		      | (rel->r_index[1] << 8)
514833965Sjdp		      | rel->r_index[0]);
514933965Sjdp	  r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
515033965Sjdp	  r_type   = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
515133965Sjdp		      >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
515233965Sjdp	}
515333965Sjdp
515433965Sjdp      r_addend = GET_SWORD (input_bfd, rel->r_addend);
515533965Sjdp
515633965Sjdp      BFD_ASSERT (r_type < TABLE_SIZE (howto_table_ext));
515733965Sjdp
515833965Sjdp      if (relocateable)
515933965Sjdp	{
516033965Sjdp	  /* We are generating a relocateable output file, and must
516133965Sjdp	     modify the reloc accordingly.  */
516233965Sjdp	  if (r_extern
516333965Sjdp	      || r_type == RELOC_BASE10
516433965Sjdp	      || r_type == RELOC_BASE13
516533965Sjdp	      || r_type == RELOC_BASE22)
516633965Sjdp	    {
516733965Sjdp	      /* If we know the symbol this relocation is against,
516833965Sjdp		 convert it into a relocation against a section.  This
516933965Sjdp		 is what the native linker does.  */
517033965Sjdp	      if (r_type == RELOC_BASE10
517133965Sjdp		  || r_type == RELOC_BASE13
517233965Sjdp		  || r_type == RELOC_BASE22)
517333965Sjdp		h = NULL;
517433965Sjdp	      else
517533965Sjdp		h = sym_hashes[r_index];
517633965Sjdp	      if (h != (struct aout_link_hash_entry *) NULL
517733965Sjdp		  && (h->root.type == bfd_link_hash_defined
517833965Sjdp		      || h->root.type == bfd_link_hash_defweak))
517933965Sjdp		{
518033965Sjdp		  asection *output_section;
518133965Sjdp
518233965Sjdp		  /* Change the r_extern value.  */
518333965Sjdp		  if (bfd_header_big_endian (output_bfd))
518433965Sjdp		    rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG;
518533965Sjdp		  else
518633965Sjdp		    rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE;
518733965Sjdp
518833965Sjdp		  /* Compute a new r_index.  */
518933965Sjdp		  output_section = h->root.u.def.section->output_section;
519033965Sjdp		  if (output_section == obj_textsec (output_bfd))
519133965Sjdp		    r_index = N_TEXT;
519233965Sjdp		  else if (output_section == obj_datasec (output_bfd))
519333965Sjdp		    r_index = N_DATA;
519433965Sjdp		  else if (output_section == obj_bsssec (output_bfd))
519533965Sjdp		    r_index = N_BSS;
519633965Sjdp		  else
519733965Sjdp		    r_index = N_ABS;
519833965Sjdp
519933965Sjdp		  /* Add the symbol value and the section VMA to the
520033965Sjdp		     addend.  */
520133965Sjdp		  relocation = (h->root.u.def.value
520233965Sjdp				+ output_section->vma
520333965Sjdp				+ h->root.u.def.section->output_offset);
520433965Sjdp
520533965Sjdp		  /* Now RELOCATION is the VMA of the final
520633965Sjdp		     destination.  If this is a PC relative reloc,
520733965Sjdp		     then ADDEND is the negative of the source VMA.
520833965Sjdp		     We want to set ADDEND to the difference between
520933965Sjdp		     the destination VMA and the source VMA, which
521033965Sjdp		     means we must adjust RELOCATION by the change in
521133965Sjdp		     the source VMA.  This is done below.  */
521233965Sjdp		}
521333965Sjdp	      else
521433965Sjdp		{
521533965Sjdp		  /* We must change r_index according to the symbol
521633965Sjdp		     map.  */
521733965Sjdp		  r_index = symbol_map[r_index];
521833965Sjdp
521933965Sjdp		  if (r_index == -1)
522033965Sjdp		    {
522133965Sjdp		      if (h != NULL)
522233965Sjdp			{
522333965Sjdp			  /* We decided to strip this symbol, but it
522433965Sjdp                             turns out that we can't.  Note that we
522533965Sjdp                             lose the other and desc information here.
522633965Sjdp                             I don't think that will ever matter for a
522733965Sjdp                             global symbol.  */
522833965Sjdp			  if (h->indx < 0)
522933965Sjdp			    {
523033965Sjdp			      h->indx = -2;
523133965Sjdp			      h->written = false;
523233965Sjdp			      if (! aout_link_write_other_symbol (h,
523333965Sjdp								  (PTR) finfo))
523433965Sjdp				return false;
523533965Sjdp			    }
523633965Sjdp			  r_index = h->indx;
523733965Sjdp			}
523833965Sjdp		      else
523933965Sjdp			{
524033965Sjdp			  const char *name;
524133965Sjdp
524233965Sjdp			  name = strings + GET_WORD (input_bfd,
524333965Sjdp						     syms[r_index].e_strx);
524433965Sjdp			  if (! ((*finfo->info->callbacks->unattached_reloc)
524533965Sjdp				 (finfo->info, name, input_bfd, input_section,
524633965Sjdp				  r_addr)))
524733965Sjdp			    return false;
524833965Sjdp			  r_index = 0;
524933965Sjdp			}
525033965Sjdp		    }
525133965Sjdp
525233965Sjdp		  relocation = 0;
525333965Sjdp
525433965Sjdp		  /* If this is a PC relative reloc, then the addend
525533965Sjdp		     is the negative of the source VMA.  We must
525633965Sjdp		     adjust it by the change in the source VMA.  This
525733965Sjdp		     is done below.  */
525833965Sjdp		}
525933965Sjdp
526033965Sjdp	      /* Write out the new r_index value.  */
526133965Sjdp	      if (bfd_header_big_endian (output_bfd))
526233965Sjdp		{
526333965Sjdp		  rel->r_index[0] = r_index >> 16;
526433965Sjdp		  rel->r_index[1] = r_index >> 8;
526533965Sjdp		  rel->r_index[2] = r_index;
526633965Sjdp		}
526733965Sjdp	      else
526833965Sjdp		{
526933965Sjdp		  rel->r_index[2] = r_index >> 16;
527033965Sjdp		  rel->r_index[1] = r_index >> 8;
527133965Sjdp		  rel->r_index[0] = r_index;
527233965Sjdp		}
527333965Sjdp	    }
527433965Sjdp	  else
527533965Sjdp	    {
527633965Sjdp	      /* This is a relocation against a section.  We must
527733965Sjdp		 adjust by the amount that the section moved.  */
527833965Sjdp	      r_section = aout_reloc_index_to_section (input_bfd, r_index);
527933965Sjdp	      relocation = (r_section->output_section->vma
528033965Sjdp			    + r_section->output_offset
528133965Sjdp			    - r_section->vma);
528233965Sjdp
528333965Sjdp	      /* If this is a PC relative reloc, then the addend is
528433965Sjdp		 the difference in VMA between the destination and the
528533965Sjdp		 source.  We have just adjusted for the change in VMA
528633965Sjdp		 of the destination, so we must also adjust by the
528733965Sjdp		 change in VMA of the source.  This is done below.  */
528833965Sjdp	    }
528933965Sjdp
529033965Sjdp	  /* As described above, we must always adjust a PC relative
529133965Sjdp	     reloc by the change in VMA of the source.  However, if
529233965Sjdp	     pcrel_offset is set, then the addend does not include the
529333965Sjdp	     location within the section, in which case we don't need
529433965Sjdp	     to adjust anything.  */
529533965Sjdp	  if (howto_table_ext[r_type].pc_relative
529633965Sjdp	      && ! howto_table_ext[r_type].pcrel_offset)
529733965Sjdp	    relocation -= (input_section->output_section->vma
529833965Sjdp			   + input_section->output_offset
529933965Sjdp			   - input_section->vma);
530033965Sjdp
530133965Sjdp	  /* Change the addend if necessary.  */
530233965Sjdp	  if (relocation != 0)
530333965Sjdp	    PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend);
530433965Sjdp
530533965Sjdp	  /* Change the address of the relocation.  */
530633965Sjdp	  PUT_WORD (output_bfd,
530733965Sjdp		    r_addr + input_section->output_offset,
530833965Sjdp		    rel->r_address);
530933965Sjdp	}
531033965Sjdp      else
531133965Sjdp	{
531233965Sjdp	  boolean hundef;
531333965Sjdp	  bfd_reloc_status_type r;
531433965Sjdp
531533965Sjdp	  /* We are generating an executable, and must do a full
531633965Sjdp	     relocation.  */
531733965Sjdp	  hundef = false;
531860484Sobrien
531933965Sjdp	  if (r_extern)
532033965Sjdp	    {
532133965Sjdp	      h = sym_hashes[r_index];
532233965Sjdp
532333965Sjdp	      if (h != (struct aout_link_hash_entry *) NULL
532433965Sjdp		  && (h->root.type == bfd_link_hash_defined
532533965Sjdp		      || h->root.type == bfd_link_hash_defweak))
532633965Sjdp		{
532733965Sjdp		  relocation = (h->root.u.def.value
532833965Sjdp				+ h->root.u.def.section->output_section->vma
532933965Sjdp				+ h->root.u.def.section->output_offset);
533033965Sjdp		}
533133965Sjdp	      else if (h != (struct aout_link_hash_entry *) NULL
533233965Sjdp		       && h->root.type == bfd_link_hash_undefweak)
533333965Sjdp		relocation = 0;
533433965Sjdp	      else
533533965Sjdp		{
533633965Sjdp		  hundef = true;
533733965Sjdp		  relocation = 0;
533833965Sjdp		}
533933965Sjdp	    }
534033965Sjdp	  else if (r_type == RELOC_BASE10
534133965Sjdp		   || r_type == RELOC_BASE13
534233965Sjdp		   || r_type == RELOC_BASE22)
534333965Sjdp	    {
534433965Sjdp	      struct external_nlist *sym;
534533965Sjdp	      int type;
534633965Sjdp
534733965Sjdp	      /* For base relative relocs, r_index is always an index
534833965Sjdp                 into the symbol table, even if r_extern is 0.  */
534933965Sjdp	      sym = syms + r_index;
535033965Sjdp	      type = bfd_h_get_8 (input_bfd, sym->e_type);
535133965Sjdp	      if ((type & N_TYPE) == N_TEXT
535233965Sjdp		  || type == N_WEAKT)
535333965Sjdp		r_section = obj_textsec (input_bfd);
535433965Sjdp	      else if ((type & N_TYPE) == N_DATA
535533965Sjdp		       || type == N_WEAKD)
535633965Sjdp		r_section = obj_datasec (input_bfd);
535733965Sjdp	      else if ((type & N_TYPE) == N_BSS
535833965Sjdp		       || type == N_WEAKB)
535933965Sjdp		r_section = obj_bsssec (input_bfd);
536033965Sjdp	      else if ((type & N_TYPE) == N_ABS
536133965Sjdp		       || type == N_WEAKA)
536233965Sjdp		r_section = bfd_abs_section_ptr;
536333965Sjdp	      else
536433965Sjdp		abort ();
536533965Sjdp	      relocation = (r_section->output_section->vma
536633965Sjdp			    + r_section->output_offset
536733965Sjdp			    + (GET_WORD (input_bfd, sym->e_value)
536833965Sjdp			       - r_section->vma));
536933965Sjdp	    }
537033965Sjdp	  else
537133965Sjdp	    {
537233965Sjdp	      r_section = aout_reloc_index_to_section (input_bfd, r_index);
537333965Sjdp
537433965Sjdp	      /* If this is a PC relative reloc, then R_ADDEND is the
537533965Sjdp		 difference between the two vmas, or
537633965Sjdp		   old_dest_sec + old_dest_off - (old_src_sec + old_src_off)
537733965Sjdp		 where
537833965Sjdp		   old_dest_sec == section->vma
537933965Sjdp		 and
538033965Sjdp		   old_src_sec == input_section->vma
538133965Sjdp		 and
538233965Sjdp		   old_src_off == r_addr
538333965Sjdp
538433965Sjdp		 _bfd_final_link_relocate expects RELOCATION +
538533965Sjdp		 R_ADDEND to be the VMA of the destination minus
538633965Sjdp		 r_addr (the minus r_addr is because this relocation
538733965Sjdp		 is not pcrel_offset, which is a bit confusing and
538833965Sjdp		 should, perhaps, be changed), or
538933965Sjdp		   new_dest_sec
539033965Sjdp		 where
539133965Sjdp		   new_dest_sec == output_section->vma + output_offset
539233965Sjdp		 We arrange for this to happen by setting RELOCATION to
539333965Sjdp		   new_dest_sec + old_src_sec - old_dest_sec
539433965Sjdp
539533965Sjdp		 If this is not a PC relative reloc, then R_ADDEND is
539633965Sjdp		 simply the VMA of the destination, so we set
539733965Sjdp		 RELOCATION to the change in the destination VMA, or
539833965Sjdp		   new_dest_sec - old_dest_sec
539933965Sjdp		 */
540033965Sjdp	      relocation = (r_section->output_section->vma
540133965Sjdp			    + r_section->output_offset
540233965Sjdp			    - r_section->vma);
540333965Sjdp	      if (howto_table_ext[r_type].pc_relative)
540433965Sjdp		relocation += input_section->vma;
540533965Sjdp	    }
540633965Sjdp
540733965Sjdp	  if (check_dynamic_reloc != NULL)
540833965Sjdp	    {
540933965Sjdp	      boolean skip;
541033965Sjdp
541133965Sjdp	      if (! ((*check_dynamic_reloc)
541233965Sjdp		     (finfo->info, input_bfd, input_section, h,
541333965Sjdp		      (PTR) rel, contents, &skip, &relocation)))
541433965Sjdp		return false;
541533965Sjdp	      if (skip)
541633965Sjdp		continue;
541733965Sjdp	    }
541833965Sjdp
541933965Sjdp	  /* Now warn if a global symbol is undefined.  We could not
542033965Sjdp             do this earlier, because check_dynamic_reloc might want
542133965Sjdp             to skip this reloc.  */
542233965Sjdp	  if (hundef
542333965Sjdp	      && ! finfo->info->shared
542433965Sjdp	      && r_type != RELOC_BASE10
542533965Sjdp	      && r_type != RELOC_BASE13
542633965Sjdp	      && r_type != RELOC_BASE22)
542733965Sjdp	    {
542833965Sjdp	      const char *name;
542933965Sjdp
543033965Sjdp	      if (h != NULL)
543133965Sjdp		name = h->root.root.string;
543233965Sjdp	      else
543333965Sjdp		name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
543433965Sjdp	      if (! ((*finfo->info->callbacks->undefined_symbol)
543560484Sobrien		     (finfo->info, name, input_bfd, input_section,
543660484Sobrien		     r_addr, true)))
543733965Sjdp		return false;
543833965Sjdp	    }
543933965Sjdp
544060484Sobrien	  if (r_type != RELOC_SPARC_REV32)
544160484Sobrien	    r = MY_final_link_relocate (howto_table_ext + r_type,
544260484Sobrien					input_bfd, input_section,
544360484Sobrien					contents, r_addr, relocation,
544460484Sobrien					r_addend);
544560484Sobrien	  else
544660484Sobrien	    {
544760484Sobrien	      bfd_vma x;
544860484Sobrien
544960484Sobrien	      x = bfd_get_32 (input_bfd, contents + r_addr);
545060484Sobrien	      x = x + relocation + r_addend;
545160484Sobrien	      bfd_putl32 (/*input_bfd,*/ x, contents + r_addr);
545260484Sobrien	      r = bfd_reloc_ok;
545360484Sobrien	    }
545460484Sobrien
545533965Sjdp	  if (r != bfd_reloc_ok)
545633965Sjdp	    {
545733965Sjdp	      switch (r)
545833965Sjdp		{
545933965Sjdp		default:
546033965Sjdp		case bfd_reloc_outofrange:
546133965Sjdp		  abort ();
546233965Sjdp		case bfd_reloc_overflow:
546333965Sjdp		  {
546433965Sjdp		    const char *name;
546533965Sjdp
546633965Sjdp		    if (h != NULL)
546733965Sjdp		      name = h->root.root.string;
546833965Sjdp		    else if (r_extern
546933965Sjdp			     || r_type == RELOC_BASE10
547033965Sjdp			     || r_type == RELOC_BASE13
547133965Sjdp			     || r_type == RELOC_BASE22)
547233965Sjdp		      name = strings + GET_WORD (input_bfd,
547333965Sjdp						 syms[r_index].e_strx);
547433965Sjdp		    else
547533965Sjdp		      {
547633965Sjdp			asection *s;
547733965Sjdp
547833965Sjdp			s = aout_reloc_index_to_section (input_bfd, r_index);
547933965Sjdp			name = bfd_section_name (input_bfd, s);
548033965Sjdp		      }
548133965Sjdp		    if (! ((*finfo->info->callbacks->reloc_overflow)
548233965Sjdp			   (finfo->info, name, howto_table_ext[r_type].name,
548333965Sjdp			    r_addend, input_bfd, input_section, r_addr)))
548433965Sjdp		      return false;
548533965Sjdp		  }
548633965Sjdp		  break;
548733965Sjdp		}
548833965Sjdp	    }
548933965Sjdp	}
549033965Sjdp    }
549133965Sjdp
549233965Sjdp  return true;
549333965Sjdp}
549433965Sjdp
549533965Sjdp/* Handle a link order which is supposed to generate a reloc.  */
549633965Sjdp
549733965Sjdpstatic boolean
549833965Sjdpaout_link_reloc_link_order (finfo, o, p)
549933965Sjdp     struct aout_final_link_info *finfo;
550033965Sjdp     asection *o;
550133965Sjdp     struct bfd_link_order *p;
550233965Sjdp{
550333965Sjdp  struct bfd_link_order_reloc *pr;
550433965Sjdp  int r_index;
550533965Sjdp  int r_extern;
550633965Sjdp  reloc_howto_type *howto;
550760484Sobrien  file_ptr *reloff_ptr = NULL;
550833965Sjdp  struct reloc_std_external srel;
550933965Sjdp  struct reloc_ext_external erel;
551033965Sjdp  PTR rel_ptr;
551133965Sjdp
551233965Sjdp  pr = p->u.reloc.p;
551333965Sjdp
551433965Sjdp  if (p->type == bfd_section_reloc_link_order)
551533965Sjdp    {
551633965Sjdp      r_extern = 0;
551733965Sjdp      if (bfd_is_abs_section (pr->u.section))
551833965Sjdp	r_index = N_ABS | N_EXT;
551933965Sjdp      else
552033965Sjdp	{
552133965Sjdp	  BFD_ASSERT (pr->u.section->owner == finfo->output_bfd);
552233965Sjdp	  r_index = pr->u.section->target_index;
552333965Sjdp	}
552433965Sjdp    }
552533965Sjdp  else
552633965Sjdp    {
552733965Sjdp      struct aout_link_hash_entry *h;
552833965Sjdp
552933965Sjdp      BFD_ASSERT (p->type == bfd_symbol_reloc_link_order);
553033965Sjdp      r_extern = 1;
553133965Sjdp      h = ((struct aout_link_hash_entry *)
553233965Sjdp	   bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info,
553333965Sjdp					 pr->u.name, false, false, true));
553433965Sjdp      if (h != (struct aout_link_hash_entry *) NULL
553533965Sjdp	  && h->indx >= 0)
553633965Sjdp	r_index = h->indx;
553733965Sjdp      else if (h != NULL)
553833965Sjdp	{
553933965Sjdp	  /* We decided to strip this symbol, but it turns out that we
554033965Sjdp	     can't.  Note that we lose the other and desc information
554133965Sjdp	     here.  I don't think that will ever matter for a global
554233965Sjdp	     symbol.  */
554333965Sjdp	  h->indx = -2;
554433965Sjdp	  h->written = false;
554533965Sjdp	  if (! aout_link_write_other_symbol (h, (PTR) finfo))
554633965Sjdp	    return false;
554733965Sjdp	  r_index = h->indx;
554833965Sjdp	}
554933965Sjdp      else
555033965Sjdp	{
555133965Sjdp	  if (! ((*finfo->info->callbacks->unattached_reloc)
555233965Sjdp		 (finfo->info, pr->u.name, (bfd *) NULL,
555333965Sjdp		  (asection *) NULL, (bfd_vma) 0)))
555433965Sjdp	    return false;
555533965Sjdp	  r_index = 0;
555633965Sjdp	}
555733965Sjdp    }
555833965Sjdp
555933965Sjdp  howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc);
556033965Sjdp  if (howto == 0)
556133965Sjdp    {
556233965Sjdp      bfd_set_error (bfd_error_bad_value);
556333965Sjdp      return false;
556433965Sjdp    }
556533965Sjdp
556633965Sjdp  if (o == obj_textsec (finfo->output_bfd))
556733965Sjdp    reloff_ptr = &finfo->treloff;
556833965Sjdp  else if (o == obj_datasec (finfo->output_bfd))
556933965Sjdp    reloff_ptr = &finfo->dreloff;
557033965Sjdp  else
557133965Sjdp    abort ();
557233965Sjdp
557333965Sjdp  if (obj_reloc_entry_size (finfo->output_bfd) == RELOC_STD_SIZE)
557433965Sjdp    {
557533965Sjdp#ifdef MY_put_reloc
557633965Sjdp      MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto,
557733965Sjdp		   &srel);
557833965Sjdp#else
557933965Sjdp      {
558033965Sjdp	int r_pcrel;
558133965Sjdp	int r_baserel;
558233965Sjdp	int r_jmptable;
558333965Sjdp	int r_relative;
558433965Sjdp	int r_length;
558533965Sjdp
558633965Sjdp	r_pcrel = howto->pc_relative;
558733965Sjdp	r_baserel = (howto->type & 8) != 0;
558833965Sjdp	r_jmptable = (howto->type & 16) != 0;
558933965Sjdp	r_relative = (howto->type & 32) != 0;
559033965Sjdp	r_length = howto->size;
559133965Sjdp
559233965Sjdp	PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
559333965Sjdp	if (bfd_header_big_endian (finfo->output_bfd))
559433965Sjdp	  {
559533965Sjdp	    srel.r_index[0] = r_index >> 16;
559633965Sjdp	    srel.r_index[1] = r_index >> 8;
559733965Sjdp	    srel.r_index[2] = r_index;
559833965Sjdp	    srel.r_type[0] =
559933965Sjdp	      ((r_extern ?     RELOC_STD_BITS_EXTERN_BIG : 0)
560033965Sjdp	       | (r_pcrel ?    RELOC_STD_BITS_PCREL_BIG : 0)
560133965Sjdp	       | (r_baserel ?  RELOC_STD_BITS_BASEREL_BIG : 0)
560233965Sjdp	       | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
560333965Sjdp	       | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
560433965Sjdp	       | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
560533965Sjdp	  }
560633965Sjdp	else
560733965Sjdp	  {
560833965Sjdp	    srel.r_index[2] = r_index >> 16;
560933965Sjdp	    srel.r_index[1] = r_index >> 8;
561033965Sjdp	    srel.r_index[0] = r_index;
561133965Sjdp	    srel.r_type[0] =
561233965Sjdp	      ((r_extern ?     RELOC_STD_BITS_EXTERN_LITTLE : 0)
561333965Sjdp	       | (r_pcrel ?    RELOC_STD_BITS_PCREL_LITTLE : 0)
561433965Sjdp	       | (r_baserel ?  RELOC_STD_BITS_BASEREL_LITTLE : 0)
561533965Sjdp	       | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
561633965Sjdp	       | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
561733965Sjdp	       | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
561833965Sjdp	  }
561933965Sjdp      }
562033965Sjdp#endif
562133965Sjdp      rel_ptr = (PTR) &srel;
562233965Sjdp
562333965Sjdp      /* We have to write the addend into the object file, since
562433965Sjdp	 standard a.out relocs are in place.  It would be more
562533965Sjdp	 reliable if we had the current contents of the file here,
562633965Sjdp	 rather than assuming zeroes, but we can't read the file since
562733965Sjdp	 it was opened using bfd_openw.  */
562833965Sjdp      if (pr->addend != 0)
562933965Sjdp	{
563033965Sjdp	  bfd_size_type size;
563133965Sjdp	  bfd_reloc_status_type r;
563233965Sjdp	  bfd_byte *buf;
563333965Sjdp	  boolean ok;
563433965Sjdp
563533965Sjdp	  size = bfd_get_reloc_size (howto);
563633965Sjdp	  buf = (bfd_byte *) bfd_zmalloc (size);
563733965Sjdp	  if (buf == (bfd_byte *) NULL)
563833965Sjdp	    return false;
563933965Sjdp	  r = MY_relocate_contents (howto, finfo->output_bfd,
564033965Sjdp				      pr->addend, buf);
564133965Sjdp	  switch (r)
564233965Sjdp	    {
564333965Sjdp	    case bfd_reloc_ok:
564433965Sjdp	      break;
564533965Sjdp	    default:
564633965Sjdp	    case bfd_reloc_outofrange:
564733965Sjdp	      abort ();
564833965Sjdp	    case bfd_reloc_overflow:
564933965Sjdp	      if (! ((*finfo->info->callbacks->reloc_overflow)
565033965Sjdp		     (finfo->info,
565133965Sjdp		      (p->type == bfd_section_reloc_link_order
565233965Sjdp		       ? bfd_section_name (finfo->output_bfd,
565333965Sjdp					   pr->u.section)
565433965Sjdp		       : pr->u.name),
565533965Sjdp		      howto->name, pr->addend, (bfd *) NULL,
565633965Sjdp		      (asection *) NULL, (bfd_vma) 0)))
565733965Sjdp		{
565833965Sjdp		  free (buf);
565933965Sjdp		  return false;
566033965Sjdp		}
566133965Sjdp	      break;
566233965Sjdp	    }
566333965Sjdp	  ok = bfd_set_section_contents (finfo->output_bfd, o,
566433965Sjdp					 (PTR) buf,
566533965Sjdp					 (file_ptr) p->offset,
566633965Sjdp					 size);
566733965Sjdp	  free (buf);
566833965Sjdp	  if (! ok)
566933965Sjdp	    return false;
567033965Sjdp	}
567133965Sjdp    }
567233965Sjdp  else
567333965Sjdp    {
567433965Sjdp      PUT_WORD (finfo->output_bfd, p->offset, erel.r_address);
567533965Sjdp
567633965Sjdp      if (bfd_header_big_endian (finfo->output_bfd))
567733965Sjdp	{
567833965Sjdp	  erel.r_index[0] = r_index >> 16;
567933965Sjdp	  erel.r_index[1] = r_index >> 8;
568033965Sjdp	  erel.r_index[2] = r_index;
568133965Sjdp	  erel.r_type[0] =
568233965Sjdp	    ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
568333965Sjdp	     | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG));
568433965Sjdp	}
568533965Sjdp      else
568633965Sjdp	{
568733965Sjdp	  erel.r_index[2] = r_index >> 16;
568833965Sjdp	  erel.r_index[1] = r_index >> 8;
568933965Sjdp	  erel.r_index[0] = r_index;
569033965Sjdp	  erel.r_type[0] =
569133965Sjdp	    (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
569233965Sjdp	      | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
569333965Sjdp	}
569433965Sjdp
569533965Sjdp      PUT_WORD (finfo->output_bfd, pr->addend, erel.r_addend);
569633965Sjdp
569733965Sjdp      rel_ptr = (PTR) &erel;
569833965Sjdp    }
569933965Sjdp
570033965Sjdp  if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0
570133965Sjdp      || (bfd_write (rel_ptr, (bfd_size_type) 1,
570233965Sjdp		     obj_reloc_entry_size (finfo->output_bfd),
570333965Sjdp		     finfo->output_bfd)
570433965Sjdp	  != obj_reloc_entry_size (finfo->output_bfd)))
570533965Sjdp    return false;
570633965Sjdp
570733965Sjdp  *reloff_ptr += obj_reloc_entry_size (finfo->output_bfd);
570833965Sjdp
570933965Sjdp  /* Assert that the relocs have not run into the symbols, and that n
571033965Sjdp     the text relocs have not run into the data relocs.  */
571133965Sjdp  BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
571233965Sjdp	      && (reloff_ptr != &finfo->treloff
571333965Sjdp		  || (*reloff_ptr
571433965Sjdp		      <= obj_datasec (finfo->output_bfd)->rel_filepos)));
571533965Sjdp
571633965Sjdp  return true;
571733965Sjdp}
5718