xref: /openbsd/gnu/usr.bin/binutils/bfd/pdp11.c (revision cf2f2c56)
1d2201f2fSdrahn /* BFD back-end for PDP-11 a.out binaries.
2*cf2f2c56Smiod    Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
3d2201f2fSdrahn 
4d2201f2fSdrahn    This file is part of BFD, the Binary File Descriptor library.
5d2201f2fSdrahn 
6d2201f2fSdrahn    This program is free software; you can redistribute it and/or modify
7d2201f2fSdrahn    it under the terms of the GNU General Public License as published by
8d2201f2fSdrahn    the Free Software Foundation; either version 2 of the License, or
9d2201f2fSdrahn    (at your option) any later version.
10d2201f2fSdrahn 
11d2201f2fSdrahn    This program is distributed in the hope that it will be useful,
12d2201f2fSdrahn    but WITHOUT ANY WARRANTY; without even the implied warranty of
13d2201f2fSdrahn    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d2201f2fSdrahn    GNU General Public License for more details.
15d2201f2fSdrahn 
16d2201f2fSdrahn    You should have received a copy of the GNU General Public License
17d2201f2fSdrahn    along with this program; if not, write to the Free Software
18d2201f2fSdrahn    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19d2201f2fSdrahn 
20d2201f2fSdrahn /* BFD backend for PDP-11, running 2.11BSD in particular.
21d2201f2fSdrahn 
22d2201f2fSdrahn    This file was hacked up by looking hard at the existing vaxnetbsd
23d2201f2fSdrahn    back end and the header files in 2.11BSD.
24d2201f2fSdrahn 
25d2201f2fSdrahn    TODO
26d2201f2fSdrahn    * support for V7 file formats
27d2201f2fSdrahn    * support for overlay object files (see 2.11 a.out(5))
28d2201f2fSdrahn    * support for old and very old archives
29d2201f2fSdrahn    (see 2.11 ar(5), historical section)
30d2201f2fSdrahn 
31d2201f2fSdrahn    Search for TODO to find other areas needing more work.  */
32d2201f2fSdrahn 
33d2201f2fSdrahn #define	BYTES_IN_WORD	2
34d2201f2fSdrahn #define	BYTES_IN_LONG	4
35d2201f2fSdrahn #define ARCH_SIZE	16
36d2201f2fSdrahn #undef TARGET_IS_BIG_ENDIAN_P
37d2201f2fSdrahn 
38d2201f2fSdrahn #define	TARGET_PAGE_SIZE	1024
39d2201f2fSdrahn #define	SEGMENT__SIZE	TARGET_PAGE_SIZE
40d2201f2fSdrahn 
41d2201f2fSdrahn #define	DEFAULT_ARCH	bfd_arch_pdp11
42d2201f2fSdrahn #define	DEFAULT_MID 	M_PDP11
43d2201f2fSdrahn 
44d2201f2fSdrahn /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
45d2201f2fSdrahn    remove whitespace added here, and thus will fail to concatenate
46d2201f2fSdrahn    the tokens.  */
47d2201f2fSdrahn #define MY(OP) CONCAT2 (pdp11_aout_,OP)
48d2201f2fSdrahn 
49d2201f2fSdrahn /* This needs to start with a.out so GDB knows it is an a.out variant.  */
50d2201f2fSdrahn #define TARGETNAME "a.out-pdp11"
51d2201f2fSdrahn 
52d2201f2fSdrahn /* This is the normal load address for executables.  */
53d2201f2fSdrahn #define TEXT_START_ADDR		0
54d2201f2fSdrahn 
55d2201f2fSdrahn /* The header is not included in the text segment.  */
56d2201f2fSdrahn #define N_HEADER_IN_TEXT(x)	0
57d2201f2fSdrahn 
58d2201f2fSdrahn /* There are no shared libraries.  */
59d2201f2fSdrahn #define N_SHARED_LIB(x) 	0
60d2201f2fSdrahn 
61d2201f2fSdrahn /* There is no flags field.  */
62d2201f2fSdrahn #define N_FLAGS(exec)		0
63d2201f2fSdrahn 
64d2201f2fSdrahn #define N_SET_FLAGS(exec, flags) do { } while (0)
65d2201f2fSdrahn #define N_BADMAG(x) (((x).a_info != OMAGIC) && \
66d2201f2fSdrahn                      ((x).a_info != NMAGIC) && \
67d2201f2fSdrahn                      ((x).a_info != A_MAGIC3) && \
68d2201f2fSdrahn                      ((x).a_info != A_MAGIC4) && \
69d2201f2fSdrahn                      ((x).a_info != A_MAGIC5) && \
70d2201f2fSdrahn                      ((x).a_info != A_MAGIC6))
71d2201f2fSdrahn 
72d2201f2fSdrahn #include "bfd.h"
73d2201f2fSdrahn 
74d2201f2fSdrahn #define external_exec pdp11_external_exec
75d2201f2fSdrahn struct pdp11_external_exec
76d2201f2fSdrahn   {
77d2201f2fSdrahn     bfd_byte e_info[2];	/* magic number				*/
78d2201f2fSdrahn     bfd_byte e_text[2];	/* length of text section in bytes	*/
79d2201f2fSdrahn     bfd_byte e_data[2];	/* length of data section in bytes	*/
80d2201f2fSdrahn     bfd_byte e_bss[2];	/* length of bss area in bytes 		*/
81d2201f2fSdrahn     bfd_byte e_syms[2];	/* length of symbol table in bytes 	*/
82d2201f2fSdrahn     bfd_byte e_entry[2];	/* start address 			*/
83d2201f2fSdrahn     bfd_byte e_unused[2];	/* not used				*/
84d2201f2fSdrahn     bfd_byte e_flag[2];	/* relocation info stripped		*/
85d2201f2fSdrahn     bfd_byte e_relocatable; /* ugly hack */
86d2201f2fSdrahn   };
87d2201f2fSdrahn 
88d2201f2fSdrahn #define	EXEC_BYTES_SIZE	(8 * 2)
89d2201f2fSdrahn 
90d2201f2fSdrahn #define	A_MAGIC1	OMAGIC
91d2201f2fSdrahn #define OMAGIC		0407	/* ...object file or impure executable.  */
92d2201f2fSdrahn #define	A_MAGIC2	NMAGIC
93d2201f2fSdrahn #define NMAGIC		0410	/* pure executable.  */
94d2201f2fSdrahn #define ZMAGIC		0413	/* demand-paged executable.  */
95d2201f2fSdrahn #define	A_MAGIC3	0411	/* separated I&D */
96d2201f2fSdrahn #define	A_MAGIC4	0405	/* overlay */
97d2201f2fSdrahn #define	A_MAGIC5	0430	/* auto-overlay (nonseparate) */
98d2201f2fSdrahn #define	A_MAGIC6	0431	/* auto-overlay (separate) */
99d2201f2fSdrahn #define QMAGIC		0
100d2201f2fSdrahn #define BMAGIC		0
101d2201f2fSdrahn 
102d2201f2fSdrahn #define A_FLAG_RELOC_STRIPPED	0x0001
103d2201f2fSdrahn 
104d2201f2fSdrahn #define external_nlist pdp11_external_nlist
105d2201f2fSdrahn struct pdp11_external_nlist
106d2201f2fSdrahn   {
107d2201f2fSdrahn     bfd_byte e_unused[2];	/* unused */
108d2201f2fSdrahn     bfd_byte e_strx[2];		/* index into string table of name */
109d2201f2fSdrahn     bfd_byte e_type[1];		/* type of symbol */
110d2201f2fSdrahn     bfd_byte e_ovly[1];		/* overlay number */
111d2201f2fSdrahn     bfd_byte e_value[2];	/* value of symbol */
112d2201f2fSdrahn   };
113d2201f2fSdrahn 
114d2201f2fSdrahn #define	EXTERNAL_NLIST_SIZE	8
115d2201f2fSdrahn 
116d2201f2fSdrahn #define N_TXTOFF(x)	(EXEC_BYTES_SIZE)
117d2201f2fSdrahn #define N_DATOFF(x)	(N_TXTOFF(x) + (x).a_text)
118d2201f2fSdrahn #define N_TRELOFF(x)	(N_DATOFF(x) + (x).a_data)
119d2201f2fSdrahn #define N_DRELOFF(x)	(N_TRELOFF(x) + (x).a_trsize)
120d2201f2fSdrahn #define N_SYMOFF(x)	(N_DRELOFF(x) + (x).a_drsize)
121d2201f2fSdrahn #define N_STROFF(x)	(N_SYMOFF(x) + (x).a_syms)
122d2201f2fSdrahn 
123d2201f2fSdrahn #define WRITE_HEADERS(abfd, execp) pdp11_aout_write_headers (abfd, execp)
124d2201f2fSdrahn 
125d2201f2fSdrahn #include "sysdep.h"
126d2201f2fSdrahn #include "libbfd.h"
127d2201f2fSdrahn #include "libaout.h"
128d2201f2fSdrahn 
129d2201f2fSdrahn #define SWAP_MAGIC(ext) bfd_getl16 (ext)
130d2201f2fSdrahn 
131d2201f2fSdrahn #define MY_entry_is_text_address 1
132d2201f2fSdrahn 
133d2201f2fSdrahn #define MY_write_object_contents MY(write_object_contents)
134d2201f2fSdrahn static bfd_boolean MY(write_object_contents) PARAMS ((bfd *abfd));
135d2201f2fSdrahn #define MY_text_includes_header 1
136d2201f2fSdrahn 
137*cf2f2c56Smiod static bfd_vma bfd_getp32 (const void *);
138*cf2f2c56Smiod static bfd_signed_vma bfd_getp_signed_32 (const void *);
139*cf2f2c56Smiod static void bfd_putp32 (bfd_vma, void *);
140d2201f2fSdrahn 
141d2201f2fSdrahn #define MY_BFD_TARGET
142d2201f2fSdrahn 
143d2201f2fSdrahn #include "aout-target.h"
144d2201f2fSdrahn 
145d2201f2fSdrahn const bfd_target MY(vec) =
146d2201f2fSdrahn {
147d2201f2fSdrahn   TARGETNAME,		/* name */
148d2201f2fSdrahn   bfd_target_aout_flavour,
149d2201f2fSdrahn   BFD_ENDIAN_LITTLE,		/* target byte order (little) */
150d2201f2fSdrahn   BFD_ENDIAN_LITTLE,		/* target headers byte order (little) */
151d2201f2fSdrahn   (HAS_RELOC | EXEC_P |		/* object flags */
152d2201f2fSdrahn    HAS_LINENO | HAS_DEBUG |
153d2201f2fSdrahn    HAS_SYMS | HAS_LOCALS | WP_TEXT),
154d2201f2fSdrahn   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
155d2201f2fSdrahn   MY_symbol_leading_char,
156d2201f2fSdrahn   AR_PAD_CHAR,			/* ar_pad_char */
157d2201f2fSdrahn   15,				/* ar_max_namelen */
158d2201f2fSdrahn   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
159d2201f2fSdrahn      bfd_getp32, bfd_getp_signed_32, bfd_putp32,
160d2201f2fSdrahn      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
161d2201f2fSdrahn   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
162d2201f2fSdrahn      bfd_getp32, bfd_getp_signed_32, bfd_putp32,
163d2201f2fSdrahn      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
164d2201f2fSdrahn     {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
165d2201f2fSdrahn        bfd_generic_archive_p, MY_core_file_p},
166d2201f2fSdrahn     {bfd_false, MY_mkobject,	/* bfd_set_format */
167d2201f2fSdrahn        _bfd_generic_mkarchive, bfd_false},
168d2201f2fSdrahn     {bfd_false, MY_write_object_contents, /* bfd_write_contents */
169d2201f2fSdrahn        _bfd_write_archive_contents, bfd_false},
170d2201f2fSdrahn 
171d2201f2fSdrahn      BFD_JUMP_TABLE_GENERIC (MY),
172d2201f2fSdrahn      BFD_JUMP_TABLE_COPY (MY),
173d2201f2fSdrahn      BFD_JUMP_TABLE_CORE (MY),
174d2201f2fSdrahn      BFD_JUMP_TABLE_ARCHIVE (MY),
175d2201f2fSdrahn      BFD_JUMP_TABLE_SYMBOLS (MY),
176d2201f2fSdrahn      BFD_JUMP_TABLE_RELOCS (MY),
177d2201f2fSdrahn      BFD_JUMP_TABLE_WRITE (MY),
178d2201f2fSdrahn      BFD_JUMP_TABLE_LINK (MY),
179d2201f2fSdrahn      BFD_JUMP_TABLE_DYNAMIC (MY),
180d2201f2fSdrahn 
181d2201f2fSdrahn   /* Alternative_target */
182d2201f2fSdrahn   NULL,
183d2201f2fSdrahn 
184d2201f2fSdrahn   (PTR) MY_backend_data,
185d2201f2fSdrahn };
186d2201f2fSdrahn 
187d2201f2fSdrahn /* start of modified aoutx.h */
188d2201f2fSdrahn /* BFD semi-generic back-end for a.out binaries.
189d2201f2fSdrahn    Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1998
190d2201f2fSdrahn    Free Software Foundation, Inc.
191d2201f2fSdrahn    Written by Cygnus Support.
192d2201f2fSdrahn 
193d2201f2fSdrahn This file is part of BFD, the Binary File Descriptor library.
194d2201f2fSdrahn 
195d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
196d2201f2fSdrahn it under the terms of the GNU General Public License as published by
197d2201f2fSdrahn the Free Software Foundation; either version 2 of the License, or
198d2201f2fSdrahn (at your option) any later version.
199d2201f2fSdrahn 
200d2201f2fSdrahn This program is distributed in the hope that it will be useful,
201d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
202d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
203d2201f2fSdrahn GNU General Public License for more details.
204d2201f2fSdrahn 
205d2201f2fSdrahn You should have received a copy of the GNU General Public License
206d2201f2fSdrahn along with this program; if not, write to the Free Software
207d2201f2fSdrahn Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
208d2201f2fSdrahn 
209d2201f2fSdrahn /*
210d2201f2fSdrahn SECTION
211d2201f2fSdrahn 	a.out backends
212d2201f2fSdrahn 
213d2201f2fSdrahn 
214d2201f2fSdrahn DESCRIPTION
215d2201f2fSdrahn 
216d2201f2fSdrahn 	BFD supports a number of different flavours of a.out format,
217d2201f2fSdrahn 	though the major differences are only the sizes of the
218d2201f2fSdrahn 	structures on disk, and the shape of the relocation
219d2201f2fSdrahn 	information.
220d2201f2fSdrahn 
221d2201f2fSdrahn 	The support is split into a basic support file @file{aoutx.h}
222d2201f2fSdrahn 	and other files which derive functions from the base. One
223d2201f2fSdrahn 	derivation file is @file{aoutf1.h} (for a.out flavour 1), and
224d2201f2fSdrahn 	adds to the basic a.out functions support for sun3, sun4, 386
225d2201f2fSdrahn 	and 29k a.out files, to create a target jump vector for a
226d2201f2fSdrahn 	specific target.
227d2201f2fSdrahn 
228d2201f2fSdrahn 	This information is further split out into more specific files
229d2201f2fSdrahn 	for each machine, including @file{sunos.c} for sun3 and sun4,
230d2201f2fSdrahn 	@file{newsos3.c} for the Sony NEWS, and @file{demo64.c} for a
231d2201f2fSdrahn 	demonstration of a 64 bit a.out format.
232d2201f2fSdrahn 
233d2201f2fSdrahn 	The base file @file{aoutx.h} defines general mechanisms for
234d2201f2fSdrahn 	reading and writing records to and from disk and various
235d2201f2fSdrahn 	other methods which BFD requires. It is included by
236d2201f2fSdrahn 	@file{aout32.c} and @file{aout64.c} to form the names
237d2201f2fSdrahn 	<<aout_32_swap_exec_header_in>>, <<aout_64_swap_exec_header_in>>, etc.
238d2201f2fSdrahn 
239d2201f2fSdrahn 	As an example, this is what goes on to make the back end for a
240d2201f2fSdrahn 	sun4, from @file{aout32.c}:
241d2201f2fSdrahn 
242d2201f2fSdrahn |	#define ARCH_SIZE 32
243d2201f2fSdrahn |	#include "aoutx.h"
244d2201f2fSdrahn 
245d2201f2fSdrahn 	Which exports names:
246d2201f2fSdrahn 
247d2201f2fSdrahn |	...
248d2201f2fSdrahn |	aout_32_canonicalize_reloc
249d2201f2fSdrahn |	aout_32_find_nearest_line
250d2201f2fSdrahn |	aout_32_get_lineno
251d2201f2fSdrahn |	aout_32_get_reloc_upper_bound
252d2201f2fSdrahn |	...
253d2201f2fSdrahn 
254d2201f2fSdrahn 	from @file{sunos.c}:
255d2201f2fSdrahn 
256d2201f2fSdrahn |	#define TARGET_NAME "a.out-sunos-big"
257d2201f2fSdrahn |	#define VECNAME    sunos_big_vec
258d2201f2fSdrahn |	#include "aoutf1.h"
259d2201f2fSdrahn 
260d2201f2fSdrahn 	requires all the names from @file{aout32.c}, and produces the jump vector
261d2201f2fSdrahn 
262d2201f2fSdrahn |	sunos_big_vec
263d2201f2fSdrahn 
264d2201f2fSdrahn 	The file @file{host-aout.c} is a special case.  It is for a large set
265d2201f2fSdrahn 	of hosts that use ``more or less standard'' a.out files, and
266d2201f2fSdrahn 	for which cross-debugging is not interesting.  It uses the
267d2201f2fSdrahn 	standard 32-bit a.out support routines, but determines the
268d2201f2fSdrahn 	file offsets and addresses of the text, data, and BSS
269d2201f2fSdrahn 	sections, the machine architecture and machine type, and the
270d2201f2fSdrahn 	entry point address, in a host-dependent manner.  Once these
271d2201f2fSdrahn 	values have been determined, generic code is used to handle
272d2201f2fSdrahn 	the  object file.
273d2201f2fSdrahn 
274d2201f2fSdrahn 	When porting it to run on a new system, you must supply:
275d2201f2fSdrahn 
276d2201f2fSdrahn |        HOST_PAGE_SIZE
277d2201f2fSdrahn |        HOST_SEGMENT_SIZE
278d2201f2fSdrahn |        HOST_MACHINE_ARCH       (optional)
279d2201f2fSdrahn |        HOST_MACHINE_MACHINE    (optional)
280d2201f2fSdrahn |        HOST_TEXT_START_ADDR
281d2201f2fSdrahn |        HOST_STACK_END_ADDR
282d2201f2fSdrahn 
283d2201f2fSdrahn 	in the file @file{../include/sys/h-@var{XXX}.h} (for your host).  These
284d2201f2fSdrahn 	values, plus the structures and macros defined in @file{a.out.h} on
285d2201f2fSdrahn 	your host system, will produce a BFD target that will access
286d2201f2fSdrahn 	ordinary a.out files on your host. To configure a new machine
287d2201f2fSdrahn 	to use @file{host-aout.c}, specify:
288d2201f2fSdrahn 
289d2201f2fSdrahn |	TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
290d2201f2fSdrahn |	TDEPFILES= host-aout.o trad-core.o
291d2201f2fSdrahn 
292d2201f2fSdrahn 	in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in}
293d2201f2fSdrahn 	to use the
294d2201f2fSdrahn 	@file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your
295d2201f2fSdrahn 	configuration is selected.
296d2201f2fSdrahn 
297d2201f2fSdrahn */
298d2201f2fSdrahn 
299d2201f2fSdrahn /* Some assumptions:
300d2201f2fSdrahn    * Any BFD with D_PAGED set is ZMAGIC, and vice versa.
301d2201f2fSdrahn      Doesn't matter what the setting of WP_TEXT is on output, but it'll
302d2201f2fSdrahn      get set on input.
303d2201f2fSdrahn    * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC.
304d2201f2fSdrahn    * Any BFD with both flags clear is OMAGIC.
305d2201f2fSdrahn    (Just want to make these explicit, so the conditions tested in this
306d2201f2fSdrahn    file make sense if you're more familiar with a.out than with BFD.)  */
307d2201f2fSdrahn 
308d2201f2fSdrahn #define KEEPIT udata.i
309d2201f2fSdrahn 
310d2201f2fSdrahn #include <string.h>		/* For strchr and friends */
311d2201f2fSdrahn #include "bfd.h"
312d2201f2fSdrahn #include "sysdep.h"
313d2201f2fSdrahn #include "safe-ctype.h"
314d2201f2fSdrahn #include "bfdlink.h"
315d2201f2fSdrahn 
316d2201f2fSdrahn #include "libaout.h"
317d2201f2fSdrahn /*#include "libbfd.h"*/
318d2201f2fSdrahn #include "aout/aout64.h"
319d2201f2fSdrahn #include "aout/stab_gnu.h"
320d2201f2fSdrahn #include "aout/ar.h"
321d2201f2fSdrahn 
322d2201f2fSdrahn #undef N_TYPE
323d2201f2fSdrahn #undef N_UNDF
324d2201f2fSdrahn #undef N_ABS
325d2201f2fSdrahn #undef N_TEXT
326d2201f2fSdrahn #undef N_DATA
327d2201f2fSdrahn #undef N_BSS
328d2201f2fSdrahn #undef N_REG
329d2201f2fSdrahn #undef N_FN
330d2201f2fSdrahn #undef N_EXT
331d2201f2fSdrahn #define N_TYPE		0x1f	/* type mask */
332d2201f2fSdrahn #define N_UNDF		0x00	/* undefined */
333d2201f2fSdrahn #define N_ABS		0x01	/* absolute */
334d2201f2fSdrahn #define N_TEXT		0x02	/* text segment */
335d2201f2fSdrahn #define N_DATA		0x03	/* data segment */
336d2201f2fSdrahn #define N_BSS		0x04	/* bss segment */
337d2201f2fSdrahn #define N_REG		0x14	/* register symbol */
338d2201f2fSdrahn #define N_FN		0x1f	/* file name */
339d2201f2fSdrahn 
340d2201f2fSdrahn #define N_EXT		0x20	/* external flag */
341d2201f2fSdrahn 
342d2201f2fSdrahn #define RELOC_SIZE 2
343d2201f2fSdrahn 
344d2201f2fSdrahn struct pdp11_aout_reloc_external
345d2201f2fSdrahn {
346d2201f2fSdrahn   bfd_byte e_reloc_entry[2];
347d2201f2fSdrahn };
348d2201f2fSdrahn 
349d2201f2fSdrahn #define RELFLG		0x0001	/* pc-relative flag */
350d2201f2fSdrahn #define RTYPE		0x000e	/* type mask */
351d2201f2fSdrahn #define RIDXMASK	0xfff0	/* index mask */
352d2201f2fSdrahn 
353d2201f2fSdrahn #define RABS		0x00	/* absolute */
354d2201f2fSdrahn #define RTEXT		0x02	/* text */
355d2201f2fSdrahn #define RDATA		0x04	/* data */
356d2201f2fSdrahn #define RBSS		0x06	/* bss */
357d2201f2fSdrahn #define REXT		0x08	/* external */
358d2201f2fSdrahn 
359d2201f2fSdrahn #define RINDEX(x)	(((x) & 0xfff0) >> 4)
360d2201f2fSdrahn 
361d2201f2fSdrahn static bfd_boolean aout_get_external_symbols PARAMS ((bfd *));
362d2201f2fSdrahn static bfd_boolean translate_from_native_sym_flags
363d2201f2fSdrahn   PARAMS ((bfd *, aout_symbol_type *));
364d2201f2fSdrahn static bfd_boolean translate_to_native_sym_flags
365d2201f2fSdrahn   PARAMS ((bfd *, asymbol *, struct external_nlist *));
366d2201f2fSdrahn static void adjust_o_magic PARAMS ((bfd *, struct internal_exec *));
367d2201f2fSdrahn static void adjust_z_magic PARAMS ((bfd *, struct internal_exec *));
368d2201f2fSdrahn static void adjust_n_magic PARAMS ((bfd *, struct internal_exec *));
369d2201f2fSdrahn 
370d2201f2fSdrahn static int pdp11_aout_write_headers PARAMS ((bfd *, struct internal_exec *));
371d2201f2fSdrahn void pdp11_aout_swap_reloc_out PARAMS  ((bfd *, arelent *, struct pdp11_aout_reloc_external *));
372d2201f2fSdrahn void pdp11_aout_swap_reloc_in
373d2201f2fSdrahn PARAMS ((bfd *, struct pdp11_aout_reloc_external *, arelent *,
374d2201f2fSdrahn 	 bfd_size_type, asymbol **, bfd_size_type));
375d2201f2fSdrahn 
376d2201f2fSdrahn /*
377d2201f2fSdrahn SUBSECTION
378d2201f2fSdrahn 	Relocations
379d2201f2fSdrahn 
380d2201f2fSdrahn DESCRIPTION
381d2201f2fSdrahn 	The file @file{aoutx.h} provides for both the @emph{standard}
382d2201f2fSdrahn 	and @emph{extended} forms of a.out relocation records.
383d2201f2fSdrahn 
384d2201f2fSdrahn 	The standard records contain only an
385d2201f2fSdrahn 	address, a symbol index, and a type field. The extended records
386d2201f2fSdrahn 	(used on 29ks and sparcs) also have a full integer for an
387d2201f2fSdrahn 	addend.
388d2201f2fSdrahn 
389d2201f2fSdrahn */
390d2201f2fSdrahn 
391d2201f2fSdrahn #ifndef MY_final_link_relocate
392d2201f2fSdrahn #define MY_final_link_relocate _bfd_final_link_relocate
393d2201f2fSdrahn #endif
394d2201f2fSdrahn 
395d2201f2fSdrahn #ifndef MY_relocate_contents
396d2201f2fSdrahn #define MY_relocate_contents _bfd_relocate_contents
397d2201f2fSdrahn #endif
398d2201f2fSdrahn 
399d2201f2fSdrahn reloc_howto_type howto_table_pdp11[] =
400d2201f2fSdrahn {
401d2201f2fSdrahn   /* type              rs size bsz  pcrel bitpos ovrf                     sf name     part_inpl readmask  setmask    pcdone */
402d2201f2fSdrahn HOWTO( 0,	       0,  1,  16,  FALSE, 0, complain_overflow_signed,0,"16",	TRUE, 0x0000ffff,0x0000ffff, FALSE),
403d2201f2fSdrahn HOWTO( 1,	       0,  1,  16,  TRUE,  0, complain_overflow_signed,0,"DISP16",	TRUE, 0x0000ffff,0x0000ffff, FALSE),
404d2201f2fSdrahn };
405d2201f2fSdrahn 
406d2201f2fSdrahn #define TABLE_SIZE(TABLE)	(sizeof(TABLE)/sizeof(TABLE[0]))
407d2201f2fSdrahn 
408d2201f2fSdrahn reloc_howto_type *
409d2201f2fSdrahn NAME(aout,reloc_type_lookup) (abfd,code)
410d2201f2fSdrahn      bfd * abfd ATTRIBUTE_UNUSED;
411d2201f2fSdrahn      bfd_reloc_code_real_type code;
412d2201f2fSdrahn {
413d2201f2fSdrahn   switch (code)
414d2201f2fSdrahn     {
415d2201f2fSdrahn     case BFD_RELOC_16:
416d2201f2fSdrahn       return &howto_table_pdp11[0];
417d2201f2fSdrahn     case BFD_RELOC_16_PCREL:
418d2201f2fSdrahn       return &howto_table_pdp11[1];
419d2201f2fSdrahn     default:
420d2201f2fSdrahn       return (reloc_howto_type *)NULL;
421d2201f2fSdrahn     }
422d2201f2fSdrahn }
423d2201f2fSdrahn 
424d2201f2fSdrahn static int
pdp11_aout_write_headers(abfd,execp)425d2201f2fSdrahn pdp11_aout_write_headers (abfd, execp)
426d2201f2fSdrahn      bfd *abfd;
427d2201f2fSdrahn      struct internal_exec *execp;
428d2201f2fSdrahn {
429d2201f2fSdrahn   struct external_exec exec_bytes;
430d2201f2fSdrahn   bfd_size_type text_size;
431d2201f2fSdrahn   file_ptr text_end;
432d2201f2fSdrahn 
433d2201f2fSdrahn   if (adata(abfd).magic == undecided_magic)
434d2201f2fSdrahn     NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
435d2201f2fSdrahn 
436d2201f2fSdrahn   execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;
437d2201f2fSdrahn   execp->a_entry = bfd_get_start_address (abfd);
438d2201f2fSdrahn 
439d2201f2fSdrahn   if (obj_textsec (abfd)->reloc_count > 0 ||
440d2201f2fSdrahn       obj_datasec (abfd)->reloc_count > 0)
441d2201f2fSdrahn     {
442d2201f2fSdrahn       execp->a_trsize = execp->a_text;
443d2201f2fSdrahn       execp->a_drsize = execp->a_data;
444d2201f2fSdrahn     }
445d2201f2fSdrahn   else
446d2201f2fSdrahn     {
447d2201f2fSdrahn       execp->a_trsize = 0;
448d2201f2fSdrahn       execp->a_drsize = 0;
449d2201f2fSdrahn     }
450d2201f2fSdrahn 
451d2201f2fSdrahn   NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes);
452d2201f2fSdrahn 
453d2201f2fSdrahn   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
454d2201f2fSdrahn     return FALSE;
455d2201f2fSdrahn 
456d2201f2fSdrahn   if (bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd)
457d2201f2fSdrahn       != EXEC_BYTES_SIZE)
458d2201f2fSdrahn     return FALSE;
459d2201f2fSdrahn 
460d2201f2fSdrahn   /* Now write out reloc info, followed by syms and strings */
461d2201f2fSdrahn 
462d2201f2fSdrahn   if (bfd_get_outsymbols (abfd) != (asymbol **) NULL
463d2201f2fSdrahn       && bfd_get_symcount (abfd) != 0)
464d2201f2fSdrahn     {
465d2201f2fSdrahn       if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0)
466d2201f2fSdrahn 	return FALSE;
467d2201f2fSdrahn 
468d2201f2fSdrahn       if (! NAME(aout,write_syms) (abfd))
469d2201f2fSdrahn 	return FALSE;
470d2201f2fSdrahn     }
471d2201f2fSdrahn 
472d2201f2fSdrahn   if (obj_textsec (abfd)->reloc_count > 0 ||
473d2201f2fSdrahn       obj_datasec (abfd)->reloc_count > 0)
474d2201f2fSdrahn     {
475d2201f2fSdrahn       if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET) != 0)
476d2201f2fSdrahn 	return FALSE;
477d2201f2fSdrahn       if (!NAME(aout,squirt_out_relocs) (abfd, obj_textsec (abfd)))
478d2201f2fSdrahn 	return FALSE;
479d2201f2fSdrahn 
480d2201f2fSdrahn       if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET) != 0)
481d2201f2fSdrahn 	return FALSE;
482d2201f2fSdrahn       if (!NAME(aout,squirt_out_relocs) (abfd, obj_datasec (abfd)))
483d2201f2fSdrahn 	return FALSE;
484d2201f2fSdrahn     }
485d2201f2fSdrahn 
486d2201f2fSdrahn   return TRUE;
487d2201f2fSdrahn }
488d2201f2fSdrahn 
489d2201f2fSdrahn /* Write an object file.
490d2201f2fSdrahn    Section contents have already been written.  We write the
491d2201f2fSdrahn    file header, symbols, and relocation.  */
492d2201f2fSdrahn 
493d2201f2fSdrahn static bfd_boolean
494d2201f2fSdrahn MY(write_object_contents) (abfd)
495d2201f2fSdrahn      bfd *abfd;
496d2201f2fSdrahn {
497d2201f2fSdrahn   struct internal_exec *execp = exec_hdr (abfd);
498d2201f2fSdrahn 
499d2201f2fSdrahn   /* We must make certain that the magic number has been set.  This
500d2201f2fSdrahn      will normally have been done by set_section_contents, but only if
501d2201f2fSdrahn      there actually are some section contents.  */
502d2201f2fSdrahn   if (! abfd->output_has_begun)
503d2201f2fSdrahn     {
504d2201f2fSdrahn       bfd_size_type text_size;
505d2201f2fSdrahn       file_ptr text_end;
506d2201f2fSdrahn 
507d2201f2fSdrahn       NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
508d2201f2fSdrahn     }
509d2201f2fSdrahn 
510d2201f2fSdrahn   obj_reloc_entry_size (abfd) = RELOC_SIZE;
511d2201f2fSdrahn 
512d2201f2fSdrahn   return WRITE_HEADERS(abfd, execp);
513d2201f2fSdrahn }
514d2201f2fSdrahn 
515d2201f2fSdrahn /*
516d2201f2fSdrahn SUBSECTION
517d2201f2fSdrahn 	Internal entry points
518d2201f2fSdrahn 
519d2201f2fSdrahn DESCRIPTION
520d2201f2fSdrahn 	@file{aoutx.h} exports several routines for accessing the
521d2201f2fSdrahn 	contents of an a.out file, which are gathered and exported in
522d2201f2fSdrahn 	turn by various format specific files (eg sunos.c).
523d2201f2fSdrahn 
524d2201f2fSdrahn */
525d2201f2fSdrahn 
526d2201f2fSdrahn /*
527d2201f2fSdrahn FUNCTION
528d2201f2fSdrahn 	 aout_@var{size}_swap_exec_header_in
529d2201f2fSdrahn 
530d2201f2fSdrahn SYNOPSIS
531d2201f2fSdrahn 	void aout_@var{size}_swap_exec_header_in,
532d2201f2fSdrahn            (bfd *abfd,
533d2201f2fSdrahn             struct external_exec *raw_bytes,
534d2201f2fSdrahn             struct internal_exec *execp);
535d2201f2fSdrahn 
536d2201f2fSdrahn DESCRIPTION
537d2201f2fSdrahn 	Swap the information in an executable header @var{raw_bytes} taken
538d2201f2fSdrahn 	from a raw byte stream memory image into the internal exec header
539d2201f2fSdrahn 	structure @var{execp}.
540d2201f2fSdrahn */
541d2201f2fSdrahn 
542d2201f2fSdrahn #ifndef NAME_swap_exec_header_in
543d2201f2fSdrahn void
544d2201f2fSdrahn NAME(aout,swap_exec_header_in) (abfd, raw_bytes, execp)
545d2201f2fSdrahn      bfd *abfd;
546d2201f2fSdrahn      struct external_exec *raw_bytes;
547d2201f2fSdrahn      struct internal_exec *execp;
548d2201f2fSdrahn {
549d2201f2fSdrahn   struct external_exec *bytes = (struct external_exec *)raw_bytes;
550d2201f2fSdrahn 
551d2201f2fSdrahn   /* The internal_exec structure has some fields that are unused in this
552d2201f2fSdrahn      configuration (IE for i960), so ensure that all such uninitialized
553d2201f2fSdrahn      fields are zero'd out.  There are places where two of these structs
554d2201f2fSdrahn      are memcmp'd, and thus the contents do matter. */
555d2201f2fSdrahn   memset ((PTR) execp, 0, sizeof (struct internal_exec));
556d2201f2fSdrahn   /* Now fill in fields in the execp, from the bytes in the raw data.  */
557d2201f2fSdrahn   execp->a_info   = GET_MAGIC (abfd, bytes->e_info);
558d2201f2fSdrahn   execp->a_text   = GET_WORD (abfd, bytes->e_text);
559d2201f2fSdrahn   execp->a_data   = GET_WORD (abfd, bytes->e_data);
560d2201f2fSdrahn   execp->a_bss    = GET_WORD (abfd, bytes->e_bss);
561d2201f2fSdrahn   execp->a_syms   = GET_WORD (abfd, bytes->e_syms);
562d2201f2fSdrahn   execp->a_entry  = GET_WORD (abfd, bytes->e_entry);
563d2201f2fSdrahn 
564d2201f2fSdrahn   if (GET_WORD (abfd, bytes->e_flag) & A_FLAG_RELOC_STRIPPED)
565d2201f2fSdrahn     {
566d2201f2fSdrahn       execp->a_trsize = 0;
567d2201f2fSdrahn       execp->a_drsize = 0;
568d2201f2fSdrahn     }
569d2201f2fSdrahn   else
570d2201f2fSdrahn     {
571d2201f2fSdrahn       execp->a_trsize = execp->a_text;
572d2201f2fSdrahn       execp->a_drsize = execp->a_data;
573d2201f2fSdrahn     }
574d2201f2fSdrahn }
575d2201f2fSdrahn #define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in)
576d2201f2fSdrahn #endif
577d2201f2fSdrahn 
578d2201f2fSdrahn /*
579d2201f2fSdrahn FUNCTION
580d2201f2fSdrahn 	aout_@var{size}_swap_exec_header_out
581d2201f2fSdrahn 
582d2201f2fSdrahn SYNOPSIS
583d2201f2fSdrahn 	void aout_@var{size}_swap_exec_header_out
584d2201f2fSdrahn 	  (bfd *abfd,
585d2201f2fSdrahn 	   struct internal_exec *execp,
586d2201f2fSdrahn 	   struct external_exec *raw_bytes);
587d2201f2fSdrahn 
588d2201f2fSdrahn DESCRIPTION
589d2201f2fSdrahn 	Swap the information in an internal exec header structure
590d2201f2fSdrahn 	@var{execp} into the buffer @var{raw_bytes} ready for writing to disk.
591d2201f2fSdrahn */
592d2201f2fSdrahn void
593d2201f2fSdrahn NAME(aout,swap_exec_header_out) (abfd, execp, raw_bytes)
594d2201f2fSdrahn      bfd *abfd;
595d2201f2fSdrahn      struct internal_exec *execp;
596d2201f2fSdrahn      struct external_exec *raw_bytes;
597d2201f2fSdrahn {
598d2201f2fSdrahn   struct external_exec *bytes = (struct external_exec *)raw_bytes;
599d2201f2fSdrahn 
600d2201f2fSdrahn   /* Now fill in fields in the raw data, from the fields in the exec struct. */
601d2201f2fSdrahn   PUT_MAGIC (abfd, execp->a_info,		bytes->e_info);
602d2201f2fSdrahn   PUT_WORD (abfd, execp->a_text,		bytes->e_text);
603d2201f2fSdrahn   PUT_WORD (abfd, execp->a_data,		bytes->e_data);
604d2201f2fSdrahn   PUT_WORD (abfd, execp->a_bss,			bytes->e_bss);
605d2201f2fSdrahn   PUT_WORD (abfd, execp->a_syms,		bytes->e_syms);
606d2201f2fSdrahn   PUT_WORD (abfd, execp->a_entry,		bytes->e_entry);
607d2201f2fSdrahn   PUT_WORD (abfd, 0,				bytes->e_unused);
608d2201f2fSdrahn 
609d2201f2fSdrahn   if ((execp->a_trsize == 0 || execp->a_text == 0) &&
610d2201f2fSdrahn       (execp->a_drsize == 0 || execp->a_data == 0))
611d2201f2fSdrahn     PUT_WORD (abfd, A_FLAG_RELOC_STRIPPED,	bytes->e_flag);
612d2201f2fSdrahn   else if (execp->a_trsize == execp->a_text &&
613d2201f2fSdrahn 	   execp->a_drsize == execp->a_data)
614d2201f2fSdrahn     PUT_WORD (abfd, 0,				bytes->e_flag);
615d2201f2fSdrahn   else
616d2201f2fSdrahn     {
617d2201f2fSdrahn       /* TODO: print a proper warning message */
618d2201f2fSdrahn       fprintf (stderr, "BFD:%s:%d: internal error\n", __FILE__, __LINE__);
619d2201f2fSdrahn       PUT_WORD (abfd, 0,			bytes->e_flag);
620d2201f2fSdrahn     }
621d2201f2fSdrahn }
622d2201f2fSdrahn 
623d2201f2fSdrahn /* Make all the section for an a.out file.  */
624d2201f2fSdrahn 
625d2201f2fSdrahn bfd_boolean
626d2201f2fSdrahn NAME(aout,make_sections) (abfd)
627d2201f2fSdrahn      bfd *abfd;
628d2201f2fSdrahn {
629d2201f2fSdrahn   if (obj_textsec (abfd) == (asection *) NULL
630d2201f2fSdrahn       && bfd_make_section (abfd, ".text") == (asection *) NULL)
631d2201f2fSdrahn     return FALSE;
632d2201f2fSdrahn   if (obj_datasec (abfd) == (asection *) NULL
633d2201f2fSdrahn       && bfd_make_section (abfd, ".data") == (asection *) NULL)
634d2201f2fSdrahn     return FALSE;
635d2201f2fSdrahn   if (obj_bsssec (abfd) == (asection *) NULL
636d2201f2fSdrahn       && bfd_make_section (abfd, ".bss") == (asection *) NULL)
637d2201f2fSdrahn     return FALSE;
638d2201f2fSdrahn   return TRUE;
639d2201f2fSdrahn }
640d2201f2fSdrahn 
641d2201f2fSdrahn /*
642d2201f2fSdrahn FUNCTION
643d2201f2fSdrahn 	aout_@var{size}_some_aout_object_p
644d2201f2fSdrahn 
645d2201f2fSdrahn SYNOPSIS
646d2201f2fSdrahn 	const bfd_target *aout_@var{size}_some_aout_object_p
647d2201f2fSdrahn 	 (bfd *abfd,
648d2201f2fSdrahn 	  const bfd_target *(*callback_to_real_object_p)());
649d2201f2fSdrahn 
650d2201f2fSdrahn DESCRIPTION
651d2201f2fSdrahn 	Some a.out variant thinks that the file open in @var{abfd}
652d2201f2fSdrahn 	checking is an a.out file.  Do some more checking, and set up
653d2201f2fSdrahn 	for access if it really is.  Call back to the calling
654d2201f2fSdrahn 	environment's "finish up" function just before returning, to
655d2201f2fSdrahn 	handle any last-minute setup.
656d2201f2fSdrahn */
657d2201f2fSdrahn 
658d2201f2fSdrahn const bfd_target *
659d2201f2fSdrahn NAME(aout,some_aout_object_p) (abfd, execp, callback_to_real_object_p)
660d2201f2fSdrahn      bfd *abfd;
661d2201f2fSdrahn      struct internal_exec *execp;
662d2201f2fSdrahn      const bfd_target *(*callback_to_real_object_p) PARAMS ((bfd *));
663d2201f2fSdrahn {
664d2201f2fSdrahn   struct aout_data_struct *rawptr, *oldrawptr;
665d2201f2fSdrahn   const bfd_target *result;
666d2201f2fSdrahn   bfd_size_type amt = sizeof (struct aout_data_struct);
667d2201f2fSdrahn 
668d2201f2fSdrahn   rawptr = (struct aout_data_struct  *) bfd_zalloc (abfd, amt);
669d2201f2fSdrahn   if (rawptr == NULL)
670d2201f2fSdrahn     return 0;
671d2201f2fSdrahn 
672d2201f2fSdrahn   oldrawptr = abfd->tdata.aout_data;
673d2201f2fSdrahn   abfd->tdata.aout_data = rawptr;
674d2201f2fSdrahn 
675d2201f2fSdrahn   /* Copy the contents of the old tdata struct.
676d2201f2fSdrahn      In particular, we want the subformat, since for hpux it was set in
677d2201f2fSdrahn      hp300hpux.c:swap_exec_header_in and will be used in
678d2201f2fSdrahn      hp300hpux.c:callback.  */
679d2201f2fSdrahn   if (oldrawptr != NULL)
680d2201f2fSdrahn     *abfd->tdata.aout_data = *oldrawptr;
681d2201f2fSdrahn 
682d2201f2fSdrahn   abfd->tdata.aout_data->a.hdr = &rawptr->e;
683d2201f2fSdrahn   *(abfd->tdata.aout_data->a.hdr) = *execp;	/* Copy in the internal_exec struct */
684d2201f2fSdrahn   execp = abfd->tdata.aout_data->a.hdr;
685d2201f2fSdrahn 
686d2201f2fSdrahn   /* Set the file flags */
687d2201f2fSdrahn   abfd->flags = BFD_NO_FLAGS;
688d2201f2fSdrahn   if (execp->a_drsize || execp->a_trsize)
689d2201f2fSdrahn     abfd->flags |= HAS_RELOC;
690d2201f2fSdrahn   /* Setting of EXEC_P has been deferred to the bottom of this function */
691d2201f2fSdrahn   if (execp->a_syms)
692d2201f2fSdrahn     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
693d2201f2fSdrahn   if (N_DYNAMIC(*execp))
694d2201f2fSdrahn     abfd->flags |= DYNAMIC;
695d2201f2fSdrahn 
696d2201f2fSdrahn   if (N_MAGIC (*execp) == ZMAGIC)
697d2201f2fSdrahn     {
698d2201f2fSdrahn       abfd->flags |= D_PAGED | WP_TEXT;
699d2201f2fSdrahn       adata (abfd).magic = z_magic;
700d2201f2fSdrahn     }
701d2201f2fSdrahn   else if (N_MAGIC (*execp) == QMAGIC)
702d2201f2fSdrahn     {
703d2201f2fSdrahn       abfd->flags |= D_PAGED | WP_TEXT;
704d2201f2fSdrahn       adata (abfd).magic = z_magic;
705d2201f2fSdrahn       adata (abfd).subformat = q_magic_format;
706d2201f2fSdrahn     }
707d2201f2fSdrahn   else if (N_MAGIC (*execp) == NMAGIC)
708d2201f2fSdrahn     {
709d2201f2fSdrahn       abfd->flags |= WP_TEXT;
710d2201f2fSdrahn       adata (abfd).magic = n_magic;
711d2201f2fSdrahn     }
712d2201f2fSdrahn   else if (N_MAGIC (*execp) == OMAGIC
713d2201f2fSdrahn 	   || N_MAGIC (*execp) == BMAGIC)
714d2201f2fSdrahn     adata (abfd).magic = o_magic;
715d2201f2fSdrahn   else
716d2201f2fSdrahn     {
717d2201f2fSdrahn       /* Should have been checked with N_BADMAG before this routine
718d2201f2fSdrahn 	 was called.  */
719d2201f2fSdrahn       abort ();
720d2201f2fSdrahn     }
721d2201f2fSdrahn 
722d2201f2fSdrahn   bfd_get_start_address (abfd) = execp->a_entry;
723d2201f2fSdrahn 
724d2201f2fSdrahn   obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
725d2201f2fSdrahn   bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
726d2201f2fSdrahn 
727d2201f2fSdrahn   /* The default relocation entry size is that of traditional V7 Unix.  */
728d2201f2fSdrahn   obj_reloc_entry_size (abfd) = RELOC_SIZE;
729d2201f2fSdrahn 
730d2201f2fSdrahn   /* The default symbol entry size is that of traditional Unix. */
731d2201f2fSdrahn   obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
732d2201f2fSdrahn 
733d2201f2fSdrahn #ifdef USE_MMAP
734d2201f2fSdrahn   bfd_init_window (&obj_aout_sym_window (abfd));
735d2201f2fSdrahn   bfd_init_window (&obj_aout_string_window (abfd));
736d2201f2fSdrahn #endif
737d2201f2fSdrahn   obj_aout_external_syms (abfd) = NULL;
738d2201f2fSdrahn   obj_aout_external_strings (abfd) = NULL;
739d2201f2fSdrahn   obj_aout_sym_hashes (abfd) = NULL;
740d2201f2fSdrahn 
741d2201f2fSdrahn   if (! NAME(aout,make_sections) (abfd))
742d2201f2fSdrahn     return NULL;
743d2201f2fSdrahn 
744d2201f2fSdrahn   obj_datasec (abfd)->_raw_size = execp->a_data;
745d2201f2fSdrahn   obj_bsssec (abfd)->_raw_size = execp->a_bss;
746d2201f2fSdrahn 
747d2201f2fSdrahn   obj_textsec (abfd)->flags =
748d2201f2fSdrahn     (execp->a_trsize != 0
749d2201f2fSdrahn      ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
750d2201f2fSdrahn      : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
751d2201f2fSdrahn   obj_datasec (abfd)->flags =
752d2201f2fSdrahn     (execp->a_drsize != 0
753d2201f2fSdrahn      ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
754d2201f2fSdrahn      : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
755d2201f2fSdrahn   obj_bsssec (abfd)->flags = SEC_ALLOC;
756d2201f2fSdrahn 
757d2201f2fSdrahn #ifdef THIS_IS_ONLY_DOCUMENTATION
758d2201f2fSdrahn   /* The common code can't fill in these things because they depend
759d2201f2fSdrahn      on either the start address of the text segment, the rounding
760d2201f2fSdrahn      up of virtual addresses between segments, or the starting file
761d2201f2fSdrahn      position of the text segment -- all of which varies among different
762d2201f2fSdrahn      versions of a.out.  */
763d2201f2fSdrahn 
764d2201f2fSdrahn   /* Call back to the format-dependent code to fill in the rest of the
765d2201f2fSdrahn      fields and do any further cleanup.  Things that should be filled
766d2201f2fSdrahn      in by the callback:  */
767d2201f2fSdrahn 
768d2201f2fSdrahn   struct exec *execp = exec_hdr (abfd);
769d2201f2fSdrahn 
770d2201f2fSdrahn   obj_textsec (abfd)->size = N_TXTSIZE(*execp);
771d2201f2fSdrahn   obj_textsec (abfd)->raw_size = N_TXTSIZE(*execp);
772d2201f2fSdrahn   /* data and bss are already filled in since they're so standard */
773d2201f2fSdrahn 
774d2201f2fSdrahn   /* The virtual memory addresses of the sections */
775d2201f2fSdrahn   obj_textsec (abfd)->vma = N_TXTADDR(*execp);
776d2201f2fSdrahn   obj_datasec (abfd)->vma = N_DATADDR(*execp);
777d2201f2fSdrahn   obj_bsssec  (abfd)->vma = N_BSSADDR(*execp);
778d2201f2fSdrahn 
779d2201f2fSdrahn   /* The file offsets of the sections */
780d2201f2fSdrahn   obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
781d2201f2fSdrahn   obj_datasec (abfd)->filepos = N_DATOFF(*execp);
782d2201f2fSdrahn 
783d2201f2fSdrahn   /* The file offsets of the relocation info */
784d2201f2fSdrahn   obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
785d2201f2fSdrahn   obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
786d2201f2fSdrahn 
787d2201f2fSdrahn   /* The file offsets of the string table and symbol table.  */
788d2201f2fSdrahn   obj_str_filepos (abfd) = N_STROFF (*execp);
789d2201f2fSdrahn   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
790d2201f2fSdrahn 
791d2201f2fSdrahn   /* Determine the architecture and machine type of the object file.  */
792d2201f2fSdrahn   abfd->obj_arch = bfd_arch_obscure;
793d2201f2fSdrahn 
794d2201f2fSdrahn   adata(abfd)->page_size = TARGET_PAGE_SIZE;
795d2201f2fSdrahn   adata(abfd)->segment_size = SEGMENT_SIZE;
796d2201f2fSdrahn   adata(abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
797d2201f2fSdrahn 
798d2201f2fSdrahn   return abfd->xvec;
799d2201f2fSdrahn 
800d2201f2fSdrahn   /* The architecture is encoded in various ways in various a.out variants,
801d2201f2fSdrahn      or is not encoded at all in some of them.  The relocation size depends
802d2201f2fSdrahn      on the architecture and the a.out variant.  Finally, the return value
803d2201f2fSdrahn      is the bfd_target vector in use.  If an error occurs, return zero and
804d2201f2fSdrahn      set bfd_error to the appropriate error code.
805d2201f2fSdrahn 
806d2201f2fSdrahn      Formats such as b.out, which have additional fields in the a.out
807d2201f2fSdrahn      header, should cope with them in this callback as well.  */
808d2201f2fSdrahn #endif				/* DOCUMENTATION */
809d2201f2fSdrahn 
810d2201f2fSdrahn   result = (*callback_to_real_object_p)(abfd);
811d2201f2fSdrahn 
812d2201f2fSdrahn   /* Now that the segment addresses have been worked out, take a better
813d2201f2fSdrahn      guess at whether the file is executable.  If the entry point
814d2201f2fSdrahn      is within the text segment, assume it is.  (This makes files
815d2201f2fSdrahn      executable even if their entry point address is 0, as long as
816d2201f2fSdrahn      their text starts at zero.).
817d2201f2fSdrahn 
818d2201f2fSdrahn      This test had to be changed to deal with systems where the text segment
819d2201f2fSdrahn      runs at a different location than the default.  The problem is that the
820d2201f2fSdrahn      entry address can appear to be outside the text segment, thus causing an
821d2201f2fSdrahn      erroneous conclusion that the file isn't executable.
822d2201f2fSdrahn 
823d2201f2fSdrahn      To fix this, we now accept any non-zero entry point as an indication of
824d2201f2fSdrahn      executability.  This will work most of the time, since only the linker
825d2201f2fSdrahn      sets the entry point, and that is likely to be non-zero for most systems. */
826d2201f2fSdrahn 
827d2201f2fSdrahn   if (execp->a_entry != 0
828d2201f2fSdrahn       || (execp->a_entry >= obj_textsec(abfd)->vma
829d2201f2fSdrahn 	  && execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
830d2201f2fSdrahn     abfd->flags |= EXEC_P;
831d2201f2fSdrahn #ifdef STAT_FOR_EXEC
832d2201f2fSdrahn   else
833d2201f2fSdrahn     {
834d2201f2fSdrahn       struct stat stat_buf;
835d2201f2fSdrahn 
836d2201f2fSdrahn       /* The original heuristic doesn't work in some important cases.
837d2201f2fSdrahn         The a.out file has no information about the text start
838d2201f2fSdrahn         address.  For files (like kernels) linked to non-standard
839d2201f2fSdrahn         addresses (ld -Ttext nnn) the entry point may not be between
840d2201f2fSdrahn         the default text start (obj_textsec(abfd)->vma) and
841d2201f2fSdrahn         (obj_textsec(abfd)->vma) + text size.  This is not just a mach
842d2201f2fSdrahn         issue.  Many kernels are loaded at non standard addresses.  */
843d2201f2fSdrahn       if (abfd->iostream != NULL
844d2201f2fSdrahn 	  && (abfd->flags & BFD_IN_MEMORY) == 0
845d2201f2fSdrahn 	  && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
846d2201f2fSdrahn 	  && ((stat_buf.st_mode & 0111) != 0))
847d2201f2fSdrahn 	abfd->flags |= EXEC_P;
848d2201f2fSdrahn     }
849d2201f2fSdrahn #endif /* STAT_FOR_EXEC */
850d2201f2fSdrahn 
851d2201f2fSdrahn   if (result)
852d2201f2fSdrahn     {
853d2201f2fSdrahn #if 0 /* These should be set correctly anyways.  */
854d2201f2fSdrahn       abfd->sections = obj_textsec (abfd);
855d2201f2fSdrahn       obj_textsec (abfd)->next = obj_datasec (abfd);
856d2201f2fSdrahn       obj_datasec (abfd)->next = obj_bsssec (abfd);
857d2201f2fSdrahn #endif
858d2201f2fSdrahn     }
859d2201f2fSdrahn   else
860d2201f2fSdrahn     {
861d2201f2fSdrahn       free (rawptr);
862d2201f2fSdrahn       abfd->tdata.aout_data = oldrawptr;
863d2201f2fSdrahn     }
864d2201f2fSdrahn   return result;
865d2201f2fSdrahn }
866d2201f2fSdrahn 
867d2201f2fSdrahn /*
868d2201f2fSdrahn FUNCTION
869d2201f2fSdrahn 	aout_@var{size}_mkobject
870d2201f2fSdrahn 
871d2201f2fSdrahn SYNOPSIS
872d2201f2fSdrahn 	bfd_boolean aout_@var{size}_mkobject, (bfd *abfd);
873d2201f2fSdrahn 
874d2201f2fSdrahn DESCRIPTION
875d2201f2fSdrahn 	Initialize BFD @var{abfd} for use with a.out files.
876d2201f2fSdrahn */
877d2201f2fSdrahn 
878d2201f2fSdrahn bfd_boolean
879d2201f2fSdrahn NAME(aout,mkobject) (abfd)
880d2201f2fSdrahn      bfd *abfd;
881d2201f2fSdrahn {
882d2201f2fSdrahn   struct aout_data_struct  *rawptr;
883d2201f2fSdrahn   bfd_size_type amt = sizeof (struct aout_data_struct);
884d2201f2fSdrahn 
885d2201f2fSdrahn   bfd_set_error (bfd_error_system_call);
886d2201f2fSdrahn 
887d2201f2fSdrahn   /* Use an intermediate variable for clarity */
888d2201f2fSdrahn   rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
889d2201f2fSdrahn 
890d2201f2fSdrahn   if (rawptr == NULL)
891d2201f2fSdrahn     return FALSE;
892d2201f2fSdrahn 
893d2201f2fSdrahn   abfd->tdata.aout_data = rawptr;
894d2201f2fSdrahn   exec_hdr (abfd) = &(rawptr->e);
895d2201f2fSdrahn 
896d2201f2fSdrahn   obj_textsec (abfd) = (asection *)NULL;
897d2201f2fSdrahn   obj_datasec (abfd) = (asection *)NULL;
898d2201f2fSdrahn   obj_bsssec (abfd) = (asection *)NULL;
899d2201f2fSdrahn 
900d2201f2fSdrahn   return TRUE;
901d2201f2fSdrahn }
902d2201f2fSdrahn 
903d2201f2fSdrahn 
904d2201f2fSdrahn /*
905d2201f2fSdrahn FUNCTION
906d2201f2fSdrahn 	aout_@var{size}_machine_type
907d2201f2fSdrahn 
908d2201f2fSdrahn SYNOPSIS
909d2201f2fSdrahn 	enum machine_type  aout_@var{size}_machine_type
910d2201f2fSdrahn 	 (enum bfd_architecture arch,
911d2201f2fSdrahn 	  unsigned long machine));
912d2201f2fSdrahn 
913d2201f2fSdrahn DESCRIPTION
914d2201f2fSdrahn 	Keep track of machine architecture and machine type for
915d2201f2fSdrahn 	a.out's. Return the <<machine_type>> for a particular
916d2201f2fSdrahn 	architecture and machine, or <<M_UNKNOWN>> if that exact architecture
917d2201f2fSdrahn 	and machine can't be represented in a.out format.
918d2201f2fSdrahn 
919d2201f2fSdrahn 	If the architecture is understood, machine type 0 (default)
920d2201f2fSdrahn 	is always understood.
921d2201f2fSdrahn */
922d2201f2fSdrahn 
923d2201f2fSdrahn enum machine_type
924d2201f2fSdrahn NAME(aout,machine_type) (arch, machine, unknown)
925d2201f2fSdrahn      enum bfd_architecture arch;
926d2201f2fSdrahn      unsigned long machine;
927d2201f2fSdrahn      bfd_boolean *unknown;
928d2201f2fSdrahn {
929d2201f2fSdrahn   enum machine_type arch_flags;
930d2201f2fSdrahn 
931d2201f2fSdrahn   arch_flags = M_UNKNOWN;
932d2201f2fSdrahn   *unknown = TRUE;
933d2201f2fSdrahn 
934d2201f2fSdrahn   switch (arch)
935d2201f2fSdrahn     {
936d2201f2fSdrahn     case bfd_arch_sparc:
937d2201f2fSdrahn       if (machine == 0
938d2201f2fSdrahn 	  || machine == bfd_mach_sparc
939d2201f2fSdrahn 	  || machine == bfd_mach_sparc_sparclite
940d2201f2fSdrahn 	  || machine == bfd_mach_sparc_v9)
941d2201f2fSdrahn 	arch_flags = M_SPARC;
942d2201f2fSdrahn       else if (machine == bfd_mach_sparc_sparclet)
943d2201f2fSdrahn 	arch_flags = M_SPARCLET;
944d2201f2fSdrahn       break;
945d2201f2fSdrahn 
946d2201f2fSdrahn     case bfd_arch_m68k:
947d2201f2fSdrahn       switch (machine)
948d2201f2fSdrahn 	{
949d2201f2fSdrahn 	case 0:		      arch_flags = M_68010; break;
950d2201f2fSdrahn 	case bfd_mach_m68000: arch_flags = M_UNKNOWN; *unknown = FALSE; break;
951d2201f2fSdrahn 	case bfd_mach_m68010: arch_flags = M_68010; break;
952d2201f2fSdrahn 	case bfd_mach_m68020: arch_flags = M_68020; break;
953d2201f2fSdrahn 	default:	      arch_flags = M_UNKNOWN; break;
954d2201f2fSdrahn 	}
955d2201f2fSdrahn       break;
956d2201f2fSdrahn 
957d2201f2fSdrahn     case bfd_arch_i386:
958d2201f2fSdrahn       if (machine == 0
959d2201f2fSdrahn 	  || machine == bfd_mach_i386_i386
960d2201f2fSdrahn 	  || machine == bfd_mach_i386_i386_intel_syntax)
961d2201f2fSdrahn 	arch_flags = M_386;
962d2201f2fSdrahn       break;
963d2201f2fSdrahn 
964d2201f2fSdrahn     case bfd_arch_a29k:
965d2201f2fSdrahn       if (machine == 0)	arch_flags = M_29K;
966d2201f2fSdrahn       break;
967d2201f2fSdrahn 
968d2201f2fSdrahn     case bfd_arch_arm:
969d2201f2fSdrahn       if (machine == 0)	arch_flags = M_ARM;
970d2201f2fSdrahn       break;
971d2201f2fSdrahn 
972d2201f2fSdrahn     case bfd_arch_mips:
973d2201f2fSdrahn       switch (machine)
974d2201f2fSdrahn 	{
975d2201f2fSdrahn 	case 0:
976d2201f2fSdrahn 	case 2000:
977d2201f2fSdrahn 	case bfd_mach_mips3000:
978d2201f2fSdrahn           arch_flags = M_MIPS1;
979d2201f2fSdrahn 	  break;
980d2201f2fSdrahn 	case bfd_mach_mips4000: /* mips3 */
981d2201f2fSdrahn 	case bfd_mach_mips4400:
982d2201f2fSdrahn 	case bfd_mach_mips8000: /* mips4 */
983d2201f2fSdrahn 	case bfd_mach_mips6000: /* real mips2: */
984d2201f2fSdrahn           arch_flags = M_MIPS2;
985d2201f2fSdrahn 	  break;
986d2201f2fSdrahn 	default:
987d2201f2fSdrahn 	  arch_flags = M_UNKNOWN;
988d2201f2fSdrahn 	  break;
989d2201f2fSdrahn 	}
990d2201f2fSdrahn       break;
991d2201f2fSdrahn 
992d2201f2fSdrahn     case bfd_arch_ns32k:
993d2201f2fSdrahn       switch (machine)
994d2201f2fSdrahn 	{
995d2201f2fSdrahn 	case 0:    		arch_flags = M_NS32532; break;
996d2201f2fSdrahn 	case 32032:		arch_flags = M_NS32032; break;
997d2201f2fSdrahn 	case 32532:		arch_flags = M_NS32532; break;
998d2201f2fSdrahn 	default:		arch_flags = M_UNKNOWN; break;
999d2201f2fSdrahn 	}
1000d2201f2fSdrahn       break;
1001d2201f2fSdrahn 
1002d2201f2fSdrahn     case bfd_arch_pdp11:
1003d2201f2fSdrahn       /* TODO: arch_flags = M_PDP11; */
1004d2201f2fSdrahn       *unknown = FALSE;
1005d2201f2fSdrahn       break;
1006d2201f2fSdrahn 
1007d2201f2fSdrahn     case bfd_arch_vax:
1008d2201f2fSdrahn       *unknown = FALSE;
1009d2201f2fSdrahn       break;
1010d2201f2fSdrahn 
1011d2201f2fSdrahn     default:
1012d2201f2fSdrahn       arch_flags = M_UNKNOWN;
1013d2201f2fSdrahn     }
1014d2201f2fSdrahn 
1015d2201f2fSdrahn   if (arch_flags != M_UNKNOWN)
1016d2201f2fSdrahn     *unknown = FALSE;
1017d2201f2fSdrahn 
1018d2201f2fSdrahn   return arch_flags;
1019d2201f2fSdrahn }
1020d2201f2fSdrahn 
1021d2201f2fSdrahn 
1022d2201f2fSdrahn /*
1023d2201f2fSdrahn FUNCTION
1024d2201f2fSdrahn 	aout_@var{size}_set_arch_mach
1025d2201f2fSdrahn 
1026d2201f2fSdrahn SYNOPSIS
1027d2201f2fSdrahn 	bfd_boolean aout_@var{size}_set_arch_mach,
1028d2201f2fSdrahn 	 (bfd *,
1029d2201f2fSdrahn 	  enum bfd_architecture arch,
1030d2201f2fSdrahn 	  unsigned long machine));
1031d2201f2fSdrahn 
1032d2201f2fSdrahn DESCRIPTION
1033d2201f2fSdrahn 	Set the architecture and the machine of the BFD @var{abfd} to the
1034d2201f2fSdrahn 	values @var{arch} and @var{machine}.  Verify that @var{abfd}'s format
1035d2201f2fSdrahn 	can support the architecture required.
1036d2201f2fSdrahn */
1037d2201f2fSdrahn 
1038d2201f2fSdrahn bfd_boolean
1039d2201f2fSdrahn NAME(aout,set_arch_mach) (abfd, arch, machine)
1040d2201f2fSdrahn      bfd *abfd;
1041d2201f2fSdrahn      enum bfd_architecture arch;
1042d2201f2fSdrahn      unsigned long machine;
1043d2201f2fSdrahn {
1044d2201f2fSdrahn   if (! bfd_default_set_arch_mach (abfd, arch, machine))
1045d2201f2fSdrahn     return FALSE;
1046d2201f2fSdrahn 
1047d2201f2fSdrahn   if (arch != bfd_arch_unknown)
1048d2201f2fSdrahn     {
1049d2201f2fSdrahn       bfd_boolean unknown;
1050d2201f2fSdrahn 
1051d2201f2fSdrahn       NAME(aout,machine_type) (arch, machine, &unknown);
1052d2201f2fSdrahn       if (unknown)
1053d2201f2fSdrahn 	return FALSE;
1054d2201f2fSdrahn     }
1055d2201f2fSdrahn 
1056d2201f2fSdrahn   obj_reloc_entry_size (abfd) = RELOC_SIZE;
1057d2201f2fSdrahn 
1058d2201f2fSdrahn   return (*aout_backend_info(abfd)->set_sizes) (abfd);
1059d2201f2fSdrahn }
1060d2201f2fSdrahn 
1061d2201f2fSdrahn static void
adjust_o_magic(abfd,execp)1062d2201f2fSdrahn adjust_o_magic (abfd, execp)
1063d2201f2fSdrahn      bfd *abfd;
1064d2201f2fSdrahn      struct internal_exec *execp;
1065d2201f2fSdrahn {
1066d2201f2fSdrahn   file_ptr pos = adata (abfd).exec_bytes_size;
1067d2201f2fSdrahn   bfd_vma vma = 0;
1068d2201f2fSdrahn   int pad = 0;
1069d2201f2fSdrahn 
1070d2201f2fSdrahn   /* Text.  */
1071d2201f2fSdrahn   obj_textsec (abfd)->filepos = pos;
1072d2201f2fSdrahn   if (! obj_textsec (abfd)->user_set_vma)
1073d2201f2fSdrahn     obj_textsec (abfd)->vma = vma;
1074d2201f2fSdrahn   else
1075d2201f2fSdrahn     vma = obj_textsec (abfd)->vma;
1076d2201f2fSdrahn 
1077d2201f2fSdrahn   pos += obj_textsec (abfd)->_raw_size;
1078d2201f2fSdrahn   vma += obj_textsec (abfd)->_raw_size;
1079d2201f2fSdrahn 
1080d2201f2fSdrahn   /* Data.  */
1081d2201f2fSdrahn   if (!obj_datasec (abfd)->user_set_vma)
1082d2201f2fSdrahn     {
1083d2201f2fSdrahn #if 0	    /* ?? Does alignment in the file image really matter? */
1084d2201f2fSdrahn       pad = align_power (vma, obj_datasec (abfd)->alignment_power) - vma;
1085d2201f2fSdrahn #endif
1086d2201f2fSdrahn       obj_textsec (abfd)->_raw_size += pad;
1087d2201f2fSdrahn       pos += pad;
1088d2201f2fSdrahn       vma += pad;
1089d2201f2fSdrahn       obj_datasec (abfd)->vma = vma;
1090d2201f2fSdrahn     }
1091d2201f2fSdrahn   else
1092d2201f2fSdrahn     vma = obj_datasec (abfd)->vma;
1093d2201f2fSdrahn   obj_datasec (abfd)->filepos = pos;
1094d2201f2fSdrahn   pos += obj_datasec (abfd)->_raw_size;
1095d2201f2fSdrahn   vma += obj_datasec (abfd)->_raw_size;
1096d2201f2fSdrahn 
1097d2201f2fSdrahn   /* BSS.  */
1098d2201f2fSdrahn   if (! obj_bsssec (abfd)->user_set_vma)
1099d2201f2fSdrahn     {
1100d2201f2fSdrahn #if 0
1101d2201f2fSdrahn       pad = align_power (vma, obj_bsssec (abfd)->alignment_power) - vma;
1102d2201f2fSdrahn #endif
1103d2201f2fSdrahn       obj_datasec (abfd)->_raw_size += pad;
1104d2201f2fSdrahn       pos += pad;
1105d2201f2fSdrahn       vma += pad;
1106d2201f2fSdrahn       obj_bsssec (abfd)->vma = vma;
1107d2201f2fSdrahn     }
1108d2201f2fSdrahn   else
1109d2201f2fSdrahn     {
1110d2201f2fSdrahn       /* The VMA of the .bss section is set by the VMA of the
1111d2201f2fSdrahn          .data section plus the size of the .data section.  We may
1112d2201f2fSdrahn          need to add padding bytes to make this true.  */
1113d2201f2fSdrahn       pad = obj_bsssec (abfd)->vma - vma;
1114d2201f2fSdrahn       if (pad > 0)
1115d2201f2fSdrahn 	{
1116d2201f2fSdrahn 	  obj_datasec (abfd)->_raw_size += pad;
1117d2201f2fSdrahn 	  pos += pad;
1118d2201f2fSdrahn 	}
1119d2201f2fSdrahn     }
1120d2201f2fSdrahn   obj_bsssec (abfd)->filepos = pos;
1121d2201f2fSdrahn 
1122d2201f2fSdrahn   /* Fix up the exec header.  */
1123d2201f2fSdrahn   execp->a_text = obj_textsec (abfd)->_raw_size;
1124d2201f2fSdrahn   execp->a_data = obj_datasec (abfd)->_raw_size;
1125d2201f2fSdrahn   execp->a_bss  = obj_bsssec (abfd)->_raw_size;
1126d2201f2fSdrahn   N_SET_MAGIC (*execp, OMAGIC);
1127d2201f2fSdrahn }
1128d2201f2fSdrahn 
1129d2201f2fSdrahn static void
adjust_z_magic(abfd,execp)1130d2201f2fSdrahn adjust_z_magic (abfd, execp)
1131d2201f2fSdrahn      bfd *abfd;
1132d2201f2fSdrahn      struct internal_exec *execp;
1133d2201f2fSdrahn {
1134d2201f2fSdrahn   bfd_size_type data_pad, text_pad;
1135d2201f2fSdrahn   file_ptr text_end;
1136d2201f2fSdrahn   const struct aout_backend_data *abdp;
1137d2201f2fSdrahn   int ztih;			/* Nonzero if text includes exec header.  */
1138d2201f2fSdrahn 
1139d2201f2fSdrahn   abdp = aout_backend_info (abfd);
1140d2201f2fSdrahn 
1141d2201f2fSdrahn   /* Text.  */
1142d2201f2fSdrahn   ztih = (abdp != NULL
1143d2201f2fSdrahn 	  && (abdp->text_includes_header
1144d2201f2fSdrahn 	      || obj_aout_subformat (abfd) == q_magic_format));
1145d2201f2fSdrahn   obj_textsec(abfd)->filepos = (ztih
1146d2201f2fSdrahn 				? adata(abfd).exec_bytes_size
1147d2201f2fSdrahn 				: adata(abfd).zmagic_disk_block_size);
1148d2201f2fSdrahn   if (! obj_textsec(abfd)->user_set_vma)
1149d2201f2fSdrahn     {
1150d2201f2fSdrahn       /* ?? Do we really need to check for relocs here?  */
1151d2201f2fSdrahn       obj_textsec(abfd)->vma = ((abfd->flags & HAS_RELOC)
1152d2201f2fSdrahn 				? 0
1153d2201f2fSdrahn 				: (ztih
1154d2201f2fSdrahn 				   ? (abdp->default_text_vma
1155d2201f2fSdrahn 				      + adata (abfd).exec_bytes_size)
1156d2201f2fSdrahn 				   : abdp->default_text_vma));
1157d2201f2fSdrahn       text_pad = 0;
1158d2201f2fSdrahn     }
1159d2201f2fSdrahn   else
1160d2201f2fSdrahn     {
1161d2201f2fSdrahn       /* The .text section is being loaded at an unusual address.  We
1162d2201f2fSdrahn          may need to pad it such that the .data section starts at a page
1163d2201f2fSdrahn          boundary.  */
1164d2201f2fSdrahn       if (ztih)
1165d2201f2fSdrahn 	text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma)
1166d2201f2fSdrahn 		    & (adata (abfd).page_size - 1));
1167d2201f2fSdrahn       else
1168d2201f2fSdrahn 	text_pad = ((- obj_textsec (abfd)->vma)
1169d2201f2fSdrahn 		    & (adata (abfd).page_size - 1));
1170d2201f2fSdrahn     }
1171d2201f2fSdrahn 
1172d2201f2fSdrahn   /* Find start of data.  */
1173d2201f2fSdrahn   if (ztih)
1174d2201f2fSdrahn     {
1175d2201f2fSdrahn       text_end = obj_textsec (abfd)->filepos + obj_textsec (abfd)->_raw_size;
1176d2201f2fSdrahn       text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
1177d2201f2fSdrahn     }
1178d2201f2fSdrahn   else
1179d2201f2fSdrahn     {
1180d2201f2fSdrahn       /* Note that if page_size == zmagic_disk_block_size, then
1181d2201f2fSdrahn 	 filepos == page_size, and this case is the same as the ztih
1182d2201f2fSdrahn 	 case.  */
1183d2201f2fSdrahn       text_end = obj_textsec (abfd)->_raw_size;
1184d2201f2fSdrahn       text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
1185d2201f2fSdrahn       text_end += obj_textsec (abfd)->filepos;
1186d2201f2fSdrahn     }
1187d2201f2fSdrahn 
1188d2201f2fSdrahn   obj_textsec (abfd)->_raw_size += text_pad;
1189d2201f2fSdrahn   text_end += text_pad;
1190d2201f2fSdrahn 
1191d2201f2fSdrahn   /* Data.  */
1192d2201f2fSdrahn   if (!obj_datasec(abfd)->user_set_vma)
1193d2201f2fSdrahn     {
1194d2201f2fSdrahn       bfd_vma vma;
1195d2201f2fSdrahn       vma = obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size;
1196d2201f2fSdrahn       obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
1197d2201f2fSdrahn     }
1198d2201f2fSdrahn   if (abdp && abdp->zmagic_mapped_contiguous)
1199d2201f2fSdrahn     {
1200d2201f2fSdrahn       text_pad = (obj_datasec(abfd)->vma
1201d2201f2fSdrahn 		  - obj_textsec(abfd)->vma
1202d2201f2fSdrahn 		  - obj_textsec(abfd)->_raw_size);
1203d2201f2fSdrahn       obj_textsec(abfd)->_raw_size += text_pad;
1204d2201f2fSdrahn     }
1205d2201f2fSdrahn   obj_datasec (abfd)->filepos = (obj_textsec (abfd)->filepos
1206d2201f2fSdrahn 				+ obj_textsec (abfd)->_raw_size);
1207d2201f2fSdrahn 
1208d2201f2fSdrahn   /* Fix up exec header while we're at it.  */
1209d2201f2fSdrahn   execp->a_text = obj_textsec(abfd)->_raw_size;
1210d2201f2fSdrahn   if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
1211d2201f2fSdrahn     execp->a_text += adata(abfd).exec_bytes_size;
1212d2201f2fSdrahn   if (obj_aout_subformat (abfd) == q_magic_format)
1213d2201f2fSdrahn     N_SET_MAGIC (*execp, QMAGIC);
1214d2201f2fSdrahn   else
1215d2201f2fSdrahn     N_SET_MAGIC (*execp, ZMAGIC);
1216d2201f2fSdrahn 
1217d2201f2fSdrahn   /* Spec says data section should be rounded up to page boundary.  */
1218d2201f2fSdrahn   obj_datasec(abfd)->_raw_size
1219d2201f2fSdrahn     = align_power (obj_datasec(abfd)->_raw_size,
1220d2201f2fSdrahn 		   obj_bsssec(abfd)->alignment_power);
1221d2201f2fSdrahn   execp->a_data = BFD_ALIGN (obj_datasec(abfd)->_raw_size,
1222d2201f2fSdrahn 			     adata(abfd).page_size);
1223d2201f2fSdrahn   data_pad = execp->a_data - obj_datasec(abfd)->_raw_size;
1224d2201f2fSdrahn 
1225d2201f2fSdrahn   /* BSS.  */
1226d2201f2fSdrahn   if (!obj_bsssec(abfd)->user_set_vma)
1227d2201f2fSdrahn     obj_bsssec(abfd)->vma = (obj_datasec(abfd)->vma
1228d2201f2fSdrahn 			     + obj_datasec(abfd)->_raw_size);
1229d2201f2fSdrahn   /* If the BSS immediately follows the data section and extra space
1230d2201f2fSdrahn      in the page is left after the data section, fudge data
1231d2201f2fSdrahn      in the header so that the bss section looks smaller by that
1232d2201f2fSdrahn      amount.  We'll start the bss section there, and lie to the OS.
1233d2201f2fSdrahn      (Note that a linker script, as well as the above assignment,
1234d2201f2fSdrahn      could have explicitly set the BSS vma to immediately follow
1235d2201f2fSdrahn      the data section.)  */
1236d2201f2fSdrahn   if (align_power (obj_bsssec(abfd)->vma, obj_bsssec(abfd)->alignment_power)
1237d2201f2fSdrahn       == obj_datasec(abfd)->vma + obj_datasec(abfd)->_raw_size)
1238d2201f2fSdrahn     execp->a_bss = (data_pad > obj_bsssec(abfd)->_raw_size) ? 0 :
1239d2201f2fSdrahn       obj_bsssec(abfd)->_raw_size - data_pad;
1240d2201f2fSdrahn   else
1241d2201f2fSdrahn     execp->a_bss = obj_bsssec(abfd)->_raw_size;
1242d2201f2fSdrahn }
1243d2201f2fSdrahn 
1244d2201f2fSdrahn static void
adjust_n_magic(abfd,execp)1245d2201f2fSdrahn adjust_n_magic (abfd, execp)
1246d2201f2fSdrahn      bfd *abfd;
1247d2201f2fSdrahn      struct internal_exec *execp;
1248d2201f2fSdrahn {
1249d2201f2fSdrahn   file_ptr pos = adata(abfd).exec_bytes_size;
1250d2201f2fSdrahn   bfd_vma vma = 0;
1251d2201f2fSdrahn   int pad;
1252d2201f2fSdrahn 
1253d2201f2fSdrahn   /* Text.  */
1254d2201f2fSdrahn   obj_textsec(abfd)->filepos = pos;
1255d2201f2fSdrahn   if (!obj_textsec(abfd)->user_set_vma)
1256d2201f2fSdrahn     obj_textsec(abfd)->vma = vma;
1257d2201f2fSdrahn   else
1258d2201f2fSdrahn     vma = obj_textsec(abfd)->vma;
1259d2201f2fSdrahn   pos += obj_textsec(abfd)->_raw_size;
1260d2201f2fSdrahn   vma += obj_textsec(abfd)->_raw_size;
1261d2201f2fSdrahn 
1262d2201f2fSdrahn   /* Data.  */
1263d2201f2fSdrahn   obj_datasec(abfd)->filepos = pos;
1264d2201f2fSdrahn   if (!obj_datasec(abfd)->user_set_vma)
1265d2201f2fSdrahn     obj_datasec(abfd)->vma = BFD_ALIGN (vma, adata(abfd).segment_size);
1266d2201f2fSdrahn   vma = obj_datasec(abfd)->vma;
1267d2201f2fSdrahn 
1268d2201f2fSdrahn   /* Since BSS follows data immediately, see if it needs alignment.  */
1269d2201f2fSdrahn   vma += obj_datasec(abfd)->_raw_size;
1270d2201f2fSdrahn   pad = align_power (vma, obj_bsssec(abfd)->alignment_power) - vma;
1271d2201f2fSdrahn   obj_datasec(abfd)->_raw_size += pad;
1272d2201f2fSdrahn   pos += obj_datasec(abfd)->_raw_size;
1273d2201f2fSdrahn 
1274d2201f2fSdrahn   /* BSS.  */
1275d2201f2fSdrahn   if (!obj_bsssec(abfd)->user_set_vma)
1276d2201f2fSdrahn     obj_bsssec(abfd)->vma = vma;
1277d2201f2fSdrahn   else
1278d2201f2fSdrahn     vma = obj_bsssec(abfd)->vma;
1279d2201f2fSdrahn 
1280d2201f2fSdrahn   /* Fix up exec header.  */
1281d2201f2fSdrahn   execp->a_text = obj_textsec(abfd)->_raw_size;
1282d2201f2fSdrahn   execp->a_data = obj_datasec(abfd)->_raw_size;
1283d2201f2fSdrahn   execp->a_bss = obj_bsssec(abfd)->_raw_size;
1284d2201f2fSdrahn   N_SET_MAGIC (*execp, NMAGIC);
1285d2201f2fSdrahn }
1286d2201f2fSdrahn 
1287d2201f2fSdrahn bfd_boolean
1288d2201f2fSdrahn NAME(aout,adjust_sizes_and_vmas) (abfd, text_size, text_end)
1289d2201f2fSdrahn      bfd *abfd;
1290d2201f2fSdrahn      bfd_size_type *text_size;
1291d2201f2fSdrahn      file_ptr * text_end ATTRIBUTE_UNUSED;
1292d2201f2fSdrahn {
1293d2201f2fSdrahn   struct internal_exec *execp = exec_hdr (abfd);
1294d2201f2fSdrahn 
1295d2201f2fSdrahn   if (! NAME(aout,make_sections) (abfd))
1296d2201f2fSdrahn     return FALSE;
1297d2201f2fSdrahn 
1298d2201f2fSdrahn   if (adata(abfd).magic != undecided_magic)
1299d2201f2fSdrahn     return TRUE;
1300d2201f2fSdrahn 
1301d2201f2fSdrahn   obj_textsec(abfd)->_raw_size =
1302d2201f2fSdrahn     align_power(obj_textsec(abfd)->_raw_size,
1303d2201f2fSdrahn 		obj_textsec(abfd)->alignment_power);
1304d2201f2fSdrahn 
1305d2201f2fSdrahn   *text_size = obj_textsec (abfd)->_raw_size;
1306d2201f2fSdrahn   /* Rule (heuristic) for when to pad to a new page.  Note that there
1307d2201f2fSdrahn      are (at least) two ways demand-paged (ZMAGIC) files have been
1308d2201f2fSdrahn      handled.  Most Berkeley-based systems start the text segment at
1309d2201f2fSdrahn      (TARGET_PAGE_SIZE).  However, newer versions of SUNOS start the text
1310d2201f2fSdrahn      segment right after the exec header; the latter is counted in the
1311d2201f2fSdrahn      text segment size, and is paged in by the kernel with the rest of
1312d2201f2fSdrahn      the text. */
1313d2201f2fSdrahn 
1314d2201f2fSdrahn   /* This perhaps isn't the right way to do this, but made it simpler for me
1315d2201f2fSdrahn      to understand enough to implement it.  Better would probably be to go
1316d2201f2fSdrahn      right from BFD flags to alignment/positioning characteristics.  But the
1317d2201f2fSdrahn      old code was sloppy enough about handling the flags, and had enough
1318d2201f2fSdrahn      other magic, that it was a little hard for me to understand.  I think
1319d2201f2fSdrahn      I understand it better now, but I haven't time to do the cleanup this
1320d2201f2fSdrahn      minute.  */
1321d2201f2fSdrahn 
1322d2201f2fSdrahn   if (abfd->flags & WP_TEXT)
1323d2201f2fSdrahn     adata(abfd).magic = n_magic;
1324d2201f2fSdrahn   else
1325d2201f2fSdrahn     adata(abfd).magic = o_magic;
1326d2201f2fSdrahn 
1327d2201f2fSdrahn #ifdef BFD_AOUT_DEBUG /* requires gcc2 */
1328d2201f2fSdrahn #if __GNUC__ >= 2
1329d2201f2fSdrahn   fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
1330d2201f2fSdrahn 	   ({ char *str;
1331d2201f2fSdrahn 	      switch (adata(abfd).magic) {
1332d2201f2fSdrahn 	      case n_magic: str = "NMAGIC"; break;
1333d2201f2fSdrahn 	      case o_magic: str = "OMAGIC"; break;
1334d2201f2fSdrahn 	      case z_magic: str = "ZMAGIC"; break;
1335d2201f2fSdrahn 	      default: abort ();
1336d2201f2fSdrahn 	      }
1337d2201f2fSdrahn 	      str;
1338d2201f2fSdrahn 	    }),
1339d2201f2fSdrahn 	   obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size,
1340d2201f2fSdrahn 	   	obj_textsec(abfd)->alignment_power,
1341d2201f2fSdrahn 	   obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size,
1342d2201f2fSdrahn 	   	obj_datasec(abfd)->alignment_power,
1343d2201f2fSdrahn 	   obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size,
1344d2201f2fSdrahn 	   	obj_bsssec(abfd)->alignment_power);
1345d2201f2fSdrahn #endif
1346d2201f2fSdrahn #endif
1347d2201f2fSdrahn 
1348d2201f2fSdrahn   switch (adata(abfd).magic)
1349d2201f2fSdrahn     {
1350d2201f2fSdrahn     case o_magic:
1351d2201f2fSdrahn       adjust_o_magic (abfd, execp);
1352d2201f2fSdrahn       break;
1353d2201f2fSdrahn     case z_magic:
1354d2201f2fSdrahn       adjust_z_magic (abfd, execp);
1355d2201f2fSdrahn       break;
1356d2201f2fSdrahn     case n_magic:
1357d2201f2fSdrahn       adjust_n_magic (abfd, execp);
1358d2201f2fSdrahn       break;
1359d2201f2fSdrahn     default:
1360d2201f2fSdrahn       abort ();
1361d2201f2fSdrahn     }
1362d2201f2fSdrahn 
1363d2201f2fSdrahn #ifdef BFD_AOUT_DEBUG
1364d2201f2fSdrahn   fprintf (stderr, "       text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n",
1365d2201f2fSdrahn 	   obj_textsec(abfd)->vma, obj_textsec(abfd)->_raw_size,
1366d2201f2fSdrahn 	   	obj_textsec(abfd)->filepos,
1367d2201f2fSdrahn 	   obj_datasec(abfd)->vma, obj_datasec(abfd)->_raw_size,
1368d2201f2fSdrahn 	   	obj_datasec(abfd)->filepos,
1369d2201f2fSdrahn 	   obj_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size);
1370d2201f2fSdrahn #endif
1371d2201f2fSdrahn 
1372d2201f2fSdrahn   return TRUE;
1373d2201f2fSdrahn }
1374d2201f2fSdrahn 
1375d2201f2fSdrahn /*
1376d2201f2fSdrahn FUNCTION
1377d2201f2fSdrahn 	aout_@var{size}_new_section_hook
1378d2201f2fSdrahn 
1379d2201f2fSdrahn SYNOPSIS
1380d2201f2fSdrahn         bfd_boolean aout_@var{size}_new_section_hook,
1381d2201f2fSdrahn 	   (bfd *abfd,
1382d2201f2fSdrahn 	    asection *newsect));
1383d2201f2fSdrahn 
1384d2201f2fSdrahn DESCRIPTION
1385d2201f2fSdrahn 	Called by the BFD in response to a @code{bfd_make_section}
1386d2201f2fSdrahn 	request.
1387d2201f2fSdrahn */
1388d2201f2fSdrahn bfd_boolean
1389d2201f2fSdrahn NAME(aout,new_section_hook) (abfd, newsect)
1390d2201f2fSdrahn      bfd *abfd;
1391d2201f2fSdrahn      asection *newsect;
1392d2201f2fSdrahn {
1393d2201f2fSdrahn   /* align to double at least */
1394d2201f2fSdrahn   newsect->alignment_power = bfd_get_arch_info(abfd)->section_align_power;
1395d2201f2fSdrahn 
1396d2201f2fSdrahn 
1397d2201f2fSdrahn   if (bfd_get_format (abfd) == bfd_object)
1398d2201f2fSdrahn     {
1399d2201f2fSdrahn       if (obj_textsec (abfd) == NULL
1400d2201f2fSdrahn 	  && ! strcmp (newsect->name, ".text"))
1401d2201f2fSdrahn 	{
1402d2201f2fSdrahn 	  obj_textsec(abfd)= newsect;
1403d2201f2fSdrahn 	  newsect->target_index = N_TEXT;
1404d2201f2fSdrahn 	  return TRUE;
1405d2201f2fSdrahn 	}
1406d2201f2fSdrahn 
1407d2201f2fSdrahn     if (obj_datasec (abfd) == NULL
1408d2201f2fSdrahn 	&& ! strcmp (newsect->name, ".data"))
1409d2201f2fSdrahn       {
1410d2201f2fSdrahn 	obj_datasec (abfd) = newsect;
1411d2201f2fSdrahn 	newsect->target_index = N_DATA;
1412d2201f2fSdrahn 	return TRUE;
1413d2201f2fSdrahn       }
1414d2201f2fSdrahn 
1415d2201f2fSdrahn     if (obj_bsssec (abfd) == NULL
1416d2201f2fSdrahn 	&& !strcmp (newsect->name, ".bss"))
1417d2201f2fSdrahn       {
1418d2201f2fSdrahn 	obj_bsssec (abfd) = newsect;
1419d2201f2fSdrahn 	newsect->target_index = N_BSS;
1420d2201f2fSdrahn 	return TRUE;
1421d2201f2fSdrahn       }
1422d2201f2fSdrahn   }
1423d2201f2fSdrahn 
1424d2201f2fSdrahn   /* We allow more than three sections internally */
1425d2201f2fSdrahn   return TRUE;
1426d2201f2fSdrahn }
1427d2201f2fSdrahn 
1428d2201f2fSdrahn bfd_boolean
1429d2201f2fSdrahn NAME(aout,set_section_contents) (abfd, section, location, offset, count)
1430d2201f2fSdrahn      bfd *abfd;
1431d2201f2fSdrahn      sec_ptr section;
1432*cf2f2c56Smiod      const PTR location;
1433d2201f2fSdrahn      file_ptr offset;
1434d2201f2fSdrahn      bfd_size_type count;
1435d2201f2fSdrahn {
1436d2201f2fSdrahn   file_ptr text_end;
1437d2201f2fSdrahn   bfd_size_type text_size;
1438d2201f2fSdrahn 
1439d2201f2fSdrahn   if (! abfd->output_has_begun)
1440d2201f2fSdrahn     {
1441d2201f2fSdrahn       if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
1442d2201f2fSdrahn 	return FALSE;
1443d2201f2fSdrahn     }
1444d2201f2fSdrahn 
1445d2201f2fSdrahn   if (section == obj_bsssec (abfd))
1446d2201f2fSdrahn     {
1447d2201f2fSdrahn       bfd_set_error (bfd_error_no_contents);
1448d2201f2fSdrahn       return FALSE;
1449d2201f2fSdrahn     }
1450d2201f2fSdrahn 
1451d2201f2fSdrahn   if (section != obj_textsec (abfd)
1452d2201f2fSdrahn       && section != obj_datasec (abfd))
1453d2201f2fSdrahn     {
1454d2201f2fSdrahn       (*_bfd_error_handler)
1455d2201f2fSdrahn 	("%s: can not represent section `%s' in a.out object file format",
1456d2201f2fSdrahn 	 bfd_get_filename (abfd), bfd_get_section_name (abfd, section));
1457d2201f2fSdrahn       bfd_set_error (bfd_error_nonrepresentable_section);
1458d2201f2fSdrahn       return FALSE;
1459d2201f2fSdrahn     }
1460d2201f2fSdrahn 
1461d2201f2fSdrahn   if (count != 0)
1462d2201f2fSdrahn     {
1463d2201f2fSdrahn       if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
1464d2201f2fSdrahn 	  || bfd_bwrite (location, count, abfd) != count)
1465d2201f2fSdrahn 	return FALSE;
1466d2201f2fSdrahn     }
1467d2201f2fSdrahn 
1468d2201f2fSdrahn   return TRUE;
1469d2201f2fSdrahn }
1470d2201f2fSdrahn 
1471d2201f2fSdrahn /* Read the external symbols from an a.out file.  */
1472d2201f2fSdrahn 
1473d2201f2fSdrahn static bfd_boolean
aout_get_external_symbols(abfd)1474d2201f2fSdrahn aout_get_external_symbols (abfd)
1475d2201f2fSdrahn      bfd *abfd;
1476d2201f2fSdrahn {
1477d2201f2fSdrahn   if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL)
1478d2201f2fSdrahn     {
1479d2201f2fSdrahn       bfd_size_type count;
1480d2201f2fSdrahn       struct external_nlist *syms;
1481d2201f2fSdrahn 
1482d2201f2fSdrahn       count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
1483d2201f2fSdrahn 
1484d2201f2fSdrahn #ifdef USE_MMAP
1485d2201f2fSdrahn       if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd),
1486d2201f2fSdrahn 				 exec_hdr (abfd)->a_syms,
1487d2201f2fSdrahn 				 &obj_aout_sym_window (abfd), TRUE))
1488d2201f2fSdrahn 	return FALSE;
1489d2201f2fSdrahn       syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
1490d2201f2fSdrahn #else
1491d2201f2fSdrahn       /* We allocate using malloc to make the values easy to free
1492d2201f2fSdrahn 	 later on.  If we put them on the objalloc it might not be
1493d2201f2fSdrahn 	 possible to free them.  */
1494d2201f2fSdrahn       syms = (struct external_nlist *) bfd_malloc (count * EXTERNAL_NLIST_SIZE);
1495d2201f2fSdrahn       if (syms == (struct external_nlist *) NULL && count != 0)
1496d2201f2fSdrahn 	return FALSE;
1497d2201f2fSdrahn 
1498d2201f2fSdrahn       if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
1499d2201f2fSdrahn 	  || (bfd_bread (syms, exec_hdr (abfd)->a_syms, abfd)
1500d2201f2fSdrahn 	      != exec_hdr (abfd)->a_syms))
1501d2201f2fSdrahn 	{
1502d2201f2fSdrahn 	  free (syms);
1503d2201f2fSdrahn 	  return FALSE;
1504d2201f2fSdrahn 	}
1505d2201f2fSdrahn #endif
1506d2201f2fSdrahn 
1507d2201f2fSdrahn       obj_aout_external_syms (abfd) = syms;
1508d2201f2fSdrahn       obj_aout_external_sym_count (abfd) = count;
1509d2201f2fSdrahn     }
1510d2201f2fSdrahn 
1511d2201f2fSdrahn   if (obj_aout_external_strings (abfd) == NULL
1512d2201f2fSdrahn       && exec_hdr (abfd)->a_syms != 0)
1513d2201f2fSdrahn     {
1514d2201f2fSdrahn       unsigned char string_chars[BYTES_IN_LONG];
1515d2201f2fSdrahn       bfd_size_type stringsize;
1516d2201f2fSdrahn       char *strings;
1517d2201f2fSdrahn 
1518d2201f2fSdrahn       /* Get the size of the strings.  */
1519d2201f2fSdrahn       if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
1520d2201f2fSdrahn 	  || (bfd_bread ((PTR) string_chars, (bfd_size_type) BYTES_IN_LONG,
1521d2201f2fSdrahn 			abfd) != BYTES_IN_LONG))
1522d2201f2fSdrahn 	return FALSE;
1523d2201f2fSdrahn       stringsize = H_GET_32 (abfd, string_chars);
1524d2201f2fSdrahn 
1525d2201f2fSdrahn #ifdef USE_MMAP
1526d2201f2fSdrahn       if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize,
1527d2201f2fSdrahn 				 &obj_aout_string_window (abfd), TRUE))
1528d2201f2fSdrahn 	return FALSE;
1529d2201f2fSdrahn       strings = (char *) obj_aout_string_window (abfd).data;
1530d2201f2fSdrahn #else
1531d2201f2fSdrahn       strings = (char *) bfd_malloc (stringsize + 1);
1532d2201f2fSdrahn       if (strings == NULL)
1533d2201f2fSdrahn 	return FALSE;
1534d2201f2fSdrahn 
1535d2201f2fSdrahn       /* Skip space for the string count in the buffer for convenience
1536d2201f2fSdrahn 	 when using indexes.  */
1537d2201f2fSdrahn       if (bfd_bread (strings + 4, stringsize - 4, abfd) != stringsize - 4)
1538d2201f2fSdrahn 	{
1539d2201f2fSdrahn 	  free (strings);
1540d2201f2fSdrahn 	  return FALSE;
1541d2201f2fSdrahn 	}
1542d2201f2fSdrahn #endif
1543d2201f2fSdrahn 
1544d2201f2fSdrahn       /* Ensure that a zero index yields an empty string.  */
1545d2201f2fSdrahn       strings[0] = '\0';
1546d2201f2fSdrahn 
1547d2201f2fSdrahn       strings[stringsize - 1] = 0;
1548d2201f2fSdrahn 
1549d2201f2fSdrahn       obj_aout_external_strings (abfd) = strings;
1550d2201f2fSdrahn       obj_aout_external_string_size (abfd) = stringsize;
1551d2201f2fSdrahn     }
1552d2201f2fSdrahn 
1553d2201f2fSdrahn   return TRUE;
1554d2201f2fSdrahn }
1555d2201f2fSdrahn 
1556d2201f2fSdrahn /* Translate an a.out symbol into a BFD symbol.  The desc, other, type
1557d2201f2fSdrahn    and symbol->value fields of CACHE_PTR will be set from the a.out
1558d2201f2fSdrahn    nlist structure.  This function is responsible for setting
1559d2201f2fSdrahn    symbol->flags and symbol->section, and adjusting symbol->value.  */
1560d2201f2fSdrahn 
1561d2201f2fSdrahn static bfd_boolean
translate_from_native_sym_flags(abfd,cache_ptr)1562d2201f2fSdrahn translate_from_native_sym_flags (abfd, cache_ptr)
1563d2201f2fSdrahn      bfd *abfd;
1564d2201f2fSdrahn      aout_symbol_type *cache_ptr;
1565d2201f2fSdrahn {
1566d2201f2fSdrahn   flagword visible;
1567d2201f2fSdrahn 
1568d2201f2fSdrahn   if (cache_ptr->type == N_FN)
1569d2201f2fSdrahn     {
1570d2201f2fSdrahn       asection *sec;
1571d2201f2fSdrahn 
1572d2201f2fSdrahn       /* This is a debugging symbol.  */
1573d2201f2fSdrahn 
1574d2201f2fSdrahn       cache_ptr->symbol.flags = BSF_DEBUGGING;
1575d2201f2fSdrahn 
1576d2201f2fSdrahn       /* Work out the symbol section.  */
1577d2201f2fSdrahn       switch (cache_ptr->type & N_TYPE)
1578d2201f2fSdrahn 	{
1579d2201f2fSdrahn 	case N_TEXT:
1580d2201f2fSdrahn 	case N_FN:
1581d2201f2fSdrahn 	  sec = obj_textsec (abfd);
1582d2201f2fSdrahn 	  break;
1583d2201f2fSdrahn 	case N_DATA:
1584d2201f2fSdrahn 	  sec = obj_datasec (abfd);
1585d2201f2fSdrahn 	  break;
1586d2201f2fSdrahn 	case N_BSS:
1587d2201f2fSdrahn 	  sec = obj_bsssec (abfd);
1588d2201f2fSdrahn 	  break;
1589d2201f2fSdrahn 	default:
1590d2201f2fSdrahn 	case N_ABS:
1591d2201f2fSdrahn 	  sec = bfd_abs_section_ptr;
1592d2201f2fSdrahn 	  break;
1593d2201f2fSdrahn 	}
1594d2201f2fSdrahn 
1595d2201f2fSdrahn       cache_ptr->symbol.section = sec;
1596d2201f2fSdrahn       cache_ptr->symbol.value -= sec->vma;
1597d2201f2fSdrahn 
1598d2201f2fSdrahn       return TRUE;
1599d2201f2fSdrahn     }
1600d2201f2fSdrahn 
1601d2201f2fSdrahn   /* Get the default visibility.  This does not apply to all types, so
1602d2201f2fSdrahn      we just hold it in a local variable to use if wanted.  */
1603d2201f2fSdrahn   if ((cache_ptr->type & N_EXT) == 0)
1604d2201f2fSdrahn     visible = BSF_LOCAL;
1605d2201f2fSdrahn   else
1606d2201f2fSdrahn     visible = BSF_GLOBAL;
1607d2201f2fSdrahn 
1608d2201f2fSdrahn   switch (cache_ptr->type)
1609d2201f2fSdrahn     {
1610d2201f2fSdrahn     default:
1611d2201f2fSdrahn     case N_ABS: case N_ABS | N_EXT:
1612d2201f2fSdrahn       cache_ptr->symbol.section = bfd_abs_section_ptr;
1613d2201f2fSdrahn       cache_ptr->symbol.flags = visible;
1614d2201f2fSdrahn       break;
1615d2201f2fSdrahn 
1616d2201f2fSdrahn     case N_UNDF | N_EXT:
1617d2201f2fSdrahn       if (cache_ptr->symbol.value != 0)
1618d2201f2fSdrahn 	{
1619d2201f2fSdrahn 	  /* This is a common symbol.  */
1620d2201f2fSdrahn 	  cache_ptr->symbol.flags = BSF_GLOBAL;
1621d2201f2fSdrahn 	  cache_ptr->symbol.section = bfd_com_section_ptr;
1622d2201f2fSdrahn 	}
1623d2201f2fSdrahn       else
1624d2201f2fSdrahn 	{
1625d2201f2fSdrahn 	  cache_ptr->symbol.flags = 0;
1626d2201f2fSdrahn 	  cache_ptr->symbol.section = bfd_und_section_ptr;
1627d2201f2fSdrahn 	}
1628d2201f2fSdrahn       break;
1629d2201f2fSdrahn 
1630d2201f2fSdrahn     case N_TEXT: case N_TEXT | N_EXT:
1631d2201f2fSdrahn       cache_ptr->symbol.section = obj_textsec (abfd);
1632d2201f2fSdrahn       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
1633d2201f2fSdrahn       cache_ptr->symbol.flags = visible;
1634d2201f2fSdrahn       break;
1635d2201f2fSdrahn 
1636d2201f2fSdrahn     case N_DATA: case N_DATA | N_EXT:
1637d2201f2fSdrahn       cache_ptr->symbol.section = obj_datasec (abfd);
1638d2201f2fSdrahn       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
1639d2201f2fSdrahn       cache_ptr->symbol.flags = visible;
1640d2201f2fSdrahn       break;
1641d2201f2fSdrahn 
1642d2201f2fSdrahn     case N_BSS: case N_BSS | N_EXT:
1643d2201f2fSdrahn       cache_ptr->symbol.section = obj_bsssec (abfd);
1644d2201f2fSdrahn       cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
1645d2201f2fSdrahn       cache_ptr->symbol.flags = visible;
1646d2201f2fSdrahn       break;
1647d2201f2fSdrahn     }
1648d2201f2fSdrahn 
1649d2201f2fSdrahn   return TRUE;
1650d2201f2fSdrahn }
1651d2201f2fSdrahn 
1652d2201f2fSdrahn /* Set the fields of SYM_POINTER according to CACHE_PTR.  */
1653d2201f2fSdrahn 
1654d2201f2fSdrahn static bfd_boolean
translate_to_native_sym_flags(abfd,cache_ptr,sym_pointer)1655d2201f2fSdrahn translate_to_native_sym_flags (abfd, cache_ptr, sym_pointer)
1656d2201f2fSdrahn      bfd *abfd;
1657d2201f2fSdrahn      asymbol *cache_ptr;
1658d2201f2fSdrahn      struct external_nlist *sym_pointer;
1659d2201f2fSdrahn {
1660d2201f2fSdrahn   bfd_vma value = cache_ptr->value;
1661d2201f2fSdrahn   asection *sec;
1662d2201f2fSdrahn   bfd_vma off;
1663d2201f2fSdrahn 
1664d2201f2fSdrahn   /* Mask out any existing type bits in case copying from one section
1665d2201f2fSdrahn      to another.  */
1666d2201f2fSdrahn   sym_pointer->e_type[0] &= ~N_TYPE;
1667d2201f2fSdrahn 
1668d2201f2fSdrahn   sec = bfd_get_section (cache_ptr);
1669d2201f2fSdrahn   off = 0;
1670d2201f2fSdrahn 
1671d2201f2fSdrahn   if (sec == NULL)
1672d2201f2fSdrahn     {
1673d2201f2fSdrahn       /* This case occurs, e.g., for the *DEBUG* section of a COFF
1674d2201f2fSdrahn 	 file.  */
1675d2201f2fSdrahn       (*_bfd_error_handler)
1676d2201f2fSdrahn 	("%s: can not represent section for symbol `%s' in a.out object file format",
1677d2201f2fSdrahn 	 bfd_archive_filename (abfd),
1678d2201f2fSdrahn 	 cache_ptr->name != NULL ? cache_ptr->name : "*unknown*");
1679d2201f2fSdrahn       bfd_set_error (bfd_error_nonrepresentable_section);
1680d2201f2fSdrahn       return FALSE;
1681d2201f2fSdrahn     }
1682d2201f2fSdrahn 
1683d2201f2fSdrahn   if (sec->output_section != NULL)
1684d2201f2fSdrahn     {
1685d2201f2fSdrahn       off = sec->output_offset;
1686d2201f2fSdrahn       sec = sec->output_section;
1687d2201f2fSdrahn     }
1688d2201f2fSdrahn 
1689d2201f2fSdrahn   if (bfd_is_abs_section (sec))
1690d2201f2fSdrahn     sym_pointer->e_type[0] |= N_ABS;
1691d2201f2fSdrahn   else if (sec == obj_textsec (abfd))
1692d2201f2fSdrahn     sym_pointer->e_type[0] |= N_TEXT;
1693d2201f2fSdrahn   else if (sec == obj_datasec (abfd))
1694d2201f2fSdrahn     sym_pointer->e_type[0] |= N_DATA;
1695d2201f2fSdrahn   else if (sec == obj_bsssec (abfd))
1696d2201f2fSdrahn     sym_pointer->e_type[0] |= N_BSS;
1697d2201f2fSdrahn   else if (bfd_is_und_section (sec))
1698d2201f2fSdrahn     sym_pointer->e_type[0] = N_UNDF | N_EXT;
1699d2201f2fSdrahn   else if (bfd_is_com_section (sec))
1700d2201f2fSdrahn     sym_pointer->e_type[0] = N_UNDF | N_EXT;
1701d2201f2fSdrahn   else
1702d2201f2fSdrahn     {
1703d2201f2fSdrahn       (*_bfd_error_handler)
1704d2201f2fSdrahn 	("%s: can not represent section `%s' in a.out object file format",
1705d2201f2fSdrahn 	 bfd_archive_filename (abfd), bfd_get_section_name (abfd, sec));
1706d2201f2fSdrahn       bfd_set_error (bfd_error_nonrepresentable_section);
1707d2201f2fSdrahn       return FALSE;
1708d2201f2fSdrahn     }
1709d2201f2fSdrahn 
1710d2201f2fSdrahn   /* Turn the symbol from section relative to absolute again */
1711d2201f2fSdrahn   value += sec->vma + off;
1712d2201f2fSdrahn 
1713d2201f2fSdrahn   if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
1714d2201f2fSdrahn     sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
1715d2201f2fSdrahn   else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
1716d2201f2fSdrahn     sym_pointer->e_type[0] |= N_EXT;
1717d2201f2fSdrahn 
1718d2201f2fSdrahn #if 0
1719d2201f2fSdrahn   if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
1720d2201f2fSdrahn     {
1721d2201f2fSdrahn       int type = ((aout_symbol_type *) cache_ptr)->type;
1722d2201f2fSdrahn 
1723d2201f2fSdrahn 
1724d2201f2fSdrahn       switch (type)
1725d2201f2fSdrahn 	{
1726d2201f2fSdrahn 	case N_ABS:	type = N_SETA; break;
1727d2201f2fSdrahn 	case N_TEXT:	type = N_SETT; break;
1728d2201f2fSdrahn 	case N_DATA:	type = N_SETD; break;
1729d2201f2fSdrahn 	case N_BSS:	type = N_SETB; break;
1730d2201f2fSdrahn 	}
1731d2201f2fSdrahn       sym_pointer->e_type[0] = type;
1732d2201f2fSdrahn     }
1733d2201f2fSdrahn #endif
1734d2201f2fSdrahn 
1735d2201f2fSdrahn #if 0
1736d2201f2fSdrahn   if ((cache_ptr->flags & BSF_WEAK) != 0)
1737d2201f2fSdrahn     {
1738d2201f2fSdrahn       int type;
1739d2201f2fSdrahn 
1740d2201f2fSdrahn       switch (sym_pointer->e_type[0] & N_TYPE)
1741d2201f2fSdrahn 	{
1742d2201f2fSdrahn 	default:
1743d2201f2fSdrahn 	case N_ABS:	type = N_WEAKA; break;
1744d2201f2fSdrahn 	case N_TEXT:	type = N_WEAKT; break;
1745d2201f2fSdrahn 	case N_DATA:	type = N_WEAKD; break;
1746d2201f2fSdrahn 	case N_BSS:	type = N_WEAKB; break;
1747d2201f2fSdrahn 	case N_UNDF:	type = N_WEAKU; break;
1748d2201f2fSdrahn 	}
1749d2201f2fSdrahn       sym_pointer->e_type[0] = type;
1750d2201f2fSdrahn     }
1751d2201f2fSdrahn #endif
1752d2201f2fSdrahn 
1753d2201f2fSdrahn   PUT_WORD(abfd, value, sym_pointer->e_value);
1754d2201f2fSdrahn 
1755d2201f2fSdrahn   return TRUE;
1756d2201f2fSdrahn }
1757d2201f2fSdrahn 
1758d2201f2fSdrahn /* Native-level interface to symbols. */
1759d2201f2fSdrahn 
1760d2201f2fSdrahn asymbol *
1761d2201f2fSdrahn NAME(aout,make_empty_symbol) (abfd)
1762d2201f2fSdrahn      bfd *abfd;
1763d2201f2fSdrahn {
1764d2201f2fSdrahn   bfd_size_type amt = sizeof (aout_symbol_type);
1765d2201f2fSdrahn   aout_symbol_type *new = (aout_symbol_type *) bfd_zalloc (abfd, amt);
1766d2201f2fSdrahn   if (!new)
1767d2201f2fSdrahn     return NULL;
1768d2201f2fSdrahn   new->symbol.the_bfd = abfd;
1769d2201f2fSdrahn 
1770d2201f2fSdrahn   return &new->symbol;
1771d2201f2fSdrahn }
1772d2201f2fSdrahn 
1773d2201f2fSdrahn /* Translate a set of internal symbols into external symbols.  */
1774d2201f2fSdrahn 
1775d2201f2fSdrahn bfd_boolean
1776d2201f2fSdrahn NAME(aout,translate_symbol_table) (abfd, in, ext, count, str, strsize, dynamic)
1777d2201f2fSdrahn      bfd *abfd;
1778d2201f2fSdrahn      aout_symbol_type *in;
1779d2201f2fSdrahn      struct external_nlist *ext;
1780d2201f2fSdrahn      bfd_size_type count;
1781d2201f2fSdrahn      char *str;
1782d2201f2fSdrahn      bfd_size_type strsize;
1783d2201f2fSdrahn      bfd_boolean dynamic;
1784d2201f2fSdrahn {
1785d2201f2fSdrahn   struct external_nlist *ext_end;
1786d2201f2fSdrahn 
1787d2201f2fSdrahn   ext_end = ext + count;
1788d2201f2fSdrahn   for (; ext < ext_end; ext++, in++)
1789d2201f2fSdrahn     {
1790d2201f2fSdrahn       bfd_vma x;
1791d2201f2fSdrahn 
1792d2201f2fSdrahn       x = GET_WORD (abfd, ext->e_strx);
1793d2201f2fSdrahn       in->symbol.the_bfd = abfd;
1794d2201f2fSdrahn 
1795d2201f2fSdrahn       /* For the normal symbols, the zero index points at the number
1796d2201f2fSdrahn 	 of bytes in the string table but is to be interpreted as the
1797d2201f2fSdrahn 	 null string.  For the dynamic symbols, the number of bytes in
1798d2201f2fSdrahn 	 the string table is stored in the __DYNAMIC structure and the
1799d2201f2fSdrahn 	 zero index points at an actual string.  */
1800d2201f2fSdrahn       if (x == 0 && ! dynamic)
1801d2201f2fSdrahn 	in->symbol.name = "";
1802d2201f2fSdrahn       else if (x < strsize)
1803d2201f2fSdrahn 	in->symbol.name = str + x;
1804d2201f2fSdrahn       else
1805d2201f2fSdrahn 	return FALSE;
1806d2201f2fSdrahn 
1807d2201f2fSdrahn       in->symbol.value = GET_SWORD (abfd,  ext->e_value);
1808d2201f2fSdrahn       /* TODO: is 0 a safe value here? */
1809d2201f2fSdrahn       in->desc = 0;
1810d2201f2fSdrahn       in->other = 0;
1811d2201f2fSdrahn       in->type = H_GET_8 (abfd,  ext->e_type);
1812d2201f2fSdrahn       in->symbol.udata.p = NULL;
1813d2201f2fSdrahn 
1814d2201f2fSdrahn       if (! translate_from_native_sym_flags (abfd, in))
1815d2201f2fSdrahn 	return FALSE;
1816d2201f2fSdrahn 
1817d2201f2fSdrahn       if (dynamic)
1818d2201f2fSdrahn 	in->symbol.flags |= BSF_DYNAMIC;
1819d2201f2fSdrahn     }
1820d2201f2fSdrahn 
1821d2201f2fSdrahn   return TRUE;
1822d2201f2fSdrahn }
1823d2201f2fSdrahn 
1824d2201f2fSdrahn /* We read the symbols into a buffer, which is discarded when this
1825d2201f2fSdrahn    function exits.  We read the strings into a buffer large enough to
1826d2201f2fSdrahn    hold them all plus all the cached symbol entries. */
1827d2201f2fSdrahn 
1828d2201f2fSdrahn bfd_boolean
1829d2201f2fSdrahn NAME(aout,slurp_symbol_table) (abfd)
1830d2201f2fSdrahn      bfd *abfd;
1831d2201f2fSdrahn {
1832d2201f2fSdrahn   struct external_nlist *old_external_syms;
1833d2201f2fSdrahn   aout_symbol_type *cached;
1834d2201f2fSdrahn   bfd_size_type cached_size;
1835d2201f2fSdrahn 
1836d2201f2fSdrahn   /* If there's no work to be done, don't do any */
1837d2201f2fSdrahn   if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
1838d2201f2fSdrahn     return TRUE;
1839d2201f2fSdrahn 
1840d2201f2fSdrahn   old_external_syms = obj_aout_external_syms (abfd);
1841d2201f2fSdrahn 
1842d2201f2fSdrahn   if (! aout_get_external_symbols (abfd))
1843d2201f2fSdrahn     return FALSE;
1844d2201f2fSdrahn 
1845d2201f2fSdrahn   cached_size = obj_aout_external_sym_count (abfd);
1846d2201f2fSdrahn   cached_size *= sizeof (aout_symbol_type);
1847d2201f2fSdrahn   cached = (aout_symbol_type *) bfd_zmalloc (cached_size);
1848d2201f2fSdrahn   if (cached == NULL && cached_size != 0)
1849d2201f2fSdrahn     return FALSE;
1850d2201f2fSdrahn 
1851d2201f2fSdrahn   /* Convert from external symbol information to internal.  */
1852d2201f2fSdrahn   if (! (NAME(aout,translate_symbol_table)
1853d2201f2fSdrahn 	 (abfd, cached,
1854d2201f2fSdrahn 	  obj_aout_external_syms (abfd),
1855d2201f2fSdrahn 	  obj_aout_external_sym_count (abfd),
1856d2201f2fSdrahn 	  obj_aout_external_strings (abfd),
1857d2201f2fSdrahn 	  obj_aout_external_string_size (abfd),
1858d2201f2fSdrahn 	  FALSE)))
1859d2201f2fSdrahn     {
1860d2201f2fSdrahn       free (cached);
1861d2201f2fSdrahn       return FALSE;
1862d2201f2fSdrahn     }
1863d2201f2fSdrahn 
1864d2201f2fSdrahn   bfd_get_symcount (abfd) = obj_aout_external_sym_count (abfd);
1865d2201f2fSdrahn 
1866d2201f2fSdrahn   obj_aout_symbols (abfd) = cached;
1867d2201f2fSdrahn 
1868d2201f2fSdrahn   /* It is very likely that anybody who calls this function will not
1869d2201f2fSdrahn      want the external symbol information, so if it was allocated
1870d2201f2fSdrahn      because of our call to aout_get_external_symbols, we free it up
1871d2201f2fSdrahn      right away to save space.  */
1872d2201f2fSdrahn   if (old_external_syms == (struct external_nlist *) NULL
1873d2201f2fSdrahn       && obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
1874d2201f2fSdrahn     {
1875d2201f2fSdrahn #ifdef USE_MMAP
1876d2201f2fSdrahn       bfd_free_window (&obj_aout_sym_window (abfd));
1877d2201f2fSdrahn #else
1878d2201f2fSdrahn       free (obj_aout_external_syms (abfd));
1879d2201f2fSdrahn #endif
1880d2201f2fSdrahn       obj_aout_external_syms (abfd) = NULL;
1881d2201f2fSdrahn     }
1882d2201f2fSdrahn 
1883d2201f2fSdrahn   return TRUE;
1884d2201f2fSdrahn }
1885d2201f2fSdrahn 
1886d2201f2fSdrahn /* We use a hash table when writing out symbols so that we only write
1887d2201f2fSdrahn    out a particular string once.  This helps particularly when the
1888d2201f2fSdrahn    linker writes out stabs debugging entries, because each different
1889d2201f2fSdrahn    contributing object file tends to have many duplicate stabs
1890d2201f2fSdrahn    strings.
1891d2201f2fSdrahn 
1892d2201f2fSdrahn    This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
1893d2201f2fSdrahn    if BFD_TRADITIONAL_FORMAT is set.  */
1894d2201f2fSdrahn 
1895d2201f2fSdrahn static bfd_size_type add_to_stringtab
1896d2201f2fSdrahn   PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, bfd_boolean));
1897d2201f2fSdrahn static bfd_boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *));
1898d2201f2fSdrahn 
1899d2201f2fSdrahn /* Get the index of a string in a strtab, adding it if it is not
1900d2201f2fSdrahn    already present.  */
1901d2201f2fSdrahn 
1902d2201f2fSdrahn static INLINE bfd_size_type
add_to_stringtab(abfd,tab,str,copy)1903d2201f2fSdrahn add_to_stringtab (abfd, tab, str, copy)
1904d2201f2fSdrahn      bfd *abfd;
1905d2201f2fSdrahn      struct bfd_strtab_hash *tab;
1906d2201f2fSdrahn      const char *str;
1907d2201f2fSdrahn      bfd_boolean copy;
1908d2201f2fSdrahn {
1909d2201f2fSdrahn   bfd_boolean hash;
1910d2201f2fSdrahn   bfd_size_type index;
1911d2201f2fSdrahn 
1912d2201f2fSdrahn   /* An index of 0 always means the empty string.  */
1913d2201f2fSdrahn   if (str == 0 || *str == '\0')
1914d2201f2fSdrahn     return 0;
1915d2201f2fSdrahn 
1916d2201f2fSdrahn   /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx
1917d2201f2fSdrahn      doesn't understand a hashed string table.  */
1918d2201f2fSdrahn   hash = TRUE;
1919d2201f2fSdrahn   if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
1920d2201f2fSdrahn     hash = FALSE;
1921d2201f2fSdrahn 
1922d2201f2fSdrahn   index = _bfd_stringtab_add (tab, str, hash, copy);
1923d2201f2fSdrahn 
1924d2201f2fSdrahn   if (index != (bfd_size_type) -1)
1925d2201f2fSdrahn     {
1926d2201f2fSdrahn       /* Add BYTES_IN_LONG to the return value to account for the
1927d2201f2fSdrahn 	 space taken up by the string table size.  */
1928d2201f2fSdrahn       index += BYTES_IN_LONG;
1929d2201f2fSdrahn     }
1930d2201f2fSdrahn 
1931d2201f2fSdrahn   return index;
1932d2201f2fSdrahn }
1933d2201f2fSdrahn 
1934d2201f2fSdrahn /* Write out a strtab.  ABFD is already at the right location in the
1935d2201f2fSdrahn    file.  */
1936d2201f2fSdrahn 
1937d2201f2fSdrahn static bfd_boolean
emit_stringtab(abfd,tab)1938d2201f2fSdrahn emit_stringtab (abfd, tab)
1939d2201f2fSdrahn      register bfd *abfd;
1940d2201f2fSdrahn      struct bfd_strtab_hash *tab;
1941d2201f2fSdrahn {
1942d2201f2fSdrahn   bfd_byte buffer[BYTES_IN_LONG];
1943d2201f2fSdrahn 
1944d2201f2fSdrahn   /* The string table starts with the size.  */
1945d2201f2fSdrahn   H_PUT_32 (abfd, _bfd_stringtab_size (tab) + BYTES_IN_LONG, buffer);
1946d2201f2fSdrahn   if (bfd_bwrite ((PTR) buffer, (bfd_size_type) BYTES_IN_LONG, abfd)
1947d2201f2fSdrahn       != BYTES_IN_LONG)
1948d2201f2fSdrahn     return FALSE;
1949d2201f2fSdrahn 
1950d2201f2fSdrahn   return _bfd_stringtab_emit (abfd, tab);
1951d2201f2fSdrahn }
1952d2201f2fSdrahn 
1953d2201f2fSdrahn bfd_boolean
1954d2201f2fSdrahn NAME(aout,write_syms) (abfd)
1955d2201f2fSdrahn      bfd *abfd;
1956d2201f2fSdrahn {
1957d2201f2fSdrahn   unsigned int count ;
1958d2201f2fSdrahn   asymbol **generic = bfd_get_outsymbols (abfd);
1959d2201f2fSdrahn   struct bfd_strtab_hash *strtab;
1960d2201f2fSdrahn 
1961d2201f2fSdrahn   strtab = _bfd_stringtab_init ();
1962d2201f2fSdrahn   if (strtab == NULL)
1963d2201f2fSdrahn     return FALSE;
1964d2201f2fSdrahn 
1965d2201f2fSdrahn   for (count = 0; count < bfd_get_symcount (abfd); count++)
1966d2201f2fSdrahn     {
1967d2201f2fSdrahn       asymbol *g = generic[count];
1968d2201f2fSdrahn       bfd_size_type indx;
1969d2201f2fSdrahn       struct external_nlist nsp;
1970d2201f2fSdrahn 
1971d2201f2fSdrahn       PUT_WORD (abfd, 0, nsp.e_unused);
1972d2201f2fSdrahn 
1973d2201f2fSdrahn       indx = add_to_stringtab (abfd, strtab, g->name, FALSE);
1974d2201f2fSdrahn       if (indx == (bfd_size_type) -1)
1975d2201f2fSdrahn 	goto error_return;
1976d2201f2fSdrahn       PUT_WORD (abfd, indx, nsp.e_strx);
1977d2201f2fSdrahn 
1978d2201f2fSdrahn       if (bfd_asymbol_flavour(g) == abfd->xvec->flavour)
1979d2201f2fSdrahn 	H_PUT_8 (abfd, aout_symbol(g)->type,  nsp.e_type);
1980d2201f2fSdrahn       else
1981d2201f2fSdrahn 	H_PUT_8 (abfd, 0, nsp.e_type);
1982d2201f2fSdrahn 
1983d2201f2fSdrahn       if (! translate_to_native_sym_flags (abfd, g, &nsp))
1984d2201f2fSdrahn 	goto error_return;
1985d2201f2fSdrahn 
1986d2201f2fSdrahn       H_PUT_8 (abfd, 0, nsp.e_ovly);
1987d2201f2fSdrahn 
1988d2201f2fSdrahn       if (bfd_bwrite ((PTR)&nsp, (bfd_size_type) EXTERNAL_NLIST_SIZE, abfd)
1989d2201f2fSdrahn 	  != EXTERNAL_NLIST_SIZE)
1990d2201f2fSdrahn 	goto error_return;
1991d2201f2fSdrahn 
1992d2201f2fSdrahn       /* NB: `KEEPIT' currently overlays `udata.p', so set this only
1993d2201f2fSdrahn 	 here, at the end.  */
1994d2201f2fSdrahn       g->KEEPIT = count;
1995d2201f2fSdrahn     }
1996d2201f2fSdrahn 
1997d2201f2fSdrahn   if (! emit_stringtab (abfd, strtab))
1998d2201f2fSdrahn     goto error_return;
1999d2201f2fSdrahn 
2000d2201f2fSdrahn   _bfd_stringtab_free (strtab);
2001d2201f2fSdrahn 
2002d2201f2fSdrahn   return TRUE;
2003d2201f2fSdrahn 
2004d2201f2fSdrahn error_return:
2005d2201f2fSdrahn   _bfd_stringtab_free (strtab);
2006d2201f2fSdrahn   return FALSE;
2007d2201f2fSdrahn }
2008d2201f2fSdrahn 
2009d2201f2fSdrahn 
2010d2201f2fSdrahn long
2011*cf2f2c56Smiod NAME(aout,canonicalize_symtab) (abfd, location)
2012d2201f2fSdrahn      bfd *abfd;
2013d2201f2fSdrahn      asymbol **location;
2014d2201f2fSdrahn {
2015d2201f2fSdrahn     unsigned int counter = 0;
2016d2201f2fSdrahn     aout_symbol_type *symbase;
2017d2201f2fSdrahn 
2018d2201f2fSdrahn     if (!NAME(aout,slurp_symbol_table)(abfd))
2019d2201f2fSdrahn       return -1;
2020d2201f2fSdrahn 
2021d2201f2fSdrahn     for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
2022d2201f2fSdrahn       *(location++) = (asymbol *)( symbase++);
2023d2201f2fSdrahn     *location++ =0;
2024d2201f2fSdrahn     return bfd_get_symcount (abfd);
2025d2201f2fSdrahn }
2026d2201f2fSdrahn 
2027d2201f2fSdrahn 
2028d2201f2fSdrahn /* Standard reloc stuff */
2029d2201f2fSdrahn 
2030d2201f2fSdrahn /* Extended stuff */
2031d2201f2fSdrahn /* Output extended relocation information to a file in target byte order. */
2032d2201f2fSdrahn 
2033d2201f2fSdrahn void
pdp11_aout_swap_reloc_out(abfd,g,natptr)2034d2201f2fSdrahn pdp11_aout_swap_reloc_out (abfd, g, natptr)
2035d2201f2fSdrahn      bfd *abfd;
2036d2201f2fSdrahn      arelent *g;
2037d2201f2fSdrahn      register struct pdp11_aout_reloc_external *natptr;
2038d2201f2fSdrahn {
2039d2201f2fSdrahn   int r_index;
2040d2201f2fSdrahn   int r_pcrel;
2041d2201f2fSdrahn   int reloc_entry;
2042d2201f2fSdrahn   int r_type;
2043d2201f2fSdrahn   asymbol *sym = *(g->sym_ptr_ptr);
2044d2201f2fSdrahn   asection *output_section = sym->section->output_section;
2045d2201f2fSdrahn 
2046d2201f2fSdrahn   if (g->addend != 0)
2047d2201f2fSdrahn     fprintf (stderr, "BFD: can't do this reloc addend stuff\n");
2048d2201f2fSdrahn 
2049d2201f2fSdrahn   r_pcrel = g->howto->pc_relative;
2050d2201f2fSdrahn 
2051d2201f2fSdrahn   if (bfd_is_abs_section (output_section))
2052d2201f2fSdrahn     r_type = RABS;
2053d2201f2fSdrahn   else if (output_section == obj_textsec (abfd))
2054d2201f2fSdrahn     r_type = RTEXT;
2055d2201f2fSdrahn   else if (output_section == obj_datasec (abfd))
2056d2201f2fSdrahn     r_type = RDATA;
2057d2201f2fSdrahn   else if (output_section == obj_bsssec (abfd))
2058d2201f2fSdrahn     r_type = RBSS;
2059d2201f2fSdrahn   else if (bfd_is_und_section (output_section))
2060d2201f2fSdrahn     r_type = REXT;
2061d2201f2fSdrahn   else if (bfd_is_com_section (output_section))
2062d2201f2fSdrahn     r_type = REXT;
2063d2201f2fSdrahn   else
2064d2201f2fSdrahn     r_type = -1;
2065d2201f2fSdrahn 
2066d2201f2fSdrahn   BFD_ASSERT (r_type != -1);
2067d2201f2fSdrahn 
2068d2201f2fSdrahn   if (r_type == RABS)
2069d2201f2fSdrahn     r_index = 0;
2070d2201f2fSdrahn   else
2071d2201f2fSdrahn     r_index = (*(g->sym_ptr_ptr))->KEEPIT;
2072d2201f2fSdrahn 
2073d2201f2fSdrahn #if 0
2074d2201f2fSdrahn   if (bfd_is_abs_section (bfd_get_section (sym)))
2075d2201f2fSdrahn     {
2076d2201f2fSdrahn       r_extern = 0;
2077d2201f2fSdrahn       r_index = N_ABS;
2078d2201f2fSdrahn       r_type = RABS;
2079d2201f2fSdrahn     }
2080d2201f2fSdrahn   else if ((sym->flags & BSF_SECTION_SYM) == 0)
2081d2201f2fSdrahn     {
2082d2201f2fSdrahn       if (bfd_is_und_section (bfd_get_section (sym))
2083d2201f2fSdrahn 	  || (sym->flags & BSF_GLOBAL) != 0)
2084d2201f2fSdrahn 	r_extern = 1;
2085d2201f2fSdrahn       else
2086d2201f2fSdrahn 	r_extern = 0;
2087d2201f2fSdrahn       r_index = (*(g->sym_ptr_ptr))->KEEPIT;
2088d2201f2fSdrahn     }
2089d2201f2fSdrahn   else
2090d2201f2fSdrahn     {
2091d2201f2fSdrahn       /* Just an ordinary section */
2092d2201f2fSdrahn       r_extern = 0;
2093d2201f2fSdrahn       r_index = output_section->target_index;
2094d2201f2fSdrahn     }
2095d2201f2fSdrahn #endif
2096d2201f2fSdrahn 
2097d2201f2fSdrahn   reloc_entry = r_index << 4 | r_type | r_pcrel;
2098d2201f2fSdrahn 
2099d2201f2fSdrahn   PUT_WORD (abfd, reloc_entry, natptr->e_reloc_entry);
2100d2201f2fSdrahn }
2101d2201f2fSdrahn 
2102d2201f2fSdrahn /* BFD deals internally with all things based from the section they're
2103d2201f2fSdrahn    in. so, something in 10 bytes into a text section  with a base of
2104d2201f2fSdrahn    50 would have a symbol (.text+10) and know .text vma was 50.
2105d2201f2fSdrahn 
2106d2201f2fSdrahn    Aout keeps all it's symbols based from zero, so the symbol would
2107d2201f2fSdrahn    contain 60. This macro subs the base of each section from the value
2108d2201f2fSdrahn    to give the true offset from the section */
2109d2201f2fSdrahn 
2110d2201f2fSdrahn 
2111d2201f2fSdrahn #define MOVE_ADDRESS(ad)       						\
2112d2201f2fSdrahn   if (r_extern) 							\
2113d2201f2fSdrahn     {									\
2114d2201f2fSdrahn       /* Undefined symbol.  */						\
2115d2201f2fSdrahn       cache_ptr->sym_ptr_ptr = symbols + r_index;			\
2116d2201f2fSdrahn       cache_ptr->addend = ad;						\
2117d2201f2fSdrahn     }									\
2118d2201f2fSdrahn   else									\
2119d2201f2fSdrahn     {									\
2120d2201f2fSdrahn       /* Defined, section relative. replace symbol with pointer to    	\
2121d2201f2fSdrahn 	 symbol which points to section.  */				\
2122d2201f2fSdrahn       switch (r_index)							\
2123d2201f2fSdrahn 	{								\
2124d2201f2fSdrahn 	case N_TEXT:							\
2125d2201f2fSdrahn 	case N_TEXT | N_EXT:						\
2126d2201f2fSdrahn 	  cache_ptr->sym_ptr_ptr  = obj_textsec (abfd)->symbol_ptr_ptr;	\
2127d2201f2fSdrahn 	  cache_ptr->addend = ad  - su->textsec->vma;			\
2128d2201f2fSdrahn 	  break;							\
2129d2201f2fSdrahn 	case N_DATA:							\
2130d2201f2fSdrahn 	case N_DATA | N_EXT:						\
2131d2201f2fSdrahn 	  cache_ptr->sym_ptr_ptr  = obj_datasec (abfd)->symbol_ptr_ptr;	\
2132d2201f2fSdrahn 	  cache_ptr->addend = ad - su->datasec->vma;			\
2133d2201f2fSdrahn 	  break;							\
2134d2201f2fSdrahn 	case N_BSS:							\
2135d2201f2fSdrahn 	case N_BSS | N_EXT:						\
2136d2201f2fSdrahn 	  cache_ptr->sym_ptr_ptr  = obj_bsssec (abfd)->symbol_ptr_ptr;	\
2137d2201f2fSdrahn 	  cache_ptr->addend = ad - su->bsssec->vma;			\
2138d2201f2fSdrahn 	  break;							\
2139d2201f2fSdrahn 	default:							\
2140d2201f2fSdrahn 	case N_ABS:							\
2141d2201f2fSdrahn 	case N_ABS | N_EXT:						\
2142d2201f2fSdrahn 	  cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
2143d2201f2fSdrahn 	  cache_ptr->addend = ad;					\
2144d2201f2fSdrahn 	  break;							\
2145d2201f2fSdrahn 	}								\
2146d2201f2fSdrahn     }
2147d2201f2fSdrahn 
2148d2201f2fSdrahn void
pdp11_aout_swap_reloc_in(abfd,bytes,cache_ptr,offset,symbols,symcount)2149d2201f2fSdrahn pdp11_aout_swap_reloc_in (abfd, bytes, cache_ptr, offset,
2150d2201f2fSdrahn 			  symbols, symcount)
2151d2201f2fSdrahn      bfd *abfd;
2152d2201f2fSdrahn      struct pdp11_aout_reloc_external *bytes;
2153d2201f2fSdrahn      arelent *cache_ptr;
2154d2201f2fSdrahn      bfd_size_type offset;
2155d2201f2fSdrahn      asymbol **symbols;
2156d2201f2fSdrahn      bfd_size_type symcount;
2157d2201f2fSdrahn {
2158d2201f2fSdrahn   struct aoutdata *su = &(abfd->tdata.aout_data->a);
2159d2201f2fSdrahn   unsigned int r_index;
2160d2201f2fSdrahn   int reloc_entry;
2161d2201f2fSdrahn   int r_extern;
2162d2201f2fSdrahn   int r_pcrel;
2163d2201f2fSdrahn 
2164d2201f2fSdrahn   reloc_entry = GET_WORD (abfd, (PTR)bytes);
2165d2201f2fSdrahn 
2166d2201f2fSdrahn   r_pcrel = reloc_entry & RELFLG;
2167d2201f2fSdrahn 
2168d2201f2fSdrahn   cache_ptr->address = offset;
2169d2201f2fSdrahn   cache_ptr->howto = howto_table_pdp11 + (r_pcrel ? 1 : 0);
2170d2201f2fSdrahn 
2171d2201f2fSdrahn   if ((reloc_entry & RTYPE) == RABS)
2172d2201f2fSdrahn     r_index = N_ABS;
2173d2201f2fSdrahn   else
2174d2201f2fSdrahn     r_index = RINDEX (reloc_entry);
2175d2201f2fSdrahn 
2176d2201f2fSdrahn   /* r_extern reflects whether the symbol the reloc is against is
2177d2201f2fSdrahn      local or global.  */
2178d2201f2fSdrahn   r_extern = (reloc_entry & RTYPE) == REXT;
2179d2201f2fSdrahn 
2180d2201f2fSdrahn   if (r_extern && r_index > symcount)
2181d2201f2fSdrahn     {
2182d2201f2fSdrahn       /* We could arrange to return an error, but it might be useful
2183d2201f2fSdrahn          to see the file even if it is bad.  */
2184d2201f2fSdrahn       r_extern = 0;
2185d2201f2fSdrahn       r_index = N_ABS;
2186d2201f2fSdrahn     }
2187d2201f2fSdrahn 
2188d2201f2fSdrahn   MOVE_ADDRESS(0);
2189d2201f2fSdrahn }
2190d2201f2fSdrahn 
2191d2201f2fSdrahn /* Read and swap the relocs for a section.  */
2192d2201f2fSdrahn 
2193d2201f2fSdrahn bfd_boolean
2194d2201f2fSdrahn NAME(aout,slurp_reloc_table) (abfd, asect, symbols)
2195d2201f2fSdrahn      bfd *abfd;
2196d2201f2fSdrahn      sec_ptr asect;
2197d2201f2fSdrahn      asymbol **symbols;
2198d2201f2fSdrahn {
2199d2201f2fSdrahn   struct pdp11_aout_reloc_external *rptr;
2200d2201f2fSdrahn   bfd_size_type count;
2201d2201f2fSdrahn   bfd_size_type reloc_size;
2202d2201f2fSdrahn   PTR relocs;
2203d2201f2fSdrahn   arelent *reloc_cache;
2204d2201f2fSdrahn   size_t each_size;
2205d2201f2fSdrahn   unsigned int counter = 0;
2206d2201f2fSdrahn   arelent *cache_ptr;
2207d2201f2fSdrahn 
2208d2201f2fSdrahn   if (asect->relocation)
2209d2201f2fSdrahn     return TRUE;
2210d2201f2fSdrahn 
2211d2201f2fSdrahn   if (asect->flags & SEC_CONSTRUCTOR)
2212d2201f2fSdrahn     return TRUE;
2213d2201f2fSdrahn 
2214d2201f2fSdrahn   if (asect == obj_datasec (abfd))
2215d2201f2fSdrahn     reloc_size = exec_hdr(abfd)->a_drsize;
2216d2201f2fSdrahn   else if (asect == obj_textsec (abfd))
2217d2201f2fSdrahn     reloc_size = exec_hdr(abfd)->a_trsize;
2218d2201f2fSdrahn   else if (asect == obj_bsssec (abfd))
2219d2201f2fSdrahn     reloc_size = 0;
2220d2201f2fSdrahn   else
2221d2201f2fSdrahn     {
2222d2201f2fSdrahn       bfd_set_error (bfd_error_invalid_operation);
2223d2201f2fSdrahn       return FALSE;
2224d2201f2fSdrahn     }
2225d2201f2fSdrahn 
2226d2201f2fSdrahn   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
2227d2201f2fSdrahn     return FALSE;
2228d2201f2fSdrahn 
2229d2201f2fSdrahn   each_size = obj_reloc_entry_size (abfd);
2230d2201f2fSdrahn 
2231d2201f2fSdrahn   relocs = bfd_malloc (reloc_size);
2232d2201f2fSdrahn   if (relocs == NULL && reloc_size != 0)
2233d2201f2fSdrahn     return FALSE;
2234d2201f2fSdrahn 
2235d2201f2fSdrahn   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
2236d2201f2fSdrahn     {
2237d2201f2fSdrahn       free (relocs);
2238d2201f2fSdrahn       return FALSE;
2239d2201f2fSdrahn     }
2240d2201f2fSdrahn 
2241d2201f2fSdrahn   count = reloc_size / each_size;
2242d2201f2fSdrahn 
2243d2201f2fSdrahn   /* Count the number of NON-ZERO relocs, this is the count we want. */
2244d2201f2fSdrahn   {
2245d2201f2fSdrahn     unsigned int real_count = 0;
2246d2201f2fSdrahn 
2247d2201f2fSdrahn     for (counter = 0; counter < count; counter++)
2248d2201f2fSdrahn       {
2249d2201f2fSdrahn 	int x;
2250d2201f2fSdrahn 
2251d2201f2fSdrahn 	x = GET_WORD (abfd, (char *) relocs + each_size * counter);
2252d2201f2fSdrahn 	if (x != 0)
2253d2201f2fSdrahn 	  real_count++;
2254d2201f2fSdrahn       }
2255d2201f2fSdrahn 
2256d2201f2fSdrahn     count = real_count;
2257d2201f2fSdrahn   }
2258d2201f2fSdrahn 
2259d2201f2fSdrahn   reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
2260d2201f2fSdrahn   if (reloc_cache == NULL && count != 0)
2261d2201f2fSdrahn     return FALSE;
2262d2201f2fSdrahn 
2263d2201f2fSdrahn   cache_ptr = reloc_cache;
2264d2201f2fSdrahn 
2265d2201f2fSdrahn   rptr = (struct pdp11_aout_reloc_external *) relocs;
2266d2201f2fSdrahn   for (counter = 0;
2267d2201f2fSdrahn        counter < count;
2268d2201f2fSdrahn        counter++, ((char *)rptr) += RELOC_SIZE, cache_ptr++)
2269d2201f2fSdrahn     {
2270d2201f2fSdrahn       while (GET_WORD (abfd, (PTR)rptr) == 0)
2271d2201f2fSdrahn 	{
2272d2201f2fSdrahn 	  rptr =
2273d2201f2fSdrahn 	    (struct pdp11_aout_reloc_external *)
2274d2201f2fSdrahn 	    ((char *) rptr + RELOC_SIZE);
2275d2201f2fSdrahn 	  if ((char *) rptr >= (char *) relocs + reloc_size)
2276d2201f2fSdrahn 	    goto done;
2277d2201f2fSdrahn 	}
2278d2201f2fSdrahn 
2279d2201f2fSdrahn       pdp11_aout_swap_reloc_in (abfd, rptr, cache_ptr,
2280d2201f2fSdrahn 				(bfd_size_type) ((char *) rptr - (char *) relocs),
2281d2201f2fSdrahn 				symbols,
2282d2201f2fSdrahn 				(bfd_size_type) bfd_get_symcount (abfd));
2283d2201f2fSdrahn     }
2284d2201f2fSdrahn  done:
2285d2201f2fSdrahn   /* Just in case, if rptr >= relocs + reloc_size should happen
2286d2201f2fSdrahn      too early. */
2287d2201f2fSdrahn   BFD_ASSERT (counter == count);
2288d2201f2fSdrahn 
2289d2201f2fSdrahn   free (relocs);
2290d2201f2fSdrahn 
2291d2201f2fSdrahn   asect->relocation = reloc_cache;
2292d2201f2fSdrahn   asect->reloc_count = cache_ptr - reloc_cache;
2293d2201f2fSdrahn 
2294d2201f2fSdrahn   return TRUE;
2295d2201f2fSdrahn }
2296d2201f2fSdrahn 
2297d2201f2fSdrahn /* Write out a relocation section into an object file.  */
2298d2201f2fSdrahn 
2299d2201f2fSdrahn bfd_boolean
2300d2201f2fSdrahn NAME(aout,squirt_out_relocs) (abfd, section)
2301d2201f2fSdrahn      bfd *abfd;
2302d2201f2fSdrahn      asection *section;
2303d2201f2fSdrahn {
2304d2201f2fSdrahn   arelent **generic;
2305d2201f2fSdrahn   unsigned char *native;
2306d2201f2fSdrahn   unsigned int count = section->reloc_count;
2307d2201f2fSdrahn   bfd_size_type natsize;
2308d2201f2fSdrahn 
2309d2201f2fSdrahn #if 0
2310d2201f2fSdrahn   /* If we're writing an .o file, we must write
2311d2201f2fSdrahn      relocation information, even if there is none. */
2312d2201f2fSdrahn   if ((count == 0 || section->orelocation == NULL) &&
2313d2201f2fSdrahn       <writing_executable>)
2314d2201f2fSdrahn     return TRUE;
2315d2201f2fSdrahn #endif
2316d2201f2fSdrahn 
2317d2201f2fSdrahn   natsize = bfd_get_section_size_before_reloc (section);
2318d2201f2fSdrahn   native = (unsigned char *) bfd_zalloc (abfd, natsize);
2319d2201f2fSdrahn   if (!native)
2320d2201f2fSdrahn     return FALSE;
2321d2201f2fSdrahn 
2322d2201f2fSdrahn   generic = section->orelocation;
2323d2201f2fSdrahn   if (generic != NULL)
2324d2201f2fSdrahn     {
2325d2201f2fSdrahn       while (count > 0)
2326d2201f2fSdrahn 	{
2327d2201f2fSdrahn 	  struct pdp11_aout_reloc_external *r;
2328d2201f2fSdrahn 
2329d2201f2fSdrahn 	  r = (struct pdp11_aout_reloc_external *)
2330d2201f2fSdrahn 	    (native + (*generic)->address);
2331d2201f2fSdrahn 	  pdp11_aout_swap_reloc_out (abfd, *generic, r);
2332d2201f2fSdrahn 	  count--;
2333d2201f2fSdrahn 	  generic++;
2334d2201f2fSdrahn 	}
2335d2201f2fSdrahn     }
2336d2201f2fSdrahn 
2337d2201f2fSdrahn   if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
2338d2201f2fSdrahn     {
2339d2201f2fSdrahn       bfd_release (abfd, native);
2340d2201f2fSdrahn       return FALSE;
2341d2201f2fSdrahn     }
2342d2201f2fSdrahn 
2343d2201f2fSdrahn   bfd_release (abfd, native);
2344d2201f2fSdrahn   return TRUE;
2345d2201f2fSdrahn }
2346d2201f2fSdrahn 
2347d2201f2fSdrahn /* This is stupid.  This function should be a boolean predicate */
2348d2201f2fSdrahn long
2349d2201f2fSdrahn NAME(aout,canonicalize_reloc) (abfd, section, relptr, symbols)
2350d2201f2fSdrahn      bfd *abfd;
2351d2201f2fSdrahn      sec_ptr section;
2352d2201f2fSdrahn      arelent **relptr;
2353d2201f2fSdrahn      asymbol **symbols;
2354d2201f2fSdrahn {
2355d2201f2fSdrahn   arelent *tblptr = section->relocation;
2356d2201f2fSdrahn   unsigned int count;
2357d2201f2fSdrahn 
2358d2201f2fSdrahn   if (section == obj_bsssec (abfd))
2359d2201f2fSdrahn     {
2360d2201f2fSdrahn       *relptr = NULL;
2361d2201f2fSdrahn       return 0;
2362d2201f2fSdrahn     }
2363d2201f2fSdrahn 
2364d2201f2fSdrahn   if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
2365d2201f2fSdrahn     return -1;
2366d2201f2fSdrahn 
2367d2201f2fSdrahn   if (section->flags & SEC_CONSTRUCTOR)
2368d2201f2fSdrahn     {
2369d2201f2fSdrahn       arelent_chain *chain = section->constructor_chain;
2370d2201f2fSdrahn 
2371d2201f2fSdrahn       for (count = 0; count < section->reloc_count; count ++)
2372d2201f2fSdrahn 	{
2373d2201f2fSdrahn 	  *relptr ++ = &chain->relent;
2374d2201f2fSdrahn 	  chain = chain->next;
2375d2201f2fSdrahn 	}
2376d2201f2fSdrahn     }
2377d2201f2fSdrahn   else
2378d2201f2fSdrahn     {
2379d2201f2fSdrahn       tblptr = section->relocation;
2380d2201f2fSdrahn 
2381d2201f2fSdrahn       for (count = 0; count++ < section->reloc_count;)
2382d2201f2fSdrahn 	*relptr++ = tblptr++;
2383d2201f2fSdrahn     }
2384d2201f2fSdrahn 
2385d2201f2fSdrahn   *relptr = 0;
2386d2201f2fSdrahn 
2387d2201f2fSdrahn   return section->reloc_count;
2388d2201f2fSdrahn }
2389d2201f2fSdrahn 
2390d2201f2fSdrahn long
2391d2201f2fSdrahn NAME(aout,get_reloc_upper_bound) (abfd, asect)
2392d2201f2fSdrahn      bfd *abfd;
2393d2201f2fSdrahn      sec_ptr asect;
2394d2201f2fSdrahn {
2395d2201f2fSdrahn   if (bfd_get_format (abfd) != bfd_object)
2396d2201f2fSdrahn     {
2397d2201f2fSdrahn       bfd_set_error (bfd_error_invalid_operation);
2398d2201f2fSdrahn       return -1;
2399d2201f2fSdrahn     }
2400d2201f2fSdrahn 
2401d2201f2fSdrahn   if (asect->flags & SEC_CONSTRUCTOR)
2402d2201f2fSdrahn     return (sizeof (arelent *) * (asect->reloc_count+1));
2403d2201f2fSdrahn 
2404d2201f2fSdrahn   if (asect == obj_datasec (abfd))
2405d2201f2fSdrahn     return (sizeof (arelent *)
2406d2201f2fSdrahn 	    * ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
2407d2201f2fSdrahn 	       + 1));
2408d2201f2fSdrahn 
2409d2201f2fSdrahn   if (asect == obj_textsec (abfd))
2410d2201f2fSdrahn     return (sizeof (arelent *)
2411d2201f2fSdrahn 	    * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
2412d2201f2fSdrahn 	       + 1));
2413d2201f2fSdrahn 
2414d2201f2fSdrahn   /* TODO: why are there two if statements for obj_bsssec()? */
2415d2201f2fSdrahn 
2416d2201f2fSdrahn   if (asect == obj_bsssec (abfd))
2417d2201f2fSdrahn     return sizeof (arelent *);
2418d2201f2fSdrahn 
2419d2201f2fSdrahn   if (asect == obj_bsssec (abfd))
2420d2201f2fSdrahn     return 0;
2421d2201f2fSdrahn 
2422d2201f2fSdrahn   bfd_set_error (bfd_error_invalid_operation);
2423d2201f2fSdrahn   return -1;
2424d2201f2fSdrahn }
2425d2201f2fSdrahn 
2426d2201f2fSdrahn 
2427d2201f2fSdrahn long
2428d2201f2fSdrahn NAME(aout,get_symtab_upper_bound) (abfd)
2429d2201f2fSdrahn      bfd *abfd;
2430d2201f2fSdrahn {
2431d2201f2fSdrahn   if (!NAME(aout,slurp_symbol_table)(abfd))
2432d2201f2fSdrahn     return -1;
2433d2201f2fSdrahn 
2434d2201f2fSdrahn   return (bfd_get_symcount (abfd) + 1) * (sizeof (aout_symbol_type *));
2435d2201f2fSdrahn }
2436d2201f2fSdrahn 
2437d2201f2fSdrahn alent *
2438d2201f2fSdrahn NAME(aout,get_lineno) (abfd, symbol)
2439d2201f2fSdrahn      bfd * abfd ATTRIBUTE_UNUSED;
2440d2201f2fSdrahn      asymbol * symbol ATTRIBUTE_UNUSED;
2441d2201f2fSdrahn {
2442d2201f2fSdrahn   return (alent *)NULL;
2443d2201f2fSdrahn }
2444d2201f2fSdrahn 
2445d2201f2fSdrahn void
2446d2201f2fSdrahn NAME(aout,get_symbol_info) (abfd, symbol, ret)
2447d2201f2fSdrahn      bfd * abfd ATTRIBUTE_UNUSED;
2448d2201f2fSdrahn      asymbol *symbol;
2449d2201f2fSdrahn      symbol_info *ret;
2450d2201f2fSdrahn {
2451d2201f2fSdrahn   bfd_symbol_info (symbol, ret);
2452d2201f2fSdrahn 
2453d2201f2fSdrahn   if (ret->type == '?')
2454d2201f2fSdrahn     {
2455d2201f2fSdrahn       int type_code = aout_symbol(symbol)->type & 0xff;
2456d2201f2fSdrahn       const char *stab_name = bfd_get_stab_name (type_code);
2457d2201f2fSdrahn       static char buf[10];
2458d2201f2fSdrahn 
2459d2201f2fSdrahn       if (stab_name == NULL)
2460d2201f2fSdrahn 	{
2461d2201f2fSdrahn 	  sprintf(buf, "(%d)", type_code);
2462d2201f2fSdrahn 	  stab_name = buf;
2463d2201f2fSdrahn 	}
2464d2201f2fSdrahn       ret->type = '-';
2465d2201f2fSdrahn       ret->stab_type = type_code;
2466d2201f2fSdrahn       ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff);
2467d2201f2fSdrahn       ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff);
2468d2201f2fSdrahn       ret->stab_name = stab_name;
2469d2201f2fSdrahn     }
2470d2201f2fSdrahn }
2471d2201f2fSdrahn 
2472d2201f2fSdrahn void
2473d2201f2fSdrahn NAME(aout,print_symbol) (abfd, afile, symbol, how)
2474d2201f2fSdrahn      bfd * abfd;
2475d2201f2fSdrahn      PTR afile;
2476d2201f2fSdrahn      asymbol *symbol;
2477d2201f2fSdrahn      bfd_print_symbol_type how;
2478d2201f2fSdrahn {
2479d2201f2fSdrahn   FILE *file = (FILE *)afile;
2480d2201f2fSdrahn 
2481d2201f2fSdrahn   switch (how)
2482d2201f2fSdrahn     {
2483d2201f2fSdrahn     case bfd_print_symbol_name:
2484d2201f2fSdrahn       if (symbol->name)
2485d2201f2fSdrahn 	fprintf(file,"%s", symbol->name);
2486d2201f2fSdrahn       break;
2487d2201f2fSdrahn     case bfd_print_symbol_more:
2488d2201f2fSdrahn       fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
2489d2201f2fSdrahn 	      (unsigned)(aout_symbol(symbol)->other & 0xff),
2490d2201f2fSdrahn 	      (unsigned)(aout_symbol(symbol)->type));
2491d2201f2fSdrahn       break;
2492d2201f2fSdrahn     case bfd_print_symbol_all:
2493d2201f2fSdrahn       {
2494d2201f2fSdrahn 	const char *section_name = symbol->section->name;
2495d2201f2fSdrahn 
2496d2201f2fSdrahn 	bfd_print_symbol_vandf (abfd, (PTR)file, symbol);
2497d2201f2fSdrahn 
2498d2201f2fSdrahn 	fprintf (file," %-5s %04x %02x %02x",
2499d2201f2fSdrahn 		 section_name,
2500d2201f2fSdrahn 		 (unsigned)(aout_symbol(symbol)->desc & 0xffff),
2501d2201f2fSdrahn 		 (unsigned)(aout_symbol(symbol)->other & 0xff),
2502d2201f2fSdrahn 		 (unsigned)(aout_symbol(symbol)->type  & 0xff));
2503d2201f2fSdrahn 	if (symbol->name)
2504d2201f2fSdrahn 	  fprintf(file," %s", symbol->name);
2505d2201f2fSdrahn       }
2506d2201f2fSdrahn       break;
2507d2201f2fSdrahn     }
2508d2201f2fSdrahn }
2509d2201f2fSdrahn 
2510d2201f2fSdrahn /* If we don't have to allocate more than 1MB to hold the generic
2511d2201f2fSdrahn    symbols, we use the generic minisymbol method: it's faster, since
2512d2201f2fSdrahn    it only translates the symbols once, not multiple times.  */
2513d2201f2fSdrahn #define MINISYM_THRESHOLD (1000000 / sizeof (asymbol))
2514d2201f2fSdrahn 
2515d2201f2fSdrahn /* Read minisymbols.  For minisymbols, we use the unmodified a.out
2516d2201f2fSdrahn    symbols.  The minisymbol_to_symbol function translates these into
2517d2201f2fSdrahn    BFD asymbol structures.  */
2518d2201f2fSdrahn 
2519d2201f2fSdrahn long
2520d2201f2fSdrahn NAME(aout,read_minisymbols) (abfd, dynamic, minisymsp, sizep)
2521d2201f2fSdrahn      bfd *abfd;
2522d2201f2fSdrahn      bfd_boolean dynamic;
2523d2201f2fSdrahn      PTR *minisymsp;
2524d2201f2fSdrahn      unsigned int *sizep;
2525d2201f2fSdrahn {
2526d2201f2fSdrahn   if (dynamic)
2527d2201f2fSdrahn     {
2528d2201f2fSdrahn       /* We could handle the dynamic symbols here as well, but it's
2529d2201f2fSdrahn          easier to hand them off.  */
2530d2201f2fSdrahn       return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
2531d2201f2fSdrahn     }
2532d2201f2fSdrahn 
2533d2201f2fSdrahn   if (! aout_get_external_symbols (abfd))
2534d2201f2fSdrahn     return -1;
2535d2201f2fSdrahn 
2536d2201f2fSdrahn   if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
2537d2201f2fSdrahn     return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
2538d2201f2fSdrahn 
2539d2201f2fSdrahn   *minisymsp = (PTR) obj_aout_external_syms (abfd);
2540d2201f2fSdrahn 
2541d2201f2fSdrahn   /* By passing the external symbols back from this routine, we are
2542d2201f2fSdrahn      giving up control over the memory block.  Clear
2543d2201f2fSdrahn      obj_aout_external_syms, so that we do not try to free it
2544d2201f2fSdrahn      ourselves.  */
2545d2201f2fSdrahn   obj_aout_external_syms (abfd) = NULL;
2546d2201f2fSdrahn 
2547d2201f2fSdrahn   *sizep = EXTERNAL_NLIST_SIZE;
2548d2201f2fSdrahn   return obj_aout_external_sym_count (abfd);
2549d2201f2fSdrahn }
2550d2201f2fSdrahn 
2551d2201f2fSdrahn /* Convert a minisymbol to a BFD asymbol.  A minisymbol is just an
2552d2201f2fSdrahn    unmodified a.out symbol.  The SYM argument is a structure returned
2553d2201f2fSdrahn    by bfd_make_empty_symbol, which we fill in here.  */
2554d2201f2fSdrahn 
2555d2201f2fSdrahn asymbol *
2556d2201f2fSdrahn NAME(aout,minisymbol_to_symbol) (abfd, dynamic, minisym, sym)
2557d2201f2fSdrahn      bfd *abfd;
2558d2201f2fSdrahn      bfd_boolean dynamic;
2559d2201f2fSdrahn      const PTR minisym;
2560d2201f2fSdrahn      asymbol *sym;
2561d2201f2fSdrahn {
2562d2201f2fSdrahn   if (dynamic
2563d2201f2fSdrahn       || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
2564d2201f2fSdrahn     return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym);
2565d2201f2fSdrahn 
2566d2201f2fSdrahn   memset (sym, 0, sizeof (aout_symbol_type));
2567d2201f2fSdrahn 
2568d2201f2fSdrahn   /* We call translate_symbol_table to translate a single symbol.  */
2569d2201f2fSdrahn   if (! (NAME(aout,translate_symbol_table)
2570d2201f2fSdrahn 	 (abfd,
2571d2201f2fSdrahn 	  (aout_symbol_type *) sym,
2572d2201f2fSdrahn 	  (struct external_nlist *) minisym,
2573d2201f2fSdrahn 	  (bfd_size_type) 1,
2574d2201f2fSdrahn 	  obj_aout_external_strings (abfd),
2575d2201f2fSdrahn 	  obj_aout_external_string_size (abfd),
2576d2201f2fSdrahn 	  FALSE)))
2577d2201f2fSdrahn     return NULL;
2578d2201f2fSdrahn 
2579d2201f2fSdrahn   return sym;
2580d2201f2fSdrahn }
2581d2201f2fSdrahn 
2582d2201f2fSdrahn /*
2583d2201f2fSdrahn  provided a BFD, a section and an offset into the section, calculate
2584d2201f2fSdrahn  and return the name of the source file and the line nearest to the
2585d2201f2fSdrahn  wanted location.
2586d2201f2fSdrahn */
2587d2201f2fSdrahn 
2588d2201f2fSdrahn bfd_boolean
2589d2201f2fSdrahn NAME(aout,find_nearest_line)
2590d2201f2fSdrahn      (abfd, section, symbols, offset, filename_ptr, functionname_ptr, line_ptr)
2591d2201f2fSdrahn      bfd *abfd;
2592d2201f2fSdrahn      asection *section;
2593d2201f2fSdrahn      asymbol **symbols;
2594d2201f2fSdrahn      bfd_vma offset;
2595d2201f2fSdrahn      const char **filename_ptr;
2596d2201f2fSdrahn      const char **functionname_ptr;
2597d2201f2fSdrahn      unsigned int *line_ptr;
2598d2201f2fSdrahn {
2599d2201f2fSdrahn   /* Run down the file looking for the filename, function and linenumber */
2600d2201f2fSdrahn   asymbol **p;
2601d2201f2fSdrahn   const char *directory_name = NULL;
2602d2201f2fSdrahn   const char *main_file_name = NULL;
2603d2201f2fSdrahn   const char *current_file_name = NULL;
2604d2201f2fSdrahn   const char *line_file_name = NULL; /* Value of current_file_name at line number. */
2605d2201f2fSdrahn   bfd_vma low_line_vma = 0;
2606d2201f2fSdrahn   bfd_vma low_func_vma = 0;
2607d2201f2fSdrahn   asymbol *func = 0;
2608d2201f2fSdrahn   size_t filelen, funclen;
2609d2201f2fSdrahn   char *buf;
2610d2201f2fSdrahn 
2611d2201f2fSdrahn   *filename_ptr = abfd->filename;
2612d2201f2fSdrahn   *functionname_ptr = 0;
2613d2201f2fSdrahn   *line_ptr = 0;
2614d2201f2fSdrahn 
2615d2201f2fSdrahn   if (symbols != (asymbol **)NULL)
2616d2201f2fSdrahn     {
2617d2201f2fSdrahn       for (p = symbols; *p; p++)
2618d2201f2fSdrahn 	{
2619d2201f2fSdrahn 	  aout_symbol_type  *q = (aout_symbol_type *)(*p);
2620d2201f2fSdrahn 	next:
2621d2201f2fSdrahn 	  switch (q->type)
2622d2201f2fSdrahn 	    {
2623d2201f2fSdrahn 	    case N_TEXT:
2624d2201f2fSdrahn 	      /* If this looks like a file name symbol, and it comes after
2625d2201f2fSdrahn 		 the line number we have found so far, but before the
2626d2201f2fSdrahn 		 offset, then we have probably not found the right line
2627d2201f2fSdrahn 		 number.  */
2628d2201f2fSdrahn 	      if (q->symbol.value <= offset
2629d2201f2fSdrahn 		  && ((q->symbol.value > low_line_vma
2630d2201f2fSdrahn 		       && (line_file_name != NULL
2631d2201f2fSdrahn 			   || *line_ptr != 0))
2632d2201f2fSdrahn 		      || (q->symbol.value > low_func_vma
2633d2201f2fSdrahn 			  && func != NULL)))
2634d2201f2fSdrahn 		{
2635d2201f2fSdrahn 		  const char * symname;
2636d2201f2fSdrahn 
2637d2201f2fSdrahn 		  symname = q->symbol.name;
2638d2201f2fSdrahn 		  if (strcmp (symname + strlen (symname) - 2, ".o") == 0)
2639d2201f2fSdrahn 		    {
2640d2201f2fSdrahn 		      if (q->symbol.value > low_line_vma)
2641d2201f2fSdrahn 			{
2642d2201f2fSdrahn 			  *line_ptr = 0;
2643d2201f2fSdrahn 			  line_file_name = NULL;
2644d2201f2fSdrahn 			}
2645d2201f2fSdrahn 		      if (q->symbol.value > low_func_vma)
2646d2201f2fSdrahn 			func = NULL;
2647d2201f2fSdrahn 		    }
2648d2201f2fSdrahn 		}
2649d2201f2fSdrahn 	      break;
2650d2201f2fSdrahn 
2651d2201f2fSdrahn 	    case N_SO:
2652d2201f2fSdrahn 	      /* If this symbol is less than the offset, but greater than
2653d2201f2fSdrahn 		 the line number we have found so far, then we have not
2654d2201f2fSdrahn 		 found the right line number.  */
2655d2201f2fSdrahn 	      if (q->symbol.value <= offset)
2656d2201f2fSdrahn 		{
2657d2201f2fSdrahn 		  if (q->symbol.value > low_line_vma)
2658d2201f2fSdrahn 		    {
2659d2201f2fSdrahn 		      *line_ptr = 0;
2660d2201f2fSdrahn 		      line_file_name = NULL;
2661d2201f2fSdrahn 		    }
2662d2201f2fSdrahn 		  if (q->symbol.value > low_func_vma)
2663d2201f2fSdrahn 		    func = NULL;
2664d2201f2fSdrahn 		}
2665d2201f2fSdrahn 
2666d2201f2fSdrahn 	      main_file_name = current_file_name = q->symbol.name;
2667d2201f2fSdrahn 	      /* Look ahead to next symbol to check if that too is an N_SO. */
2668d2201f2fSdrahn 	      p++;
2669d2201f2fSdrahn 	      if (*p == NULL)
2670d2201f2fSdrahn 		break;
2671d2201f2fSdrahn 	      q = (aout_symbol_type *)(*p);
2672d2201f2fSdrahn 	      if (q->type != (int)N_SO)
2673d2201f2fSdrahn 		goto next;
2674d2201f2fSdrahn 
2675d2201f2fSdrahn 	      /* Found a second N_SO  First is directory; second is filename. */
2676d2201f2fSdrahn 	      directory_name = current_file_name;
2677d2201f2fSdrahn 	      main_file_name = current_file_name = q->symbol.name;
2678d2201f2fSdrahn 	      if (obj_textsec(abfd) != section)
2679d2201f2fSdrahn 		goto done;
2680d2201f2fSdrahn 	      break;
2681d2201f2fSdrahn 	    case N_SOL:
2682d2201f2fSdrahn 	      current_file_name = q->symbol.name;
2683d2201f2fSdrahn 	      break;
2684d2201f2fSdrahn 
2685d2201f2fSdrahn 	    case N_SLINE:
2686d2201f2fSdrahn 	    case N_DSLINE:
2687d2201f2fSdrahn 	    case N_BSLINE:
2688d2201f2fSdrahn 	      /* We'll keep this if it resolves nearer than the one we have
2689d2201f2fSdrahn 		 already.  */
2690d2201f2fSdrahn 	      if (q->symbol.value >= low_line_vma
2691d2201f2fSdrahn 		  && q->symbol.value <= offset)
2692d2201f2fSdrahn 		{
2693d2201f2fSdrahn 		  *line_ptr = q->desc;
2694d2201f2fSdrahn 		  low_line_vma = q->symbol.value;
2695d2201f2fSdrahn 		  line_file_name = current_file_name;
2696d2201f2fSdrahn 		}
2697d2201f2fSdrahn 	      break;
2698d2201f2fSdrahn 
2699d2201f2fSdrahn 	    case N_FUN:
2700d2201f2fSdrahn 	      {
2701d2201f2fSdrahn 		/* We'll keep this if it is nearer than the one we have already */
2702d2201f2fSdrahn 		if (q->symbol.value >= low_func_vma &&
2703d2201f2fSdrahn 		    q->symbol.value <= offset)
2704d2201f2fSdrahn 		  {
2705d2201f2fSdrahn 		    low_func_vma = q->symbol.value;
2706d2201f2fSdrahn 		    func = (asymbol *)q;
2707d2201f2fSdrahn 		  }
2708d2201f2fSdrahn 		else if (q->symbol.value > offset)
2709d2201f2fSdrahn 		  goto done;
2710d2201f2fSdrahn 	      }
2711d2201f2fSdrahn 	      break;
2712d2201f2fSdrahn 	    }
2713d2201f2fSdrahn 	}
2714d2201f2fSdrahn     }
2715d2201f2fSdrahn 
2716d2201f2fSdrahn  done:
2717d2201f2fSdrahn   if (*line_ptr != 0)
2718d2201f2fSdrahn     main_file_name = line_file_name;
2719d2201f2fSdrahn 
2720d2201f2fSdrahn   if (main_file_name == NULL
2721d2201f2fSdrahn       || main_file_name[0] == '/'
2722d2201f2fSdrahn       || directory_name == NULL)
2723d2201f2fSdrahn     filelen = 0;
2724d2201f2fSdrahn   else
2725d2201f2fSdrahn     filelen = strlen (directory_name) + strlen (main_file_name);
2726d2201f2fSdrahn   if (func == NULL)
2727d2201f2fSdrahn     funclen = 0;
2728d2201f2fSdrahn   else
2729d2201f2fSdrahn     funclen = strlen (bfd_asymbol_name (func));
2730d2201f2fSdrahn 
2731d2201f2fSdrahn   if (adata (abfd).line_buf != NULL)
2732d2201f2fSdrahn     free (adata (abfd).line_buf);
2733d2201f2fSdrahn   if (filelen + funclen == 0)
2734d2201f2fSdrahn     adata (abfd).line_buf = buf = NULL;
2735d2201f2fSdrahn   else
2736d2201f2fSdrahn     {
2737d2201f2fSdrahn       buf = (char *) bfd_malloc ((bfd_size_type) filelen + funclen + 3);
2738d2201f2fSdrahn       adata (abfd).line_buf = buf;
2739d2201f2fSdrahn       if (buf == NULL)
2740d2201f2fSdrahn 	return FALSE;
2741d2201f2fSdrahn     }
2742d2201f2fSdrahn 
2743d2201f2fSdrahn   if (main_file_name != NULL)
2744d2201f2fSdrahn     {
2745d2201f2fSdrahn       if (main_file_name[0] == '/' || directory_name == NULL)
2746d2201f2fSdrahn 	*filename_ptr = main_file_name;
2747d2201f2fSdrahn       else
2748d2201f2fSdrahn 	{
2749d2201f2fSdrahn 	  sprintf (buf, "%s%s", directory_name, main_file_name);
2750d2201f2fSdrahn 	  *filename_ptr = buf;
2751d2201f2fSdrahn 	  buf += filelen + 1;
2752d2201f2fSdrahn 	}
2753d2201f2fSdrahn     }
2754d2201f2fSdrahn 
2755d2201f2fSdrahn   if (func)
2756d2201f2fSdrahn     {
2757d2201f2fSdrahn       const char *function = func->name;
2758d2201f2fSdrahn       char *colon;
2759d2201f2fSdrahn 
2760d2201f2fSdrahn       /* The caller expects a symbol name.  We actually have a
2761d2201f2fSdrahn 	 function name, without the leading underscore.  Put the
2762d2201f2fSdrahn 	 underscore back in, so that the caller gets a symbol name.  */
2763d2201f2fSdrahn       if (bfd_get_symbol_leading_char (abfd) == '\0')
2764d2201f2fSdrahn 	strcpy (buf, function);
2765d2201f2fSdrahn       else
2766d2201f2fSdrahn 	{
2767d2201f2fSdrahn 	  buf[0] = bfd_get_symbol_leading_char (abfd);
2768d2201f2fSdrahn 	  strcpy (buf + 1, function);
2769d2201f2fSdrahn 	}
2770d2201f2fSdrahn 
2771d2201f2fSdrahn       /* Have to remove : stuff.  */
2772d2201f2fSdrahn       colon = strchr (buf, ':');
2773d2201f2fSdrahn       if (colon != NULL)
2774d2201f2fSdrahn 	*colon = '\0';
2775d2201f2fSdrahn       *functionname_ptr = buf;
2776d2201f2fSdrahn     }
2777d2201f2fSdrahn 
2778d2201f2fSdrahn   return TRUE;
2779d2201f2fSdrahn }
2780d2201f2fSdrahn 
2781d2201f2fSdrahn int
2782d2201f2fSdrahn NAME(aout,sizeof_headers) (abfd, execable)
2783d2201f2fSdrahn      bfd *abfd;
2784d2201f2fSdrahn      bfd_boolean execable ATTRIBUTE_UNUSED;
2785d2201f2fSdrahn {
2786d2201f2fSdrahn   return adata(abfd).exec_bytes_size;
2787d2201f2fSdrahn }
2788d2201f2fSdrahn 
2789d2201f2fSdrahn /* Free all information we have cached for this BFD.  We can always
2790d2201f2fSdrahn    read it again later if we need it.  */
2791d2201f2fSdrahn 
2792d2201f2fSdrahn bfd_boolean
2793d2201f2fSdrahn NAME(aout,bfd_free_cached_info) (abfd)
2794d2201f2fSdrahn      bfd *abfd;
2795d2201f2fSdrahn {
2796d2201f2fSdrahn   asection *o;
2797d2201f2fSdrahn 
2798d2201f2fSdrahn   if (bfd_get_format (abfd) != bfd_object)
2799d2201f2fSdrahn     return TRUE;
2800d2201f2fSdrahn 
2801d2201f2fSdrahn #define BFCI_FREE(x) if (x != NULL) { free (x); x = NULL; }
2802d2201f2fSdrahn   BFCI_FREE (obj_aout_symbols (abfd));
2803d2201f2fSdrahn #ifdef USE_MMAP
2804d2201f2fSdrahn   obj_aout_external_syms (abfd) = 0;
2805d2201f2fSdrahn   bfd_free_window (&obj_aout_sym_window (abfd));
2806d2201f2fSdrahn   bfd_free_window (&obj_aout_string_window (abfd));
2807d2201f2fSdrahn   obj_aout_external_strings (abfd) = 0;
2808d2201f2fSdrahn #else
2809d2201f2fSdrahn   BFCI_FREE (obj_aout_external_syms (abfd));
2810d2201f2fSdrahn   BFCI_FREE (obj_aout_external_strings (abfd));
2811d2201f2fSdrahn #endif
2812d2201f2fSdrahn   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
2813d2201f2fSdrahn     BFCI_FREE (o->relocation);
2814d2201f2fSdrahn #undef BFCI_FREE
2815d2201f2fSdrahn 
2816d2201f2fSdrahn   return TRUE;
2817d2201f2fSdrahn }
2818d2201f2fSdrahn 
2819d2201f2fSdrahn /* a.out link code.  */
2820d2201f2fSdrahn 
2821d2201f2fSdrahn static bfd_boolean aout_link_add_object_symbols
2822d2201f2fSdrahn   PARAMS ((bfd *, struct bfd_link_info *));
2823d2201f2fSdrahn static bfd_boolean aout_link_check_archive_element
2824d2201f2fSdrahn   PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *));
2825d2201f2fSdrahn static bfd_boolean aout_link_free_symbols PARAMS ((bfd *));
2826d2201f2fSdrahn static bfd_boolean aout_link_check_ar_symbols
2827d2201f2fSdrahn   PARAMS ((bfd *, struct bfd_link_info *, bfd_boolean *pneeded));
2828d2201f2fSdrahn static bfd_boolean aout_link_add_symbols
2829d2201f2fSdrahn   PARAMS ((bfd *, struct bfd_link_info *));
2830d2201f2fSdrahn 
2831d2201f2fSdrahn /* Routine to create an entry in an a.out link hash table.  */
2832d2201f2fSdrahn 
2833d2201f2fSdrahn struct bfd_hash_entry *
2834d2201f2fSdrahn NAME(aout,link_hash_newfunc) (entry, table, string)
2835d2201f2fSdrahn      struct bfd_hash_entry *entry;
2836d2201f2fSdrahn      struct bfd_hash_table *table;
2837d2201f2fSdrahn      const char *string;
2838d2201f2fSdrahn {
2839d2201f2fSdrahn   struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry;
2840d2201f2fSdrahn 
2841d2201f2fSdrahn   /* Allocate the structure if it has not already been allocated by a
2842d2201f2fSdrahn      subclass.  */
2843d2201f2fSdrahn   if (ret == (struct aout_link_hash_entry *) NULL)
2844d2201f2fSdrahn     ret = ((struct aout_link_hash_entry *)
2845d2201f2fSdrahn 	   bfd_hash_allocate (table, sizeof (struct aout_link_hash_entry)));
2846d2201f2fSdrahn   if (ret == (struct aout_link_hash_entry *) NULL)
2847d2201f2fSdrahn     return (struct bfd_hash_entry *) ret;
2848d2201f2fSdrahn 
2849d2201f2fSdrahn   /* Call the allocation method of the superclass.  */
2850d2201f2fSdrahn   ret = ((struct aout_link_hash_entry *)
2851d2201f2fSdrahn 	 _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
2852d2201f2fSdrahn 				 table, string));
2853d2201f2fSdrahn   if (ret)
2854d2201f2fSdrahn     {
2855d2201f2fSdrahn       /* Set local fields.  */
2856d2201f2fSdrahn       ret->written = FALSE;
2857d2201f2fSdrahn       ret->indx = -1;
2858d2201f2fSdrahn     }
2859d2201f2fSdrahn 
2860d2201f2fSdrahn   return (struct bfd_hash_entry *) ret;
2861d2201f2fSdrahn }
2862d2201f2fSdrahn 
2863d2201f2fSdrahn /* Initialize an a.out link hash table.  */
2864d2201f2fSdrahn 
2865d2201f2fSdrahn bfd_boolean
2866d2201f2fSdrahn NAME(aout,link_hash_table_init) (table, abfd, newfunc)
2867d2201f2fSdrahn      struct aout_link_hash_table *table;
2868d2201f2fSdrahn      bfd *abfd;
2869d2201f2fSdrahn      struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
2870d2201f2fSdrahn 						struct bfd_hash_table *,
2871d2201f2fSdrahn 						const char *));
2872d2201f2fSdrahn {
2873d2201f2fSdrahn   return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
2874d2201f2fSdrahn }
2875d2201f2fSdrahn 
2876d2201f2fSdrahn /* Create an a.out link hash table.  */
2877d2201f2fSdrahn 
2878d2201f2fSdrahn struct bfd_link_hash_table *
2879d2201f2fSdrahn NAME(aout,link_hash_table_create) (abfd)
2880d2201f2fSdrahn      bfd *abfd;
2881d2201f2fSdrahn {
2882d2201f2fSdrahn   struct aout_link_hash_table *ret;
2883d2201f2fSdrahn   bfd_size_type amt = sizeof (struct aout_link_hash_table);
2884d2201f2fSdrahn 
2885d2201f2fSdrahn   ret = ((struct aout_link_hash_table *) bfd_alloc (abfd, amt));
2886d2201f2fSdrahn   if (ret == NULL)
2887d2201f2fSdrahn     return (struct bfd_link_hash_table *) NULL;
2888d2201f2fSdrahn   if (! NAME(aout,link_hash_table_init) (ret, abfd,
2889d2201f2fSdrahn 					 NAME(aout,link_hash_newfunc)))
2890d2201f2fSdrahn     {
2891d2201f2fSdrahn       free (ret);
2892d2201f2fSdrahn       return (struct bfd_link_hash_table *) NULL;
2893d2201f2fSdrahn     }
2894d2201f2fSdrahn   return &ret->root;
2895d2201f2fSdrahn }
2896d2201f2fSdrahn 
2897d2201f2fSdrahn /* Given an a.out BFD, add symbols to the global hash table as
2898d2201f2fSdrahn    appropriate.  */
2899d2201f2fSdrahn 
2900d2201f2fSdrahn bfd_boolean
2901d2201f2fSdrahn NAME(aout,link_add_symbols) (abfd, info)
2902d2201f2fSdrahn      bfd *abfd;
2903d2201f2fSdrahn      struct bfd_link_info *info;
2904d2201f2fSdrahn {
2905d2201f2fSdrahn   switch (bfd_get_format (abfd))
2906d2201f2fSdrahn     {
2907d2201f2fSdrahn     case bfd_object:
2908d2201f2fSdrahn       return aout_link_add_object_symbols (abfd, info);
2909d2201f2fSdrahn     case bfd_archive:
2910d2201f2fSdrahn       return _bfd_generic_link_add_archive_symbols
2911d2201f2fSdrahn 	(abfd, info, aout_link_check_archive_element);
2912d2201f2fSdrahn     default:
2913d2201f2fSdrahn       bfd_set_error (bfd_error_wrong_format);
2914d2201f2fSdrahn       return FALSE;
2915d2201f2fSdrahn     }
2916d2201f2fSdrahn }
2917d2201f2fSdrahn 
2918d2201f2fSdrahn /* Add symbols from an a.out object file.  */
2919d2201f2fSdrahn 
2920d2201f2fSdrahn static bfd_boolean
aout_link_add_object_symbols(abfd,info)2921d2201f2fSdrahn aout_link_add_object_symbols (abfd, info)
2922d2201f2fSdrahn      bfd *abfd;
2923d2201f2fSdrahn      struct bfd_link_info *info;
2924d2201f2fSdrahn {
2925d2201f2fSdrahn   if (! aout_get_external_symbols (abfd))
2926d2201f2fSdrahn     return FALSE;
2927d2201f2fSdrahn   if (! aout_link_add_symbols (abfd, info))
2928d2201f2fSdrahn     return FALSE;
2929d2201f2fSdrahn   if (! info->keep_memory)
2930d2201f2fSdrahn     {
2931d2201f2fSdrahn       if (! aout_link_free_symbols (abfd))
2932d2201f2fSdrahn 	return FALSE;
2933d2201f2fSdrahn     }
2934d2201f2fSdrahn   return TRUE;
2935d2201f2fSdrahn }
2936d2201f2fSdrahn 
2937d2201f2fSdrahn /* Check a single archive element to see if we need to include it in
2938d2201f2fSdrahn    the link.  *PNEEDED is set according to whether this element is
2939d2201f2fSdrahn    needed in the link or not.  This is called from
2940d2201f2fSdrahn    _bfd_generic_link_add_archive_symbols.  */
2941d2201f2fSdrahn 
2942d2201f2fSdrahn static bfd_boolean
aout_link_check_archive_element(abfd,info,pneeded)2943d2201f2fSdrahn aout_link_check_archive_element (abfd, info, pneeded)
2944d2201f2fSdrahn      bfd *abfd;
2945d2201f2fSdrahn      struct bfd_link_info *info;
2946d2201f2fSdrahn      bfd_boolean *pneeded;
2947d2201f2fSdrahn {
2948d2201f2fSdrahn   if (! aout_get_external_symbols (abfd))
2949d2201f2fSdrahn     return FALSE;
2950d2201f2fSdrahn 
2951d2201f2fSdrahn   if (! aout_link_check_ar_symbols (abfd, info, pneeded))
2952d2201f2fSdrahn     return FALSE;
2953d2201f2fSdrahn 
2954d2201f2fSdrahn   if (*pneeded)
2955d2201f2fSdrahn     {
2956d2201f2fSdrahn       if (! aout_link_add_symbols (abfd, info))
2957d2201f2fSdrahn 	return FALSE;
2958d2201f2fSdrahn     }
2959d2201f2fSdrahn 
2960d2201f2fSdrahn   if (! info->keep_memory || ! *pneeded)
2961d2201f2fSdrahn     {
2962d2201f2fSdrahn       if (! aout_link_free_symbols (abfd))
2963d2201f2fSdrahn 	return FALSE;
2964d2201f2fSdrahn     }
2965d2201f2fSdrahn 
2966d2201f2fSdrahn   return TRUE;
2967d2201f2fSdrahn }
2968d2201f2fSdrahn 
2969d2201f2fSdrahn /* Free up the internal symbols read from an a.out file.  */
2970d2201f2fSdrahn 
2971d2201f2fSdrahn static bfd_boolean
aout_link_free_symbols(abfd)2972d2201f2fSdrahn aout_link_free_symbols (abfd)
2973d2201f2fSdrahn      bfd *abfd;
2974d2201f2fSdrahn {
2975d2201f2fSdrahn   if (obj_aout_external_syms (abfd) != (struct external_nlist *) NULL)
2976d2201f2fSdrahn     {
2977d2201f2fSdrahn #ifdef USE_MMAP
2978d2201f2fSdrahn       bfd_free_window (&obj_aout_sym_window (abfd));
2979d2201f2fSdrahn #else
2980d2201f2fSdrahn       free ((PTR) obj_aout_external_syms (abfd));
2981d2201f2fSdrahn #endif
2982d2201f2fSdrahn       obj_aout_external_syms (abfd) = (struct external_nlist *) NULL;
2983d2201f2fSdrahn     }
2984d2201f2fSdrahn   if (obj_aout_external_strings (abfd) != (char *) NULL)
2985d2201f2fSdrahn     {
2986d2201f2fSdrahn #ifdef USE_MMAP
2987d2201f2fSdrahn       bfd_free_window (&obj_aout_string_window (abfd));
2988d2201f2fSdrahn #else
2989d2201f2fSdrahn       free ((PTR) obj_aout_external_strings (abfd));
2990d2201f2fSdrahn #endif
2991d2201f2fSdrahn       obj_aout_external_strings (abfd) = (char *) NULL;
2992d2201f2fSdrahn     }
2993d2201f2fSdrahn   return TRUE;
2994d2201f2fSdrahn }
2995d2201f2fSdrahn 
2996d2201f2fSdrahn /* Look through the internal symbols to see if this object file should
2997d2201f2fSdrahn    be included in the link.  We should include this object file if it
2998d2201f2fSdrahn    defines any symbols which are currently undefined.  If this object
2999d2201f2fSdrahn    file defines a common symbol, then we may adjust the size of the
3000d2201f2fSdrahn    known symbol but we do not include the object file in the link
3001d2201f2fSdrahn    (unless there is some other reason to include it).  */
3002d2201f2fSdrahn 
3003d2201f2fSdrahn static bfd_boolean
aout_link_check_ar_symbols(abfd,info,pneeded)3004d2201f2fSdrahn aout_link_check_ar_symbols (abfd, info, pneeded)
3005d2201f2fSdrahn      bfd *abfd;
3006d2201f2fSdrahn      struct bfd_link_info *info;
3007d2201f2fSdrahn      bfd_boolean *pneeded;
3008d2201f2fSdrahn {
3009d2201f2fSdrahn   register struct external_nlist *p;
3010d2201f2fSdrahn   struct external_nlist *pend;
3011d2201f2fSdrahn   char *strings;
3012d2201f2fSdrahn 
3013d2201f2fSdrahn   *pneeded = FALSE;
3014d2201f2fSdrahn 
3015d2201f2fSdrahn   /* Look through all the symbols.  */
3016d2201f2fSdrahn   p = obj_aout_external_syms (abfd);
3017d2201f2fSdrahn   pend = p + obj_aout_external_sym_count (abfd);
3018d2201f2fSdrahn   strings = obj_aout_external_strings (abfd);
3019d2201f2fSdrahn   for (; p < pend; p++)
3020d2201f2fSdrahn     {
3021d2201f2fSdrahn       int type = H_GET_8 (abfd, p->e_type);
3022d2201f2fSdrahn       const char *name;
3023d2201f2fSdrahn       struct bfd_link_hash_entry *h;
3024d2201f2fSdrahn 
3025d2201f2fSdrahn       /* Ignore symbols that are not externally visible.  This is an
3026d2201f2fSdrahn 	 optimization only, as we check the type more thoroughly
3027d2201f2fSdrahn 	 below.  */
3028d2201f2fSdrahn       if ((type & N_EXT) == 0
3029d2201f2fSdrahn 	  || type == N_FN)
3030d2201f2fSdrahn 	continue;
3031d2201f2fSdrahn 
3032d2201f2fSdrahn       name = strings + GET_WORD (abfd, p->e_strx);
3033d2201f2fSdrahn       h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
3034d2201f2fSdrahn 
3035d2201f2fSdrahn       /* We are only interested in symbols that are currently
3036d2201f2fSdrahn 	 undefined or common.  */
3037d2201f2fSdrahn       if (h == (struct bfd_link_hash_entry *) NULL
3038d2201f2fSdrahn 	  || (h->type != bfd_link_hash_undefined
3039d2201f2fSdrahn 	      && h->type != bfd_link_hash_common))
3040d2201f2fSdrahn 	continue;
3041d2201f2fSdrahn 
3042d2201f2fSdrahn       if (type == (N_TEXT | N_EXT)
3043d2201f2fSdrahn 	  || type == (N_DATA | N_EXT)
3044d2201f2fSdrahn 	  || type == (N_BSS | N_EXT)
3045d2201f2fSdrahn 	  || type == (N_ABS | N_EXT))
3046d2201f2fSdrahn 	{
3047d2201f2fSdrahn 	  /* This object file defines this symbol.  We must link it
3048d2201f2fSdrahn 	     in.  This is true regardless of whether the current
3049d2201f2fSdrahn 	     definition of the symbol is undefined or common.  If the
3050d2201f2fSdrahn 	     current definition is common, we have a case in which we
3051d2201f2fSdrahn 	     have already seen an object file including
3052d2201f2fSdrahn 	         int a;
3053d2201f2fSdrahn 	     and this object file from the archive includes
3054d2201f2fSdrahn 	         int a = 5;
3055d2201f2fSdrahn 	     In such a case we must include this object file.
3056d2201f2fSdrahn 
3057d2201f2fSdrahn 	     FIXME: The SunOS 4.1.3 linker will pull in the archive
3058d2201f2fSdrahn 	     element if the symbol is defined in the .data section,
3059d2201f2fSdrahn 	     but not if it is defined in the .text section.  That
3060d2201f2fSdrahn 	     seems a bit crazy to me, and I haven't implemented it.
3061d2201f2fSdrahn 	     However, it might be correct.  */
3062d2201f2fSdrahn 	  if (! (*info->callbacks->add_archive_element) (info, abfd, name))
3063d2201f2fSdrahn 	    return FALSE;
3064d2201f2fSdrahn 	  *pneeded = TRUE;
3065d2201f2fSdrahn 	  return TRUE;
3066d2201f2fSdrahn 	}
3067d2201f2fSdrahn 
3068d2201f2fSdrahn       if (type == (N_UNDF | N_EXT))
3069d2201f2fSdrahn 	{
3070d2201f2fSdrahn 	  bfd_vma value;
3071d2201f2fSdrahn 
3072d2201f2fSdrahn 	  value = GET_WORD (abfd, p->e_value);
3073d2201f2fSdrahn 	  if (value != 0)
3074d2201f2fSdrahn 	    {
3075d2201f2fSdrahn 	      /* This symbol is common in the object from the archive
3076d2201f2fSdrahn 		 file.  */
3077d2201f2fSdrahn 	      if (h->type == bfd_link_hash_undefined)
3078d2201f2fSdrahn 		{
3079d2201f2fSdrahn 		  bfd *symbfd;
3080d2201f2fSdrahn 		  unsigned int power;
3081d2201f2fSdrahn 
3082d2201f2fSdrahn 		  symbfd = h->u.undef.abfd;
3083d2201f2fSdrahn 		  if (symbfd == (bfd *) NULL)
3084d2201f2fSdrahn 		    {
3085d2201f2fSdrahn 		      /* This symbol was created as undefined from
3086d2201f2fSdrahn 			 outside BFD.  We assume that we should link
3087d2201f2fSdrahn 			 in the object file.  This is done for the -u
3088d2201f2fSdrahn 			 option in the linker.  */
3089d2201f2fSdrahn 		      if (! (*info->callbacks->add_archive_element) (info,
3090d2201f2fSdrahn 								     abfd,
3091d2201f2fSdrahn 								     name))
3092d2201f2fSdrahn 			return FALSE;
3093d2201f2fSdrahn 		      *pneeded = TRUE;
3094d2201f2fSdrahn 		      return TRUE;
3095d2201f2fSdrahn 		    }
3096d2201f2fSdrahn 		  /* Turn the current link symbol into a common
3097d2201f2fSdrahn 		     symbol.  It is already on the undefs list.  */
3098d2201f2fSdrahn 		  h->type = bfd_link_hash_common;
3099d2201f2fSdrahn 		  h->u.c.p = ((struct bfd_link_hash_common_entry *)
3100d2201f2fSdrahn 			      bfd_hash_allocate (&info->hash->table,
3101d2201f2fSdrahn 				  sizeof (struct bfd_link_hash_common_entry)));
3102d2201f2fSdrahn 		  if (h->u.c.p == NULL)
3103d2201f2fSdrahn 		    return FALSE;
3104d2201f2fSdrahn 
3105d2201f2fSdrahn 		  h->u.c.size = value;
3106d2201f2fSdrahn 
3107d2201f2fSdrahn 		  /* FIXME: This isn't quite right.  The maximum
3108d2201f2fSdrahn 		     alignment of a common symbol should be set by the
3109d2201f2fSdrahn 		     architecture of the output file, not of the input
3110d2201f2fSdrahn 		     file.  */
3111d2201f2fSdrahn 		  power = bfd_log2 (value);
3112d2201f2fSdrahn 		  if (power > bfd_get_arch_info (abfd)->section_align_power)
3113d2201f2fSdrahn 		    power = bfd_get_arch_info (abfd)->section_align_power;
3114d2201f2fSdrahn 		  h->u.c.p->alignment_power = power;
3115d2201f2fSdrahn 
3116d2201f2fSdrahn 		  h->u.c.p->section = bfd_make_section_old_way (symbfd,
3117d2201f2fSdrahn 								"COMMON");
3118d2201f2fSdrahn 		}
3119d2201f2fSdrahn 	      else
3120d2201f2fSdrahn 		{
3121d2201f2fSdrahn 		  /* Adjust the size of the common symbol if
3122d2201f2fSdrahn 		     necessary.  */
3123d2201f2fSdrahn 		  if (value > h->u.c.size)
3124d2201f2fSdrahn 		    h->u.c.size = value;
3125d2201f2fSdrahn 		}
3126d2201f2fSdrahn 	    }
3127d2201f2fSdrahn 	}
3128d2201f2fSdrahn     }
3129d2201f2fSdrahn 
3130d2201f2fSdrahn   /* We do not need this object file.  */
3131d2201f2fSdrahn   return TRUE;
3132d2201f2fSdrahn }
3133d2201f2fSdrahn 
3134d2201f2fSdrahn /* Add all symbols from an object file to the hash table.  */
3135d2201f2fSdrahn 
3136d2201f2fSdrahn static bfd_boolean
aout_link_add_symbols(abfd,info)3137d2201f2fSdrahn aout_link_add_symbols (abfd, info)
3138d2201f2fSdrahn      bfd *abfd;
3139d2201f2fSdrahn      struct bfd_link_info *info;
3140d2201f2fSdrahn {
3141d2201f2fSdrahn   bfd_boolean (*add_one_symbol)
3142d2201f2fSdrahn     PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
3143d2201f2fSdrahn 	     bfd_vma, const char *, bfd_boolean, bfd_boolean,
3144d2201f2fSdrahn 	     struct bfd_link_hash_entry **));
3145d2201f2fSdrahn   struct external_nlist *syms;
3146d2201f2fSdrahn   bfd_size_type sym_count;
3147d2201f2fSdrahn   char *strings;
3148d2201f2fSdrahn   bfd_boolean copy;
3149d2201f2fSdrahn   struct aout_link_hash_entry **sym_hash;
3150d2201f2fSdrahn   register struct external_nlist *p;
3151d2201f2fSdrahn   struct external_nlist *pend;
3152d2201f2fSdrahn 
3153d2201f2fSdrahn   syms = obj_aout_external_syms (abfd);
3154d2201f2fSdrahn   sym_count = obj_aout_external_sym_count (abfd);
3155d2201f2fSdrahn   strings = obj_aout_external_strings (abfd);
3156d2201f2fSdrahn   if (info->keep_memory)
3157d2201f2fSdrahn     copy = FALSE;
3158d2201f2fSdrahn   else
3159d2201f2fSdrahn     copy = TRUE;
3160d2201f2fSdrahn 
3161d2201f2fSdrahn   if (aout_backend_info (abfd)->add_dynamic_symbols != NULL)
3162d2201f2fSdrahn     {
3163d2201f2fSdrahn       if (! ((*aout_backend_info (abfd)->add_dynamic_symbols)
3164d2201f2fSdrahn 	     (abfd, info, &syms, &sym_count, &strings)))
3165d2201f2fSdrahn 	return FALSE;
3166d2201f2fSdrahn     }
3167d2201f2fSdrahn 
3168d2201f2fSdrahn   /* We keep a list of the linker hash table entries that correspond
3169d2201f2fSdrahn      to particular symbols.  We could just look them up in the hash
3170d2201f2fSdrahn      table, but keeping the list is more efficient.  Perhaps this
3171d2201f2fSdrahn      should be conditional on info->keep_memory.  */
3172d2201f2fSdrahn   sym_hash = ((struct aout_link_hash_entry **)
3173d2201f2fSdrahn 	      bfd_alloc (abfd,
3174d2201f2fSdrahn 			 sym_count * sizeof (struct aout_link_hash_entry *)));
3175d2201f2fSdrahn   if (sym_hash == NULL && sym_count != 0)
3176d2201f2fSdrahn     return FALSE;
3177d2201f2fSdrahn   obj_aout_sym_hashes (abfd) = sym_hash;
3178d2201f2fSdrahn 
3179d2201f2fSdrahn   add_one_symbol = aout_backend_info (abfd)->add_one_symbol;
3180d2201f2fSdrahn   if (add_one_symbol == NULL)
3181d2201f2fSdrahn     add_one_symbol = _bfd_generic_link_add_one_symbol;
3182d2201f2fSdrahn 
3183d2201f2fSdrahn   p = syms;
3184d2201f2fSdrahn   pend = p + sym_count;
3185d2201f2fSdrahn   for (; p < pend; p++, sym_hash++)
3186d2201f2fSdrahn     {
3187d2201f2fSdrahn       int type;
3188d2201f2fSdrahn       const char *name;
3189d2201f2fSdrahn       bfd_vma value;
3190d2201f2fSdrahn       asection *section;
3191d2201f2fSdrahn       flagword flags;
3192d2201f2fSdrahn       const char *string;
3193d2201f2fSdrahn 
3194d2201f2fSdrahn       *sym_hash = NULL;
3195d2201f2fSdrahn 
3196d2201f2fSdrahn       type = H_GET_8 (abfd, p->e_type);
3197d2201f2fSdrahn 
3198d2201f2fSdrahn #if 0 /* not supported in PDP-11 a.out */
3199d2201f2fSdrahn       /* Ignore debugging symbols.  */
3200d2201f2fSdrahn       if ((type & N_STAB) != 0)
3201d2201f2fSdrahn 	continue;
3202d2201f2fSdrahn #endif
3203d2201f2fSdrahn 
3204d2201f2fSdrahn       name = strings + GET_WORD (abfd, p->e_strx);
3205d2201f2fSdrahn       value = GET_WORD (abfd, p->e_value);
3206d2201f2fSdrahn       flags = BSF_GLOBAL;
3207d2201f2fSdrahn       string = NULL;
3208d2201f2fSdrahn       switch (type)
3209d2201f2fSdrahn 	{
3210d2201f2fSdrahn 	default:
3211d2201f2fSdrahn 	  abort ();
3212d2201f2fSdrahn 
3213d2201f2fSdrahn 	case N_UNDF:
3214d2201f2fSdrahn 	case N_ABS:
3215d2201f2fSdrahn 	case N_TEXT:
3216d2201f2fSdrahn 	case N_DATA:
3217d2201f2fSdrahn 	case N_BSS:
3218d2201f2fSdrahn 	case N_REG:
3219d2201f2fSdrahn 	case N_FN:
3220d2201f2fSdrahn 	  /* Ignore symbols that are not externally visible.  */
3221d2201f2fSdrahn 	  continue;
3222d2201f2fSdrahn 
3223d2201f2fSdrahn 	case N_UNDF | N_EXT:
3224d2201f2fSdrahn 	  if (value == 0)
3225d2201f2fSdrahn 	    {
3226d2201f2fSdrahn 	      section = bfd_und_section_ptr;
3227d2201f2fSdrahn 	      flags = 0;
3228d2201f2fSdrahn 	    }
3229d2201f2fSdrahn 	  else
3230d2201f2fSdrahn 	    section = bfd_com_section_ptr;
3231d2201f2fSdrahn 	  break;
3232d2201f2fSdrahn 	case N_ABS | N_EXT:
3233d2201f2fSdrahn 	  section = bfd_abs_section_ptr;
3234d2201f2fSdrahn 	  break;
3235d2201f2fSdrahn 	case N_TEXT | N_EXT:
3236d2201f2fSdrahn 	  section = obj_textsec (abfd);
3237d2201f2fSdrahn 	  value -= bfd_get_section_vma (abfd, section);
3238d2201f2fSdrahn 	  break;
3239d2201f2fSdrahn 	case N_DATA | N_EXT:
3240d2201f2fSdrahn 	  /* Treat N_SETV symbols as N_DATA symbol; see comment in
3241d2201f2fSdrahn 	     translate_from_native_sym_flags.  */
3242d2201f2fSdrahn 	  section = obj_datasec (abfd);
3243d2201f2fSdrahn 	  value -= bfd_get_section_vma (abfd, section);
3244d2201f2fSdrahn 	  break;
3245d2201f2fSdrahn 	case N_BSS | N_EXT:
3246d2201f2fSdrahn 	  section = obj_bsssec (abfd);
3247d2201f2fSdrahn 	  value -= bfd_get_section_vma (abfd, section);
3248d2201f2fSdrahn 	  break;
3249d2201f2fSdrahn 	}
3250d2201f2fSdrahn 
3251d2201f2fSdrahn       if (! ((*add_one_symbol)
3252d2201f2fSdrahn 	     (info, abfd, name, flags, section, value, string, copy, FALSE,
3253d2201f2fSdrahn 	      (struct bfd_link_hash_entry **) sym_hash)))
3254d2201f2fSdrahn 	return FALSE;
3255d2201f2fSdrahn 
3256d2201f2fSdrahn       /* Restrict the maximum alignment of a common symbol based on
3257d2201f2fSdrahn 	 the architecture, since a.out has no way to represent
3258d2201f2fSdrahn 	 alignment requirements of a section in a .o file.  FIXME:
3259d2201f2fSdrahn 	 This isn't quite right: it should use the architecture of the
3260d2201f2fSdrahn 	 output file, not the input files.  */
3261d2201f2fSdrahn       if ((*sym_hash)->root.type == bfd_link_hash_common
3262d2201f2fSdrahn 	  && ((*sym_hash)->root.u.c.p->alignment_power >
3263d2201f2fSdrahn 	      bfd_get_arch_info (abfd)->section_align_power))
3264d2201f2fSdrahn 	(*sym_hash)->root.u.c.p->alignment_power =
3265d2201f2fSdrahn 	  bfd_get_arch_info (abfd)->section_align_power;
3266d2201f2fSdrahn 
3267d2201f2fSdrahn       /* If this is a set symbol, and we are not building sets, then
3268d2201f2fSdrahn 	 it is possible for the hash entry to not have been set.  In
3269d2201f2fSdrahn 	 such a case, treat the symbol as not globally defined.  */
3270d2201f2fSdrahn       if ((*sym_hash)->root.type == bfd_link_hash_new)
3271d2201f2fSdrahn 	{
3272d2201f2fSdrahn 	  BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0);
3273d2201f2fSdrahn 	  *sym_hash = NULL;
3274d2201f2fSdrahn 	}
3275d2201f2fSdrahn     }
3276d2201f2fSdrahn 
3277d2201f2fSdrahn   return TRUE;
3278d2201f2fSdrahn }
3279d2201f2fSdrahn 
3280d2201f2fSdrahn /* A hash table used for header files with N_BINCL entries.  */
3281d2201f2fSdrahn 
3282d2201f2fSdrahn struct aout_link_includes_table
3283d2201f2fSdrahn {
3284d2201f2fSdrahn   struct bfd_hash_table root;
3285d2201f2fSdrahn };
3286d2201f2fSdrahn 
3287d2201f2fSdrahn /* A linked list of totals that we have found for a particular header
3288d2201f2fSdrahn    file.  */
3289d2201f2fSdrahn 
3290d2201f2fSdrahn struct aout_link_includes_totals
3291d2201f2fSdrahn {
3292d2201f2fSdrahn   struct aout_link_includes_totals *next;
3293d2201f2fSdrahn   bfd_vma total;
3294d2201f2fSdrahn };
3295d2201f2fSdrahn 
3296d2201f2fSdrahn /* An entry in the header file hash table.  */
3297d2201f2fSdrahn 
3298d2201f2fSdrahn struct aout_link_includes_entry
3299d2201f2fSdrahn {
3300d2201f2fSdrahn   struct bfd_hash_entry root;
3301d2201f2fSdrahn   /* List of totals we have found for this file.  */
3302d2201f2fSdrahn   struct aout_link_includes_totals *totals;
3303d2201f2fSdrahn };
3304d2201f2fSdrahn 
3305d2201f2fSdrahn /* Look up an entry in an the header file hash table.  */
3306d2201f2fSdrahn 
3307d2201f2fSdrahn #define aout_link_includes_lookup(table, string, create, copy) \
3308d2201f2fSdrahn   ((struct aout_link_includes_entry *) \
3309d2201f2fSdrahn    bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
3310d2201f2fSdrahn 
3311d2201f2fSdrahn /* During the final link step we need to pass around a bunch of
3312d2201f2fSdrahn    information, so we do it in an instance of this structure.  */
3313d2201f2fSdrahn 
3314d2201f2fSdrahn struct aout_final_link_info
3315d2201f2fSdrahn {
3316d2201f2fSdrahn   /* General link information.  */
3317d2201f2fSdrahn   struct bfd_link_info *info;
3318d2201f2fSdrahn   /* Output bfd.  */
3319d2201f2fSdrahn   bfd *output_bfd;
3320d2201f2fSdrahn   /* Reloc file positions.  */
3321d2201f2fSdrahn   file_ptr treloff, dreloff;
3322d2201f2fSdrahn   /* File position of symbols.  */
3323d2201f2fSdrahn   file_ptr symoff;
3324d2201f2fSdrahn   /* String table.  */
3325d2201f2fSdrahn   struct bfd_strtab_hash *strtab;
3326d2201f2fSdrahn   /* Header file hash table.  */
3327d2201f2fSdrahn   struct aout_link_includes_table includes;
3328d2201f2fSdrahn   /* A buffer large enough to hold the contents of any section.  */
3329d2201f2fSdrahn   bfd_byte *contents;
3330d2201f2fSdrahn   /* A buffer large enough to hold the relocs of any section.  */
3331d2201f2fSdrahn   PTR relocs;
3332d2201f2fSdrahn   /* A buffer large enough to hold the symbol map of any input BFD.  */
3333d2201f2fSdrahn   int *symbol_map;
3334d2201f2fSdrahn   /* A buffer large enough to hold output symbols of any input BFD.  */
3335d2201f2fSdrahn   struct external_nlist *output_syms;
3336d2201f2fSdrahn };
3337d2201f2fSdrahn 
3338d2201f2fSdrahn static struct bfd_hash_entry *aout_link_includes_newfunc
3339d2201f2fSdrahn   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
3340d2201f2fSdrahn static bfd_boolean aout_link_input_bfd
3341d2201f2fSdrahn   PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
3342d2201f2fSdrahn static bfd_boolean aout_link_write_symbols
3343d2201f2fSdrahn   PARAMS ((struct aout_final_link_info *, bfd *input_bfd));
3344d2201f2fSdrahn static bfd_boolean aout_link_write_other_symbol
3345d2201f2fSdrahn   PARAMS ((struct aout_link_hash_entry *, PTR));
3346d2201f2fSdrahn static bfd_boolean aout_link_input_section
3347d2201f2fSdrahn   PARAMS ((struct aout_final_link_info *, bfd *input_bfd,
3348d2201f2fSdrahn 	   asection *input_section, file_ptr *reloff_ptr,
3349d2201f2fSdrahn 	   bfd_size_type rel_size));
3350d2201f2fSdrahn static INLINE asection *aout_reloc_type_to_section
3351d2201f2fSdrahn   PARAMS ((bfd *, int));
3352d2201f2fSdrahn static bfd_boolean aout_link_reloc_link_order
3353d2201f2fSdrahn   PARAMS ((struct aout_final_link_info *, asection *,
3354d2201f2fSdrahn 	   struct bfd_link_order *));
3355d2201f2fSdrahn static bfd_boolean pdp11_aout_link_input_section
3356d2201f2fSdrahn   PARAMS ((struct aout_final_link_info *finfo,
3357d2201f2fSdrahn 	   bfd *input_bfd,
3358d2201f2fSdrahn 	   asection *input_section,
3359d2201f2fSdrahn 	   struct pdp11_aout_reloc_external *relocs,
3360d2201f2fSdrahn 	   bfd_size_type rel_size,
3361d2201f2fSdrahn 	   bfd_byte *contents));
3362d2201f2fSdrahn 
3363d2201f2fSdrahn /* The function to create a new entry in the header file hash table.  */
3364d2201f2fSdrahn 
3365d2201f2fSdrahn static struct bfd_hash_entry *
aout_link_includes_newfunc(entry,table,string)3366d2201f2fSdrahn aout_link_includes_newfunc (entry, table, string)
3367d2201f2fSdrahn      struct bfd_hash_entry *entry;
3368d2201f2fSdrahn      struct bfd_hash_table *table;
3369d2201f2fSdrahn      const char *string;
3370d2201f2fSdrahn {
3371d2201f2fSdrahn   struct aout_link_includes_entry *ret =
3372d2201f2fSdrahn     (struct aout_link_includes_entry *) entry;
3373d2201f2fSdrahn 
3374d2201f2fSdrahn   /* Allocate the structure if it has not already been allocated by a
3375d2201f2fSdrahn      subclass.  */
3376d2201f2fSdrahn   if (ret == (struct aout_link_includes_entry *) NULL)
3377d2201f2fSdrahn     ret = ((struct aout_link_includes_entry *)
3378d2201f2fSdrahn 	   bfd_hash_allocate (table,
3379d2201f2fSdrahn 			      sizeof (struct aout_link_includes_entry)));
3380d2201f2fSdrahn   if (ret == (struct aout_link_includes_entry *) NULL)
3381d2201f2fSdrahn     return (struct bfd_hash_entry *) ret;
3382d2201f2fSdrahn 
3383d2201f2fSdrahn   /* Call the allocation method of the superclass.  */
3384d2201f2fSdrahn   ret = ((struct aout_link_includes_entry *)
3385d2201f2fSdrahn 	 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
3386d2201f2fSdrahn   if (ret)
3387d2201f2fSdrahn     {
3388d2201f2fSdrahn       /* Set local fields.  */
3389d2201f2fSdrahn       ret->totals = NULL;
3390d2201f2fSdrahn     }
3391d2201f2fSdrahn 
3392d2201f2fSdrahn   return (struct bfd_hash_entry *) ret;
3393d2201f2fSdrahn }
3394d2201f2fSdrahn 
3395d2201f2fSdrahn /* Do the final link step.  This is called on the output BFD.  The
3396d2201f2fSdrahn    INFO structure should point to a list of BFDs linked through the
3397d2201f2fSdrahn    link_next field which can be used to find each BFD which takes part
3398d2201f2fSdrahn    in the output.  Also, each section in ABFD should point to a list
3399d2201f2fSdrahn    of bfd_link_order structures which list all the input sections for
3400d2201f2fSdrahn    the output section.  */
3401d2201f2fSdrahn 
3402d2201f2fSdrahn bfd_boolean
3403d2201f2fSdrahn NAME(aout,final_link) (abfd, info, callback)
3404d2201f2fSdrahn      bfd *abfd;
3405d2201f2fSdrahn      struct bfd_link_info *info;
3406d2201f2fSdrahn      void (*callback) PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
3407d2201f2fSdrahn {
3408d2201f2fSdrahn   struct aout_final_link_info aout_info;
3409d2201f2fSdrahn   bfd_boolean includes_hash_initialized = FALSE;
3410d2201f2fSdrahn   register bfd *sub;
3411d2201f2fSdrahn   bfd_size_type trsize, drsize;
3412d2201f2fSdrahn   bfd_size_type max_contents_size;
3413d2201f2fSdrahn   bfd_size_type max_relocs_size;
3414d2201f2fSdrahn   bfd_size_type max_sym_count;
3415d2201f2fSdrahn   bfd_size_type text_size;
3416d2201f2fSdrahn   file_ptr text_end;
3417d2201f2fSdrahn   register struct bfd_link_order *p;
3418d2201f2fSdrahn   asection *o;
3419d2201f2fSdrahn   bfd_boolean have_link_order_relocs;
3420d2201f2fSdrahn 
3421d2201f2fSdrahn   if (info->shared)
3422d2201f2fSdrahn     abfd->flags |= DYNAMIC;
3423d2201f2fSdrahn 
3424d2201f2fSdrahn   aout_info.info = info;
3425d2201f2fSdrahn   aout_info.output_bfd = abfd;
3426d2201f2fSdrahn   aout_info.contents = NULL;
3427d2201f2fSdrahn   aout_info.relocs = NULL;
3428d2201f2fSdrahn   aout_info.symbol_map = NULL;
3429d2201f2fSdrahn   aout_info.output_syms = NULL;
3430d2201f2fSdrahn 
3431d2201f2fSdrahn   if (! bfd_hash_table_init_n (&aout_info.includes.root,
3432d2201f2fSdrahn 			       aout_link_includes_newfunc,
3433d2201f2fSdrahn 			       251))
3434d2201f2fSdrahn     goto error_return;
3435d2201f2fSdrahn   includes_hash_initialized = TRUE;
3436d2201f2fSdrahn 
3437d2201f2fSdrahn   /* Figure out the largest section size.  Also, if generating
3438*cf2f2c56Smiod      relocatable output, count the relocs.  */
3439d2201f2fSdrahn   trsize = 0;
3440d2201f2fSdrahn   drsize = 0;
3441d2201f2fSdrahn   max_contents_size = 0;
3442d2201f2fSdrahn   max_relocs_size = 0;
3443d2201f2fSdrahn   max_sym_count = 0;
3444d2201f2fSdrahn   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
3445d2201f2fSdrahn     {
3446d2201f2fSdrahn       size_t sz;
3447d2201f2fSdrahn 
3448*cf2f2c56Smiod       if (info->relocatable)
3449d2201f2fSdrahn 	{
3450d2201f2fSdrahn 	  if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
3451d2201f2fSdrahn 	    {
3452d2201f2fSdrahn 	      trsize += exec_hdr (sub)->a_trsize;
3453d2201f2fSdrahn 	      drsize += exec_hdr (sub)->a_drsize;
3454d2201f2fSdrahn 	    }
3455d2201f2fSdrahn 	  else
3456d2201f2fSdrahn 	    {
3457d2201f2fSdrahn 	      /* FIXME: We need to identify the .text and .data sections
3458d2201f2fSdrahn 		 and call get_reloc_upper_bound and canonicalize_reloc to
3459d2201f2fSdrahn 		 work out the number of relocs needed, and then multiply
3460d2201f2fSdrahn 		 by the reloc size.  */
3461d2201f2fSdrahn 	      (*_bfd_error_handler)
3462*cf2f2c56Smiod 		("%s: relocatable link from %s to %s not supported",
3463d2201f2fSdrahn 		 bfd_get_filename (abfd),
3464d2201f2fSdrahn 		 sub->xvec->name, abfd->xvec->name);
3465d2201f2fSdrahn 	      bfd_set_error (bfd_error_invalid_operation);
3466d2201f2fSdrahn 	      goto error_return;
3467d2201f2fSdrahn 	    }
3468d2201f2fSdrahn 	}
3469d2201f2fSdrahn 
3470d2201f2fSdrahn       if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
3471d2201f2fSdrahn 	{
3472d2201f2fSdrahn 	  sz = bfd_section_size (sub, obj_textsec (sub));
3473d2201f2fSdrahn 	  if (sz > max_contents_size)
3474d2201f2fSdrahn 	    max_contents_size = sz;
3475d2201f2fSdrahn 	  sz = bfd_section_size (sub, obj_datasec (sub));
3476d2201f2fSdrahn 	  if (sz > max_contents_size)
3477d2201f2fSdrahn 	    max_contents_size = sz;
3478d2201f2fSdrahn 
3479d2201f2fSdrahn 	  sz = exec_hdr (sub)->a_trsize;
3480d2201f2fSdrahn 	  if (sz > max_relocs_size)
3481d2201f2fSdrahn 	    max_relocs_size = sz;
3482d2201f2fSdrahn 	  sz = exec_hdr (sub)->a_drsize;
3483d2201f2fSdrahn 	  if (sz > max_relocs_size)
3484d2201f2fSdrahn 	    max_relocs_size = sz;
3485d2201f2fSdrahn 
3486d2201f2fSdrahn 	  sz = obj_aout_external_sym_count (sub);
3487d2201f2fSdrahn 	  if (sz > max_sym_count)
3488d2201f2fSdrahn 	    max_sym_count = sz;
3489d2201f2fSdrahn 	}
3490d2201f2fSdrahn     }
3491d2201f2fSdrahn 
3492*cf2f2c56Smiod   if (info->relocatable)
3493d2201f2fSdrahn     {
3494d2201f2fSdrahn       if (obj_textsec (abfd) != (asection *) NULL)
3495d2201f2fSdrahn 	trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
3496d2201f2fSdrahn 						 ->link_order_head)
3497d2201f2fSdrahn 		   * obj_reloc_entry_size (abfd));
3498d2201f2fSdrahn       if (obj_datasec (abfd) != (asection *) NULL)
3499d2201f2fSdrahn 	drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
3500d2201f2fSdrahn 						 ->link_order_head)
3501d2201f2fSdrahn 		   * obj_reloc_entry_size (abfd));
3502d2201f2fSdrahn     }
3503d2201f2fSdrahn 
3504d2201f2fSdrahn   exec_hdr (abfd)->a_trsize = trsize;
3505d2201f2fSdrahn   exec_hdr (abfd)->a_drsize = drsize;
3506d2201f2fSdrahn 
3507d2201f2fSdrahn   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
3508d2201f2fSdrahn 
3509d2201f2fSdrahn   /* Adjust the section sizes and vmas according to the magic number.
3510d2201f2fSdrahn      This sets a_text, a_data and a_bss in the exec_hdr and sets the
3511d2201f2fSdrahn      filepos for each section.  */
3512d2201f2fSdrahn   if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
3513d2201f2fSdrahn     goto error_return;
3514d2201f2fSdrahn 
3515d2201f2fSdrahn   /* The relocation and symbol file positions differ among a.out
3516d2201f2fSdrahn      targets.  We are passed a callback routine from the backend
3517d2201f2fSdrahn      specific code to handle this.
3518d2201f2fSdrahn      FIXME: At this point we do not know how much space the symbol
3519d2201f2fSdrahn      table will require.  This will not work for any (nonstandard)
3520d2201f2fSdrahn      a.out target that needs to know the symbol table size before it
3521d2201f2fSdrahn      can compute the relocation file positions.  This may or may not
3522d2201f2fSdrahn      be the case for the hp300hpux target, for example.  */
3523d2201f2fSdrahn   (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff,
3524d2201f2fSdrahn 	       &aout_info.symoff);
3525d2201f2fSdrahn   obj_textsec (abfd)->rel_filepos = aout_info.treloff;
3526d2201f2fSdrahn   obj_datasec (abfd)->rel_filepos = aout_info.dreloff;
3527d2201f2fSdrahn   obj_sym_filepos (abfd) = aout_info.symoff;
3528d2201f2fSdrahn 
3529d2201f2fSdrahn   /* We keep a count of the symbols as we output them.  */
3530d2201f2fSdrahn   obj_aout_external_sym_count (abfd) = 0;
3531d2201f2fSdrahn 
3532d2201f2fSdrahn   /* We accumulate the string table as we write out the symbols.  */
3533d2201f2fSdrahn   aout_info.strtab = _bfd_stringtab_init ();
3534d2201f2fSdrahn   if (aout_info.strtab == NULL)
3535d2201f2fSdrahn     goto error_return;
3536d2201f2fSdrahn 
3537d2201f2fSdrahn   /* Allocate buffers to hold section contents and relocs.  */
3538d2201f2fSdrahn   aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size);
3539d2201f2fSdrahn   aout_info.relocs = (PTR) bfd_malloc (max_relocs_size);
3540d2201f2fSdrahn   aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int *));
3541d2201f2fSdrahn   aout_info.output_syms = ((struct external_nlist *)
3542d2201f2fSdrahn 			   bfd_malloc ((max_sym_count + 1)
3543d2201f2fSdrahn 				       * sizeof (struct external_nlist)));
3544d2201f2fSdrahn   if ((aout_info.contents == NULL && max_contents_size != 0)
3545d2201f2fSdrahn       || (aout_info.relocs == NULL && max_relocs_size != 0)
3546d2201f2fSdrahn       || (aout_info.symbol_map == NULL && max_sym_count != 0)
3547d2201f2fSdrahn       || aout_info.output_syms == NULL)
3548d2201f2fSdrahn     goto error_return;
3549d2201f2fSdrahn 
3550d2201f2fSdrahn   /* If we have a symbol named __DYNAMIC, force it out now.  This is
3551d2201f2fSdrahn      required by SunOS.  Doing this here rather than in sunos.c is a
3552d2201f2fSdrahn      hack, but it's easier than exporting everything which would be
3553d2201f2fSdrahn      needed.  */
3554d2201f2fSdrahn   {
3555d2201f2fSdrahn     struct aout_link_hash_entry *h;
3556d2201f2fSdrahn 
3557d2201f2fSdrahn     h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
3558d2201f2fSdrahn 			       FALSE, FALSE, FALSE);
3559d2201f2fSdrahn     if (h != NULL)
3560d2201f2fSdrahn       aout_link_write_other_symbol (h, &aout_info);
3561d2201f2fSdrahn   }
3562d2201f2fSdrahn 
3563d2201f2fSdrahn   /* The most time efficient way to do the link would be to read all
3564d2201f2fSdrahn      the input object files into memory and then sort out the
3565d2201f2fSdrahn      information into the output file.  Unfortunately, that will
3566d2201f2fSdrahn      probably use too much memory.  Another method would be to step
3567d2201f2fSdrahn      through everything that composes the text section and write it
3568d2201f2fSdrahn      out, and then everything that composes the data section and write
3569d2201f2fSdrahn      it out, and then write out the relocs, and then write out the
3570d2201f2fSdrahn      symbols.  Unfortunately, that requires reading stuff from each
3571d2201f2fSdrahn      input file several times, and we will not be able to keep all the
3572d2201f2fSdrahn      input files open simultaneously, and reopening them will be slow.
3573d2201f2fSdrahn 
3574d2201f2fSdrahn      What we do is basically process one input file at a time.  We do
3575d2201f2fSdrahn      everything we need to do with an input file once--copy over the
3576d2201f2fSdrahn      section contents, handle the relocation information, and write
3577d2201f2fSdrahn      out the symbols--and then we throw away the information we read
3578d2201f2fSdrahn      from it.  This approach requires a lot of lseeks of the output
3579d2201f2fSdrahn      file, which is unfortunate but still faster than reopening a lot
3580d2201f2fSdrahn      of files.
3581d2201f2fSdrahn 
3582d2201f2fSdrahn      We use the output_has_begun field of the input BFDs to see
3583d2201f2fSdrahn      whether we have already handled it.  */
3584d2201f2fSdrahn   for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
3585d2201f2fSdrahn     sub->output_has_begun = FALSE;
3586d2201f2fSdrahn 
3587d2201f2fSdrahn   /* Mark all sections which are to be included in the link.  This
3588d2201f2fSdrahn      will normally be every section.  We need to do this so that we
3589d2201f2fSdrahn      can identify any sections which the linker has decided to not
3590d2201f2fSdrahn      include.  */
3591d2201f2fSdrahn   for (o = abfd->sections; o != NULL; o = o->next)
3592d2201f2fSdrahn     {
3593d2201f2fSdrahn       for (p = o->link_order_head; p != NULL; p = p->next)
3594d2201f2fSdrahn 	{
3595d2201f2fSdrahn 	  if (p->type == bfd_indirect_link_order)
3596d2201f2fSdrahn 	    p->u.indirect.section->linker_mark = TRUE;
3597d2201f2fSdrahn 	}
3598d2201f2fSdrahn     }
3599d2201f2fSdrahn 
3600d2201f2fSdrahn   have_link_order_relocs = FALSE;
3601d2201f2fSdrahn   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
3602d2201f2fSdrahn     {
3603d2201f2fSdrahn       for (p = o->link_order_head;
3604d2201f2fSdrahn 	   p != (struct bfd_link_order *) NULL;
3605d2201f2fSdrahn 	   p = p->next)
3606d2201f2fSdrahn 	{
3607d2201f2fSdrahn 	  if (p->type == bfd_indirect_link_order
3608d2201f2fSdrahn 	      && (bfd_get_flavour (p->u.indirect.section->owner)
3609d2201f2fSdrahn 		  == bfd_target_aout_flavour))
3610d2201f2fSdrahn 	    {
3611d2201f2fSdrahn 	      bfd *input_bfd;
3612d2201f2fSdrahn 
3613d2201f2fSdrahn 	      input_bfd = p->u.indirect.section->owner;
3614d2201f2fSdrahn 	      if (! input_bfd->output_has_begun)
3615d2201f2fSdrahn 		{
3616d2201f2fSdrahn 		  if (! aout_link_input_bfd (&aout_info, input_bfd))
3617d2201f2fSdrahn 		    goto error_return;
3618d2201f2fSdrahn 		  input_bfd->output_has_begun = TRUE;
3619d2201f2fSdrahn 		}
3620d2201f2fSdrahn 	    }
3621d2201f2fSdrahn 	  else if (p->type == bfd_section_reloc_link_order
3622d2201f2fSdrahn 		   || p->type == bfd_symbol_reloc_link_order)
3623d2201f2fSdrahn 	    {
3624d2201f2fSdrahn 	      /* These are handled below.  */
3625d2201f2fSdrahn 	      have_link_order_relocs = TRUE;
3626d2201f2fSdrahn 	    }
3627d2201f2fSdrahn 	  else
3628d2201f2fSdrahn 	    {
3629d2201f2fSdrahn 	      if (! _bfd_default_link_order (abfd, info, o, p))
3630d2201f2fSdrahn 		goto error_return;
3631d2201f2fSdrahn 	    }
3632d2201f2fSdrahn 	}
3633d2201f2fSdrahn     }
3634d2201f2fSdrahn 
3635d2201f2fSdrahn   /* Write out any symbols that we have not already written out.  */
3636d2201f2fSdrahn   aout_link_hash_traverse (aout_hash_table (info),
3637d2201f2fSdrahn 			   aout_link_write_other_symbol,
3638d2201f2fSdrahn 			   (PTR) &aout_info);
3639d2201f2fSdrahn 
3640d2201f2fSdrahn   /* Now handle any relocs we were asked to create by the linker.
3641d2201f2fSdrahn      These did not come from any input file.  We must do these after
3642d2201f2fSdrahn      we have written out all the symbols, so that we know the symbol
3643d2201f2fSdrahn      indices to use.  */
3644d2201f2fSdrahn   if (have_link_order_relocs)
3645d2201f2fSdrahn     {
3646d2201f2fSdrahn       for (o = abfd->sections; o != (asection *) NULL; o = o->next)
3647d2201f2fSdrahn 	{
3648d2201f2fSdrahn 	  for (p = o->link_order_head;
3649d2201f2fSdrahn 	       p != (struct bfd_link_order *) NULL;
3650d2201f2fSdrahn 	       p = p->next)
3651d2201f2fSdrahn 	    {
3652d2201f2fSdrahn 	      if (p->type == bfd_section_reloc_link_order
3653d2201f2fSdrahn 		  || p->type == bfd_symbol_reloc_link_order)
3654d2201f2fSdrahn 		{
3655d2201f2fSdrahn 		  if (! aout_link_reloc_link_order (&aout_info, o, p))
3656d2201f2fSdrahn 		    goto error_return;
3657d2201f2fSdrahn 		}
3658d2201f2fSdrahn 	    }
3659d2201f2fSdrahn 	}
3660d2201f2fSdrahn     }
3661d2201f2fSdrahn 
3662d2201f2fSdrahn   if (aout_info.contents != NULL)
3663d2201f2fSdrahn     {
3664d2201f2fSdrahn       free (aout_info.contents);
3665d2201f2fSdrahn       aout_info.contents = NULL;
3666d2201f2fSdrahn     }
3667d2201f2fSdrahn   if (aout_info.relocs != NULL)
3668d2201f2fSdrahn     {
3669d2201f2fSdrahn       free (aout_info.relocs);
3670d2201f2fSdrahn       aout_info.relocs = NULL;
3671d2201f2fSdrahn     }
3672d2201f2fSdrahn   if (aout_info.symbol_map != NULL)
3673d2201f2fSdrahn     {
3674d2201f2fSdrahn       free (aout_info.symbol_map);
3675d2201f2fSdrahn       aout_info.symbol_map = NULL;
3676d2201f2fSdrahn     }
3677d2201f2fSdrahn   if (aout_info.output_syms != NULL)
3678d2201f2fSdrahn     {
3679d2201f2fSdrahn       free (aout_info.output_syms);
3680d2201f2fSdrahn       aout_info.output_syms = NULL;
3681d2201f2fSdrahn     }
3682d2201f2fSdrahn   if (includes_hash_initialized)
3683d2201f2fSdrahn     {
3684d2201f2fSdrahn       bfd_hash_table_free (&aout_info.includes.root);
3685d2201f2fSdrahn       includes_hash_initialized = FALSE;
3686d2201f2fSdrahn     }
3687d2201f2fSdrahn 
3688d2201f2fSdrahn   /* Finish up any dynamic linking we may be doing.  */
3689d2201f2fSdrahn   if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
3690d2201f2fSdrahn     {
3691d2201f2fSdrahn       if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
3692d2201f2fSdrahn 	goto error_return;
3693d2201f2fSdrahn     }
3694d2201f2fSdrahn 
3695d2201f2fSdrahn   /* Update the header information.  */
3696d2201f2fSdrahn   abfd->symcount = obj_aout_external_sym_count (abfd);
3697d2201f2fSdrahn   exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE;
3698d2201f2fSdrahn   obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms;
3699d2201f2fSdrahn   obj_textsec (abfd)->reloc_count =
3700d2201f2fSdrahn     exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
3701d2201f2fSdrahn   obj_datasec (abfd)->reloc_count =
3702d2201f2fSdrahn     exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
3703d2201f2fSdrahn 
3704d2201f2fSdrahn   /* Write out the string table, unless there are no symbols.  */
3705d2201f2fSdrahn   if (abfd->symcount > 0)
3706d2201f2fSdrahn     {
3707d2201f2fSdrahn       if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
3708d2201f2fSdrahn 	  || ! emit_stringtab (abfd, aout_info.strtab))
3709d2201f2fSdrahn 	goto error_return;
3710d2201f2fSdrahn     }
3711d2201f2fSdrahn   else if (obj_textsec (abfd)->reloc_count == 0
3712d2201f2fSdrahn 	   && obj_datasec (abfd)->reloc_count == 0)
3713d2201f2fSdrahn     {
3714d2201f2fSdrahn       bfd_byte b;
3715d2201f2fSdrahn 
3716d2201f2fSdrahn       b = 0;
3717d2201f2fSdrahn       if (bfd_seek (abfd,
3718d2201f2fSdrahn 		    (file_ptr) (obj_datasec (abfd)->filepos
3719d2201f2fSdrahn 				+ exec_hdr (abfd)->a_data
3720d2201f2fSdrahn 				- 1),
3721d2201f2fSdrahn 		    SEEK_SET) != 0
3722d2201f2fSdrahn 	  || bfd_bwrite (&b, (bfd_size_type) 1, abfd) != 1)
3723d2201f2fSdrahn 	goto error_return;
3724d2201f2fSdrahn     }
3725d2201f2fSdrahn 
3726d2201f2fSdrahn   return TRUE;
3727d2201f2fSdrahn 
3728d2201f2fSdrahn  error_return:
3729d2201f2fSdrahn   if (aout_info.contents != NULL)
3730d2201f2fSdrahn     free (aout_info.contents);
3731d2201f2fSdrahn   if (aout_info.relocs != NULL)
3732d2201f2fSdrahn     free (aout_info.relocs);
3733d2201f2fSdrahn   if (aout_info.symbol_map != NULL)
3734d2201f2fSdrahn     free (aout_info.symbol_map);
3735d2201f2fSdrahn   if (aout_info.output_syms != NULL)
3736d2201f2fSdrahn     free (aout_info.output_syms);
3737d2201f2fSdrahn   if (includes_hash_initialized)
3738d2201f2fSdrahn     bfd_hash_table_free (&aout_info.includes.root);
3739d2201f2fSdrahn   return FALSE;
3740d2201f2fSdrahn }
3741d2201f2fSdrahn 
3742d2201f2fSdrahn /* Link an a.out input BFD into the output file.  */
3743d2201f2fSdrahn 
3744d2201f2fSdrahn static bfd_boolean
aout_link_input_bfd(finfo,input_bfd)3745d2201f2fSdrahn aout_link_input_bfd (finfo, input_bfd)
3746d2201f2fSdrahn      struct aout_final_link_info *finfo;
3747d2201f2fSdrahn      bfd *input_bfd;
3748d2201f2fSdrahn {
3749d2201f2fSdrahn   bfd_size_type sym_count;
3750d2201f2fSdrahn 
3751d2201f2fSdrahn   BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
3752d2201f2fSdrahn 
3753d2201f2fSdrahn   /* If this is a dynamic object, it may need special handling.  */
3754d2201f2fSdrahn   if ((input_bfd->flags & DYNAMIC) != 0
3755d2201f2fSdrahn       && aout_backend_info (input_bfd)->link_dynamic_object != NULL)
3756d2201f2fSdrahn     {
3757d2201f2fSdrahn       return ((*aout_backend_info (input_bfd)->link_dynamic_object)
3758d2201f2fSdrahn 	      (finfo->info, input_bfd));
3759d2201f2fSdrahn     }
3760d2201f2fSdrahn 
3761d2201f2fSdrahn   /* Get the symbols.  We probably have them already, unless
3762d2201f2fSdrahn      finfo->info->keep_memory is FALSE.  */
3763d2201f2fSdrahn   if (! aout_get_external_symbols (input_bfd))
3764d2201f2fSdrahn     return FALSE;
3765d2201f2fSdrahn 
3766d2201f2fSdrahn   sym_count = obj_aout_external_sym_count (input_bfd);
3767d2201f2fSdrahn 
3768d2201f2fSdrahn   /* Write out the symbols and get a map of the new indices.  The map
3769d2201f2fSdrahn      is placed into finfo->symbol_map.  */
3770d2201f2fSdrahn   if (! aout_link_write_symbols (finfo, input_bfd))
3771d2201f2fSdrahn     return FALSE;
3772d2201f2fSdrahn 
3773d2201f2fSdrahn   /* Relocate and write out the sections.  These functions use the
3774d2201f2fSdrahn      symbol map created by aout_link_write_symbols.  The linker_mark
3775d2201f2fSdrahn      field will be set if these sections are to be included in the
3776d2201f2fSdrahn      link, which will normally be the case.  */
3777d2201f2fSdrahn   if (obj_textsec (input_bfd)->linker_mark)
3778d2201f2fSdrahn     {
3779d2201f2fSdrahn       if (! aout_link_input_section (finfo, input_bfd,
3780d2201f2fSdrahn 				     obj_textsec (input_bfd),
3781d2201f2fSdrahn 				     &finfo->treloff,
3782d2201f2fSdrahn 				     exec_hdr (input_bfd)->a_trsize))
3783d2201f2fSdrahn 	return FALSE;
3784d2201f2fSdrahn     }
3785d2201f2fSdrahn   if (obj_datasec (input_bfd)->linker_mark)
3786d2201f2fSdrahn     {
3787d2201f2fSdrahn       if (! aout_link_input_section (finfo, input_bfd,
3788d2201f2fSdrahn 				     obj_datasec (input_bfd),
3789d2201f2fSdrahn 				     &finfo->dreloff,
3790d2201f2fSdrahn 				     exec_hdr (input_bfd)->a_drsize))
3791d2201f2fSdrahn 	return FALSE;
3792d2201f2fSdrahn     }
3793d2201f2fSdrahn 
3794d2201f2fSdrahn   /* If we are not keeping memory, we don't need the symbols any
3795d2201f2fSdrahn      longer.  We still need them if we are keeping memory, because the
3796d2201f2fSdrahn      strings in the hash table point into them.  */
3797d2201f2fSdrahn   if (! finfo->info->keep_memory)
3798d2201f2fSdrahn     {
3799d2201f2fSdrahn       if (! aout_link_free_symbols (input_bfd))
3800d2201f2fSdrahn 	return FALSE;
3801d2201f2fSdrahn     }
3802d2201f2fSdrahn 
3803d2201f2fSdrahn   return TRUE;
3804d2201f2fSdrahn }
3805d2201f2fSdrahn 
3806d2201f2fSdrahn /* Adjust and write out the symbols for an a.out file.  Set the new
3807d2201f2fSdrahn    symbol indices into a symbol_map.  */
3808d2201f2fSdrahn 
3809d2201f2fSdrahn static bfd_boolean
aout_link_write_symbols(finfo,input_bfd)3810d2201f2fSdrahn aout_link_write_symbols (finfo, input_bfd)
3811d2201f2fSdrahn      struct aout_final_link_info *finfo;
3812d2201f2fSdrahn      bfd *input_bfd;
3813d2201f2fSdrahn {
3814d2201f2fSdrahn   bfd *output_bfd;
3815d2201f2fSdrahn   bfd_size_type sym_count;
3816d2201f2fSdrahn   char *strings;
3817d2201f2fSdrahn   enum bfd_link_strip strip;
3818d2201f2fSdrahn   enum bfd_link_discard discard;
3819d2201f2fSdrahn   struct external_nlist *outsym;
3820d2201f2fSdrahn   bfd_size_type strtab_index;
3821d2201f2fSdrahn   register struct external_nlist *sym;
3822d2201f2fSdrahn   struct external_nlist *sym_end;
3823d2201f2fSdrahn   struct aout_link_hash_entry **sym_hash;
3824d2201f2fSdrahn   int *symbol_map;
3825d2201f2fSdrahn   bfd_boolean pass;
3826d2201f2fSdrahn   bfd_boolean skip_next;
3827d2201f2fSdrahn 
3828d2201f2fSdrahn   output_bfd = finfo->output_bfd;
3829d2201f2fSdrahn   sym_count = obj_aout_external_sym_count (input_bfd);
3830d2201f2fSdrahn   strings = obj_aout_external_strings (input_bfd);
3831d2201f2fSdrahn   strip = finfo->info->strip;
3832d2201f2fSdrahn   discard = finfo->info->discard;
3833d2201f2fSdrahn   outsym = finfo->output_syms;
3834d2201f2fSdrahn 
3835d2201f2fSdrahn   /* First write out a symbol for this object file, unless we are
3836d2201f2fSdrahn      discarding such symbols.  */
3837d2201f2fSdrahn   if (strip != strip_all
3838d2201f2fSdrahn       && (strip != strip_some
3839d2201f2fSdrahn 	  || bfd_hash_lookup (finfo->info->keep_hash, input_bfd->filename,
3840d2201f2fSdrahn 			      FALSE, FALSE) != NULL)
3841d2201f2fSdrahn       && discard != discard_all)
3842d2201f2fSdrahn     {
3843d2201f2fSdrahn       H_PUT_8 (output_bfd, N_TEXT, outsym->e_type);
3844d2201f2fSdrahn       strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
3845d2201f2fSdrahn 				       input_bfd->filename, FALSE);
3846d2201f2fSdrahn       if (strtab_index == (bfd_size_type) -1)
3847d2201f2fSdrahn 	return FALSE;
3848d2201f2fSdrahn       PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
3849d2201f2fSdrahn       PUT_WORD (output_bfd,
3850d2201f2fSdrahn 		(bfd_get_section_vma (output_bfd,
3851d2201f2fSdrahn 				      obj_textsec (input_bfd)->output_section)
3852d2201f2fSdrahn 		 + obj_textsec (input_bfd)->output_offset),
3853d2201f2fSdrahn 		outsym->e_value);
3854d2201f2fSdrahn       ++obj_aout_external_sym_count (output_bfd);
3855d2201f2fSdrahn       ++outsym;
3856d2201f2fSdrahn     }
3857d2201f2fSdrahn 
3858d2201f2fSdrahn   pass = FALSE;
3859d2201f2fSdrahn   skip_next = FALSE;
3860d2201f2fSdrahn   sym = obj_aout_external_syms (input_bfd);
3861d2201f2fSdrahn   sym_end = sym + sym_count;
3862d2201f2fSdrahn   sym_hash = obj_aout_sym_hashes (input_bfd);
3863d2201f2fSdrahn   symbol_map = finfo->symbol_map;
3864d2201f2fSdrahn   memset (symbol_map, 0, (size_t) sym_count * sizeof *symbol_map);
3865d2201f2fSdrahn   for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
3866d2201f2fSdrahn     {
3867d2201f2fSdrahn       const char *name;
3868d2201f2fSdrahn       int type;
3869d2201f2fSdrahn       struct aout_link_hash_entry *h;
3870d2201f2fSdrahn       bfd_boolean skip;
3871d2201f2fSdrahn       asection *symsec;
3872d2201f2fSdrahn       bfd_vma val = 0;
3873d2201f2fSdrahn       bfd_boolean copy;
3874d2201f2fSdrahn 
3875d2201f2fSdrahn       /* We set *symbol_map to 0 above for all symbols.  If it has
3876d2201f2fSdrahn          already been set to -1 for this symbol, it means that we are
3877d2201f2fSdrahn          discarding it because it appears in a duplicate header file.
3878d2201f2fSdrahn          See the N_BINCL code below.  */
3879d2201f2fSdrahn       if (*symbol_map == -1)
3880d2201f2fSdrahn 	continue;
3881d2201f2fSdrahn 
3882d2201f2fSdrahn       /* Initialize *symbol_map to -1, which means that the symbol was
3883d2201f2fSdrahn          not copied into the output file.  We will change it later if
3884d2201f2fSdrahn          we do copy the symbol over.  */
3885d2201f2fSdrahn       *symbol_map = -1;
3886d2201f2fSdrahn 
3887d2201f2fSdrahn       type = H_GET_8 (input_bfd, sym->e_type);
3888d2201f2fSdrahn       name = strings + GET_WORD (input_bfd, sym->e_strx);
3889d2201f2fSdrahn 
3890d2201f2fSdrahn       h = NULL;
3891d2201f2fSdrahn 
3892d2201f2fSdrahn       if (pass)
3893d2201f2fSdrahn 	{
3894d2201f2fSdrahn 	  /* Pass this symbol through.  It is the target of an
3895d2201f2fSdrahn 	     indirect or warning symbol.  */
3896d2201f2fSdrahn 	  val = GET_WORD (input_bfd, sym->e_value);
3897d2201f2fSdrahn 	  pass = FALSE;
3898d2201f2fSdrahn 	}
3899d2201f2fSdrahn       else if (skip_next)
3900d2201f2fSdrahn 	{
3901d2201f2fSdrahn 	  /* Skip this symbol, which is the target of an indirect
3902d2201f2fSdrahn 	     symbol that we have changed to no longer be an indirect
3903d2201f2fSdrahn 	     symbol.  */
3904d2201f2fSdrahn 	  skip_next = FALSE;
3905d2201f2fSdrahn 	  continue;
3906d2201f2fSdrahn 	}
3907d2201f2fSdrahn       else
3908d2201f2fSdrahn 	{
3909d2201f2fSdrahn 	  struct aout_link_hash_entry *hresolve;
3910d2201f2fSdrahn 
3911d2201f2fSdrahn 	  /* We have saved the hash table entry for this symbol, if
3912d2201f2fSdrahn 	     there is one.  Note that we could just look it up again
3913d2201f2fSdrahn 	     in the hash table, provided we first check that it is an
3914d2201f2fSdrahn 	     external symbol. */
3915d2201f2fSdrahn 	  h = *sym_hash;
3916d2201f2fSdrahn 
3917d2201f2fSdrahn 	  /* Use the name from the hash table, in case the symbol was
3918d2201f2fSdrahn              wrapped.  */
3919d2201f2fSdrahn 	  if (h != NULL)
3920d2201f2fSdrahn 	    name = h->root.root.string;
3921d2201f2fSdrahn 
3922d2201f2fSdrahn 	  /* If this is an indirect or warning symbol, then change
3923d2201f2fSdrahn 	     hresolve to the base symbol.  We also change *sym_hash so
3924d2201f2fSdrahn 	     that the relocation routines relocate against the real
3925d2201f2fSdrahn 	     symbol.  */
3926d2201f2fSdrahn 	  hresolve = h;
3927d2201f2fSdrahn 	  if (h != (struct aout_link_hash_entry *) NULL
3928d2201f2fSdrahn 	      && (h->root.type == bfd_link_hash_indirect
3929d2201f2fSdrahn 		  || h->root.type == bfd_link_hash_warning))
3930d2201f2fSdrahn 	    {
3931d2201f2fSdrahn 	      hresolve = (struct aout_link_hash_entry *) h->root.u.i.link;
3932d2201f2fSdrahn 	      while (hresolve->root.type == bfd_link_hash_indirect
3933d2201f2fSdrahn 		     || hresolve->root.type == bfd_link_hash_warning)
3934d2201f2fSdrahn 		hresolve = ((struct aout_link_hash_entry *)
3935d2201f2fSdrahn 			    hresolve->root.u.i.link);
3936d2201f2fSdrahn 	      *sym_hash = hresolve;
3937d2201f2fSdrahn 	    }
3938d2201f2fSdrahn 
3939d2201f2fSdrahn 	  /* If the symbol has already been written out, skip it.  */
3940d2201f2fSdrahn 	  if (h != (struct aout_link_hash_entry *) NULL
3941d2201f2fSdrahn 	      && h->root.type != bfd_link_hash_warning
3942d2201f2fSdrahn 	      && h->written)
3943d2201f2fSdrahn 	    {
3944d2201f2fSdrahn 	      if ((type & N_TYPE) == N_INDR
3945d2201f2fSdrahn 		  || type == N_WARNING)
3946d2201f2fSdrahn 		skip_next = TRUE;
3947d2201f2fSdrahn 	      *symbol_map = h->indx;
3948d2201f2fSdrahn 	      continue;
3949d2201f2fSdrahn 	    }
3950d2201f2fSdrahn 
3951d2201f2fSdrahn 	  /* See if we are stripping this symbol.  */
3952d2201f2fSdrahn 	  skip = FALSE;
3953d2201f2fSdrahn 	  switch (strip)
3954d2201f2fSdrahn 	    {
3955d2201f2fSdrahn 	    case strip_none:
3956d2201f2fSdrahn 	      break;
3957d2201f2fSdrahn 	    case strip_debugger:
3958d2201f2fSdrahn 	      if ((type & N_STAB) != 0)
3959d2201f2fSdrahn 		skip = TRUE;
3960d2201f2fSdrahn 	      break;
3961d2201f2fSdrahn 	    case strip_some:
3962d2201f2fSdrahn 	      if (bfd_hash_lookup (finfo->info->keep_hash, name, FALSE, FALSE)
3963d2201f2fSdrahn 		  == NULL)
3964d2201f2fSdrahn 		skip = TRUE;
3965d2201f2fSdrahn 	      break;
3966d2201f2fSdrahn 	    case strip_all:
3967d2201f2fSdrahn 	      skip = TRUE;
3968d2201f2fSdrahn 	      break;
3969d2201f2fSdrahn 	    }
3970d2201f2fSdrahn 	  if (skip)
3971d2201f2fSdrahn 	    {
3972d2201f2fSdrahn 	      if (h != (struct aout_link_hash_entry *) NULL)
3973d2201f2fSdrahn 		h->written = TRUE;
3974d2201f2fSdrahn 	      continue;
3975d2201f2fSdrahn 	    }
3976d2201f2fSdrahn 
3977d2201f2fSdrahn 	  /* Get the value of the symbol.  */
3978d2201f2fSdrahn 	  if ((type & N_TYPE) == N_TEXT
3979d2201f2fSdrahn 	      || type == N_WEAKT)
3980d2201f2fSdrahn 	    symsec = obj_textsec (input_bfd);
3981d2201f2fSdrahn 	  else if ((type & N_TYPE) == N_DATA
3982d2201f2fSdrahn 		   || type == N_WEAKD)
3983d2201f2fSdrahn 	    symsec = obj_datasec (input_bfd);
3984d2201f2fSdrahn 	  else if ((type & N_TYPE) == N_BSS
3985d2201f2fSdrahn 		   || type == N_WEAKB)
3986d2201f2fSdrahn 	    symsec = obj_bsssec (input_bfd);
3987d2201f2fSdrahn 	  else if ((type & N_TYPE) == N_ABS
3988d2201f2fSdrahn 		   || type == N_WEAKA)
3989d2201f2fSdrahn 	    symsec = bfd_abs_section_ptr;
3990d2201f2fSdrahn 	  else if (((type & N_TYPE) == N_INDR
3991d2201f2fSdrahn 		    && (hresolve == (struct aout_link_hash_entry *) NULL
3992d2201f2fSdrahn 			|| (hresolve->root.type != bfd_link_hash_defined
3993d2201f2fSdrahn 			    && hresolve->root.type != bfd_link_hash_defweak
3994d2201f2fSdrahn 			    && hresolve->root.type != bfd_link_hash_common)))
3995d2201f2fSdrahn 		   || type == N_WARNING)
3996d2201f2fSdrahn 	    {
3997d2201f2fSdrahn 	      /* Pass the next symbol through unchanged.  The
3998d2201f2fSdrahn 		 condition above for indirect symbols is so that if
3999d2201f2fSdrahn 		 the indirect symbol was defined, we output it with
4000d2201f2fSdrahn 		 the correct definition so the debugger will
4001d2201f2fSdrahn 		 understand it.  */
4002d2201f2fSdrahn 	      pass = TRUE;
4003d2201f2fSdrahn 	      val = GET_WORD (input_bfd, sym->e_value);
4004d2201f2fSdrahn 	      symsec = NULL;
4005d2201f2fSdrahn 	    }
4006d2201f2fSdrahn 	  else if ((type & N_STAB) != 0)
4007d2201f2fSdrahn 	    {
4008d2201f2fSdrahn 	      val = GET_WORD (input_bfd, sym->e_value);
4009d2201f2fSdrahn 	      symsec = NULL;
4010d2201f2fSdrahn 	    }
4011d2201f2fSdrahn 	  else
4012d2201f2fSdrahn 	    {
4013d2201f2fSdrahn 	      /* If we get here with an indirect symbol, it means that
4014d2201f2fSdrahn 		 we are outputting it with a real definition.  In such
4015d2201f2fSdrahn 		 a case we do not want to output the next symbol,
4016d2201f2fSdrahn 		 which is the target of the indirection.  */
4017d2201f2fSdrahn 	      if ((type & N_TYPE) == N_INDR)
4018d2201f2fSdrahn 		skip_next = TRUE;
4019d2201f2fSdrahn 
4020d2201f2fSdrahn 	      symsec = NULL;
4021d2201f2fSdrahn 
4022d2201f2fSdrahn 	      /* We need to get the value from the hash table.  We use
4023d2201f2fSdrahn 		 hresolve so that if we have defined an indirect
4024d2201f2fSdrahn 		 symbol we output the final definition.  */
4025d2201f2fSdrahn 	      if (h == (struct aout_link_hash_entry *) NULL)
4026d2201f2fSdrahn 		{
4027d2201f2fSdrahn 		  switch (type & N_TYPE)
4028d2201f2fSdrahn 		    {
4029d2201f2fSdrahn 		    case N_SETT:
4030d2201f2fSdrahn 		      symsec = obj_textsec (input_bfd);
4031d2201f2fSdrahn 		      break;
4032d2201f2fSdrahn 		    case N_SETD:
4033d2201f2fSdrahn 		      symsec = obj_datasec (input_bfd);
4034d2201f2fSdrahn 		      break;
4035d2201f2fSdrahn 		    case N_SETB:
4036d2201f2fSdrahn 		      symsec = obj_bsssec (input_bfd);
4037d2201f2fSdrahn 		      break;
4038d2201f2fSdrahn 		    case N_SETA:
4039d2201f2fSdrahn 		      symsec = bfd_abs_section_ptr;
4040d2201f2fSdrahn 		      break;
4041d2201f2fSdrahn 		    default:
4042d2201f2fSdrahn 		      val = 0;
4043d2201f2fSdrahn 		      break;
4044d2201f2fSdrahn 		    }
4045d2201f2fSdrahn 		}
4046d2201f2fSdrahn 	      else if (hresolve->root.type == bfd_link_hash_defined
4047d2201f2fSdrahn 		       || hresolve->root.type == bfd_link_hash_defweak)
4048d2201f2fSdrahn 		{
4049d2201f2fSdrahn 		  asection *input_section;
4050d2201f2fSdrahn 		  asection *output_section;
4051d2201f2fSdrahn 
4052d2201f2fSdrahn 		  /* This case usually means a common symbol which was
4053d2201f2fSdrahn 		     turned into a defined symbol.  */
4054d2201f2fSdrahn 		  input_section = hresolve->root.u.def.section;
4055d2201f2fSdrahn 		  output_section = input_section->output_section;
4056d2201f2fSdrahn 		  BFD_ASSERT (bfd_is_abs_section (output_section)
4057d2201f2fSdrahn 			      || output_section->owner == output_bfd);
4058d2201f2fSdrahn 		  val = (hresolve->root.u.def.value
4059d2201f2fSdrahn 			 + bfd_get_section_vma (output_bfd, output_section)
4060d2201f2fSdrahn 			 + input_section->output_offset);
4061d2201f2fSdrahn 
4062d2201f2fSdrahn 		  /* Get the correct type based on the section.  If
4063d2201f2fSdrahn 		     this is a constructed set, force it to be
4064d2201f2fSdrahn 		     globally visible.  */
4065d2201f2fSdrahn 		  if (type == N_SETT
4066d2201f2fSdrahn 		      || type == N_SETD
4067d2201f2fSdrahn 		      || type == N_SETB
4068d2201f2fSdrahn 		      || type == N_SETA)
4069d2201f2fSdrahn 		    type |= N_EXT;
4070d2201f2fSdrahn 
4071d2201f2fSdrahn 		  type &=~ N_TYPE;
4072d2201f2fSdrahn 
4073d2201f2fSdrahn 		  if (output_section == obj_textsec (output_bfd))
4074d2201f2fSdrahn 		    type |= (hresolve->root.type == bfd_link_hash_defined
4075d2201f2fSdrahn 			     ? N_TEXT
4076d2201f2fSdrahn 			     : N_WEAKT);
4077d2201f2fSdrahn 		  else if (output_section == obj_datasec (output_bfd))
4078d2201f2fSdrahn 		    type |= (hresolve->root.type == bfd_link_hash_defined
4079d2201f2fSdrahn 			     ? N_DATA
4080d2201f2fSdrahn 			     : N_WEAKD);
4081d2201f2fSdrahn 		  else if (output_section == obj_bsssec (output_bfd))
4082d2201f2fSdrahn 		    type |= (hresolve->root.type == bfd_link_hash_defined
4083d2201f2fSdrahn 			     ? N_BSS
4084d2201f2fSdrahn 			     : N_WEAKB);
4085d2201f2fSdrahn 		  else
4086d2201f2fSdrahn 		    type |= (hresolve->root.type == bfd_link_hash_defined
4087d2201f2fSdrahn 			     ? N_ABS
4088d2201f2fSdrahn 			     : N_WEAKA);
4089d2201f2fSdrahn 		}
4090d2201f2fSdrahn 	      else if (hresolve->root.type == bfd_link_hash_common)
4091d2201f2fSdrahn 		val = hresolve->root.u.c.size;
4092d2201f2fSdrahn 	      else if (hresolve->root.type == bfd_link_hash_undefweak)
4093d2201f2fSdrahn 		{
4094d2201f2fSdrahn 		  val = 0;
4095d2201f2fSdrahn 		  type = N_WEAKU;
4096d2201f2fSdrahn 		}
4097d2201f2fSdrahn 	      else
4098d2201f2fSdrahn 		val = 0;
4099d2201f2fSdrahn 	    }
4100d2201f2fSdrahn 	  if (symsec != (asection *) NULL)
4101d2201f2fSdrahn 	    val = (symsec->output_section->vma
4102d2201f2fSdrahn 		   + symsec->output_offset
4103d2201f2fSdrahn 		   + (GET_WORD (input_bfd, sym->e_value)
4104d2201f2fSdrahn 		      - symsec->vma));
4105d2201f2fSdrahn 
4106d2201f2fSdrahn 	  /* If this is a global symbol set the written flag, and if
4107d2201f2fSdrahn 	     it is a local symbol see if we should discard it.  */
4108d2201f2fSdrahn 	  if (h != (struct aout_link_hash_entry *) NULL)
4109d2201f2fSdrahn 	    {
4110d2201f2fSdrahn 	      h->written = TRUE;
4111d2201f2fSdrahn 	      h->indx = obj_aout_external_sym_count (output_bfd);
4112d2201f2fSdrahn 	    }
4113d2201f2fSdrahn 	  else if ((type & N_TYPE) != N_SETT
4114d2201f2fSdrahn 		   && (type & N_TYPE) != N_SETD
4115d2201f2fSdrahn 		   && (type & N_TYPE) != N_SETB
4116d2201f2fSdrahn 		   && (type & N_TYPE) != N_SETA)
4117d2201f2fSdrahn 	    {
4118d2201f2fSdrahn 	      switch (discard)
4119d2201f2fSdrahn 		{
4120d2201f2fSdrahn 		case discard_none:
4121d2201f2fSdrahn 		case discard_sec_merge:
4122d2201f2fSdrahn 		  break;
4123d2201f2fSdrahn 		case discard_l:
4124d2201f2fSdrahn 		  if ((type & N_STAB) == 0
4125d2201f2fSdrahn 		      && bfd_is_local_label_name (input_bfd, name))
4126d2201f2fSdrahn 		    skip = TRUE;
4127d2201f2fSdrahn 		  break;
4128d2201f2fSdrahn 		case discard_all:
4129d2201f2fSdrahn 		  skip = TRUE;
4130d2201f2fSdrahn 		  break;
4131d2201f2fSdrahn 		}
4132d2201f2fSdrahn 	      if (skip)
4133d2201f2fSdrahn 		{
4134d2201f2fSdrahn 		  pass = FALSE;
4135d2201f2fSdrahn 		  continue;
4136d2201f2fSdrahn 		}
4137d2201f2fSdrahn 	    }
4138d2201f2fSdrahn 
4139d2201f2fSdrahn 	  /* An N_BINCL symbol indicates the start of the stabs
4140d2201f2fSdrahn 	     entries for a header file.  We need to scan ahead to the
4141d2201f2fSdrahn 	     next N_EINCL symbol, ignoring nesting, adding up all the
4142d2201f2fSdrahn 	     characters in the symbol names, not including the file
4143d2201f2fSdrahn 	     numbers in types (the first number after an open
4144d2201f2fSdrahn 	     parenthesis).  */
4145d2201f2fSdrahn 	  if (type == N_BINCL)
4146d2201f2fSdrahn 	    {
4147d2201f2fSdrahn 	      struct external_nlist *incl_sym;
4148d2201f2fSdrahn 	      int nest;
4149d2201f2fSdrahn 	      struct aout_link_includes_entry *incl_entry;
4150d2201f2fSdrahn 	      struct aout_link_includes_totals *t;
4151d2201f2fSdrahn 
4152d2201f2fSdrahn 	      val = 0;
4153d2201f2fSdrahn 	      nest = 0;
4154d2201f2fSdrahn 	      for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
4155d2201f2fSdrahn 		{
4156d2201f2fSdrahn 		  int incl_type;
4157d2201f2fSdrahn 
4158d2201f2fSdrahn 		  incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
4159d2201f2fSdrahn 		  if (incl_type == N_EINCL)
4160d2201f2fSdrahn 		    {
4161d2201f2fSdrahn 		      if (nest == 0)
4162d2201f2fSdrahn 			break;
4163d2201f2fSdrahn 		      --nest;
4164d2201f2fSdrahn 		    }
4165d2201f2fSdrahn 		  else if (incl_type == N_BINCL)
4166d2201f2fSdrahn 		    ++nest;
4167d2201f2fSdrahn 		  else if (nest == 0)
4168d2201f2fSdrahn 		    {
4169d2201f2fSdrahn 		      const char *s;
4170d2201f2fSdrahn 
4171d2201f2fSdrahn 		      s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
4172d2201f2fSdrahn 		      for (; *s != '\0'; s++)
4173d2201f2fSdrahn 			{
4174d2201f2fSdrahn 			  val += *s;
4175d2201f2fSdrahn 			  if (*s == '(')
4176d2201f2fSdrahn 			    {
4177d2201f2fSdrahn 			      /* Skip the file number.  */
4178d2201f2fSdrahn 			      ++s;
4179d2201f2fSdrahn 			      while (ISDIGIT (*s))
4180d2201f2fSdrahn 				++s;
4181d2201f2fSdrahn 			      --s;
4182d2201f2fSdrahn 			    }
4183d2201f2fSdrahn 			}
4184d2201f2fSdrahn 		    }
4185d2201f2fSdrahn 		}
4186d2201f2fSdrahn 
4187d2201f2fSdrahn 	      /* If we have already included a header file with the
4188d2201f2fSdrahn                  same value, then replace this one with an N_EXCL
4189d2201f2fSdrahn                  symbol.  */
4190d2201f2fSdrahn 	      copy = ! finfo->info->keep_memory;
4191d2201f2fSdrahn 	      incl_entry = aout_link_includes_lookup (&finfo->includes,
4192d2201f2fSdrahn 						      name, TRUE, copy);
4193d2201f2fSdrahn 	      if (incl_entry == NULL)
4194d2201f2fSdrahn 		return FALSE;
4195d2201f2fSdrahn 	      for (t = incl_entry->totals; t != NULL; t = t->next)
4196d2201f2fSdrahn 		if (t->total == val)
4197d2201f2fSdrahn 		  break;
4198d2201f2fSdrahn 	      if (t == NULL)
4199d2201f2fSdrahn 		{
4200d2201f2fSdrahn 		  /* This is the first time we have seen this header
4201d2201f2fSdrahn                      file with this set of stabs strings.  */
4202d2201f2fSdrahn 		  t = ((struct aout_link_includes_totals *)
4203d2201f2fSdrahn 		       bfd_hash_allocate (&finfo->includes.root,
4204d2201f2fSdrahn 					  sizeof *t));
4205d2201f2fSdrahn 		  if (t == NULL)
4206d2201f2fSdrahn 		    return FALSE;
4207d2201f2fSdrahn 		  t->total = val;
4208d2201f2fSdrahn 		  t->next = incl_entry->totals;
4209d2201f2fSdrahn 		  incl_entry->totals = t;
4210d2201f2fSdrahn 		}
4211d2201f2fSdrahn 	      else
4212d2201f2fSdrahn 		{
4213d2201f2fSdrahn 		  int *incl_map;
4214d2201f2fSdrahn 
4215d2201f2fSdrahn 		  /* This is a duplicate header file.  We must change
4216d2201f2fSdrahn                      it to be an N_EXCL entry, and mark all the
4217d2201f2fSdrahn                      included symbols to prevent outputting them.  */
4218d2201f2fSdrahn 		  type = N_EXCL;
4219d2201f2fSdrahn 
4220d2201f2fSdrahn 		  nest = 0;
4221d2201f2fSdrahn 		  for (incl_sym = sym + 1, incl_map = symbol_map + 1;
4222d2201f2fSdrahn 		       incl_sym < sym_end;
4223d2201f2fSdrahn 		       incl_sym++, incl_map++)
4224d2201f2fSdrahn 		    {
4225d2201f2fSdrahn 		      int incl_type;
4226d2201f2fSdrahn 
4227d2201f2fSdrahn 		      incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
4228d2201f2fSdrahn 		      if (incl_type == N_EINCL)
4229d2201f2fSdrahn 			{
4230d2201f2fSdrahn 			  if (nest == 0)
4231d2201f2fSdrahn 			    {
4232d2201f2fSdrahn 			      *incl_map = -1;
4233d2201f2fSdrahn 			      break;
4234d2201f2fSdrahn 			    }
4235d2201f2fSdrahn 			  --nest;
4236d2201f2fSdrahn 			}
4237d2201f2fSdrahn 		      else if (incl_type == N_BINCL)
4238d2201f2fSdrahn 			++nest;
4239d2201f2fSdrahn 		      else if (nest == 0)
4240d2201f2fSdrahn 			*incl_map = -1;
4241d2201f2fSdrahn 		    }
4242d2201f2fSdrahn 		}
4243d2201f2fSdrahn 	    }
4244d2201f2fSdrahn 	}
4245d2201f2fSdrahn 
4246d2201f2fSdrahn       /* Copy this symbol into the list of symbols we are going to
4247d2201f2fSdrahn 	 write out.  */
4248d2201f2fSdrahn       H_PUT_8 (output_bfd, type, outsym->e_type);
4249d2201f2fSdrahn       copy = FALSE;
4250d2201f2fSdrahn       if (! finfo->info->keep_memory)
4251d2201f2fSdrahn 	{
4252d2201f2fSdrahn 	  /* name points into a string table which we are going to
4253d2201f2fSdrahn 	     free.  If there is a hash table entry, use that string.
4254d2201f2fSdrahn 	     Otherwise, copy name into memory.  */
4255d2201f2fSdrahn 	  if (h != (struct aout_link_hash_entry *) NULL)
4256d2201f2fSdrahn 	    name = h->root.root.string;
4257d2201f2fSdrahn 	  else
4258d2201f2fSdrahn 	    copy = TRUE;
4259d2201f2fSdrahn 	}
4260d2201f2fSdrahn       strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
4261d2201f2fSdrahn 				       name, copy);
4262d2201f2fSdrahn       if (strtab_index == (bfd_size_type) -1)
4263d2201f2fSdrahn 	return FALSE;
4264d2201f2fSdrahn       PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
4265d2201f2fSdrahn       PUT_WORD (output_bfd, val, outsym->e_value);
4266d2201f2fSdrahn       *symbol_map = obj_aout_external_sym_count (output_bfd);
4267d2201f2fSdrahn       ++obj_aout_external_sym_count (output_bfd);
4268d2201f2fSdrahn       ++outsym;
4269d2201f2fSdrahn     }
4270d2201f2fSdrahn 
4271d2201f2fSdrahn   /* Write out the output symbols we have just constructed.  */
4272d2201f2fSdrahn   if (outsym > finfo->output_syms)
4273d2201f2fSdrahn     {
4274d2201f2fSdrahn       bfd_size_type size;
4275d2201f2fSdrahn 
4276d2201f2fSdrahn       if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
4277d2201f2fSdrahn 	return FALSE;
4278d2201f2fSdrahn       size = outsym - finfo->output_syms;
4279d2201f2fSdrahn       size *= EXTERNAL_NLIST_SIZE;
4280d2201f2fSdrahn       if (bfd_bwrite ((PTR) finfo->output_syms, size, output_bfd) != size)
4281d2201f2fSdrahn 	return FALSE;
4282d2201f2fSdrahn       finfo->symoff += size;
4283d2201f2fSdrahn     }
4284d2201f2fSdrahn 
4285d2201f2fSdrahn   return TRUE;
4286d2201f2fSdrahn }
4287d2201f2fSdrahn 
4288d2201f2fSdrahn /* Write out a symbol that was not associated with an a.out input
4289d2201f2fSdrahn    object.  */
4290d2201f2fSdrahn 
4291d2201f2fSdrahn static bfd_boolean
aout_link_write_other_symbol(h,data)4292d2201f2fSdrahn aout_link_write_other_symbol (h, data)
4293d2201f2fSdrahn      struct aout_link_hash_entry *h;
4294d2201f2fSdrahn      PTR data;
4295d2201f2fSdrahn {
4296d2201f2fSdrahn   struct aout_final_link_info *finfo = (struct aout_final_link_info *) data;
4297d2201f2fSdrahn   bfd *output_bfd;
4298d2201f2fSdrahn   int type;
4299d2201f2fSdrahn   bfd_vma val;
4300d2201f2fSdrahn   struct external_nlist outsym;
4301d2201f2fSdrahn   bfd_size_type indx;
4302d2201f2fSdrahn   bfd_size_type amt;
4303d2201f2fSdrahn 
4304d2201f2fSdrahn   if (h->root.type == bfd_link_hash_warning)
4305d2201f2fSdrahn     {
4306d2201f2fSdrahn       h = (struct aout_link_hash_entry *) h->root.u.i.link;
4307d2201f2fSdrahn       if (h->root.type == bfd_link_hash_new)
4308d2201f2fSdrahn 	return TRUE;
4309d2201f2fSdrahn     }
4310d2201f2fSdrahn 
4311d2201f2fSdrahn   output_bfd = finfo->output_bfd;
4312d2201f2fSdrahn 
4313d2201f2fSdrahn   if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
4314d2201f2fSdrahn     {
4315d2201f2fSdrahn       if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
4316d2201f2fSdrahn 	     (output_bfd, finfo->info, h)))
4317d2201f2fSdrahn 	{
4318d2201f2fSdrahn 	  /* FIXME: No way to handle errors.  */
4319d2201f2fSdrahn 	  abort ();
4320d2201f2fSdrahn 	}
4321d2201f2fSdrahn     }
4322d2201f2fSdrahn 
4323d2201f2fSdrahn   if (h->written)
4324d2201f2fSdrahn     return TRUE;
4325d2201f2fSdrahn 
4326d2201f2fSdrahn   h->written = TRUE;
4327d2201f2fSdrahn 
4328d2201f2fSdrahn   /* An indx of -2 means the symbol must be written.  */
4329d2201f2fSdrahn   if (h->indx != -2
4330d2201f2fSdrahn       && (finfo->info->strip == strip_all
4331d2201f2fSdrahn 	  || (finfo->info->strip == strip_some
4332d2201f2fSdrahn 	      && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string,
4333d2201f2fSdrahn 				  FALSE, FALSE) == NULL)))
4334d2201f2fSdrahn     return TRUE;
4335d2201f2fSdrahn 
4336d2201f2fSdrahn   switch (h->root.type)
4337d2201f2fSdrahn     {
4338d2201f2fSdrahn     default:
4339d2201f2fSdrahn       abort ();
4340d2201f2fSdrahn       /* Avoid variable not initialized warnings.  */
4341d2201f2fSdrahn       return TRUE;
4342d2201f2fSdrahn     case bfd_link_hash_new:
4343d2201f2fSdrahn       /* This can happen for set symbols when sets are not being
4344d2201f2fSdrahn          built.  */
4345d2201f2fSdrahn       return TRUE;
4346d2201f2fSdrahn     case bfd_link_hash_undefined:
4347d2201f2fSdrahn       type = N_UNDF | N_EXT;
4348d2201f2fSdrahn       val = 0;
4349d2201f2fSdrahn       break;
4350d2201f2fSdrahn     case bfd_link_hash_defined:
4351d2201f2fSdrahn     case bfd_link_hash_defweak:
4352d2201f2fSdrahn       {
4353d2201f2fSdrahn 	asection *sec;
4354d2201f2fSdrahn 
4355d2201f2fSdrahn 	sec = h->root.u.def.section->output_section;
4356d2201f2fSdrahn 	BFD_ASSERT (bfd_is_abs_section (sec)
4357d2201f2fSdrahn 		    || sec->owner == output_bfd);
4358d2201f2fSdrahn 	if (sec == obj_textsec (output_bfd))
4359d2201f2fSdrahn 	  type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
4360d2201f2fSdrahn 	else if (sec == obj_datasec (output_bfd))
4361d2201f2fSdrahn 	  type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
4362d2201f2fSdrahn 	else if (sec == obj_bsssec (output_bfd))
4363d2201f2fSdrahn 	  type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
4364d2201f2fSdrahn 	else
4365d2201f2fSdrahn 	  type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
4366d2201f2fSdrahn 	type |= N_EXT;
4367d2201f2fSdrahn 	val = (h->root.u.def.value
4368d2201f2fSdrahn 	       + sec->vma
4369d2201f2fSdrahn 	       + h->root.u.def.section->output_offset);
4370d2201f2fSdrahn       }
4371d2201f2fSdrahn       break;
4372d2201f2fSdrahn     case bfd_link_hash_common:
4373d2201f2fSdrahn       type = N_UNDF | N_EXT;
4374d2201f2fSdrahn       val = h->root.u.c.size;
4375d2201f2fSdrahn       break;
4376d2201f2fSdrahn     case bfd_link_hash_undefweak:
4377d2201f2fSdrahn       type = N_WEAKU;
4378d2201f2fSdrahn       val = 0;
4379d2201f2fSdrahn     case bfd_link_hash_indirect:
4380d2201f2fSdrahn     case bfd_link_hash_warning:
4381d2201f2fSdrahn       /* FIXME: Ignore these for now.  The circumstances under which
4382d2201f2fSdrahn 	 they should be written out are not clear to me.  */
4383d2201f2fSdrahn       return TRUE;
4384d2201f2fSdrahn     }
4385d2201f2fSdrahn 
4386d2201f2fSdrahn   H_PUT_8 (output_bfd, type, outsym.e_type);
4387d2201f2fSdrahn   indx = add_to_stringtab (output_bfd, finfo->strtab, h->root.root.string,
4388d2201f2fSdrahn 			   FALSE);
4389d2201f2fSdrahn   if (indx == (bfd_size_type) -1)
4390d2201f2fSdrahn     {
4391d2201f2fSdrahn       /* FIXME: No way to handle errors.  */
4392d2201f2fSdrahn       abort ();
4393d2201f2fSdrahn     }
4394d2201f2fSdrahn   PUT_WORD (output_bfd, indx, outsym.e_strx);
4395d2201f2fSdrahn   PUT_WORD (output_bfd, val, outsym.e_value);
4396d2201f2fSdrahn 
4397d2201f2fSdrahn   amt = EXTERNAL_NLIST_SIZE;
4398d2201f2fSdrahn   if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0
4399d2201f2fSdrahn       || bfd_bwrite ((PTR) &outsym, amt, output_bfd) != amt)
4400d2201f2fSdrahn     {
4401d2201f2fSdrahn       /* FIXME: No way to handle errors.  */
4402d2201f2fSdrahn       abort ();
4403d2201f2fSdrahn     }
4404d2201f2fSdrahn 
4405d2201f2fSdrahn   finfo->symoff += amt;
4406d2201f2fSdrahn   h->indx = obj_aout_external_sym_count (output_bfd);
4407d2201f2fSdrahn   ++obj_aout_external_sym_count (output_bfd);
4408d2201f2fSdrahn 
4409d2201f2fSdrahn   return TRUE;
4410d2201f2fSdrahn }
4411d2201f2fSdrahn 
4412d2201f2fSdrahn /* Link an a.out section into the output file.  */
4413d2201f2fSdrahn 
4414d2201f2fSdrahn static bfd_boolean
aout_link_input_section(finfo,input_bfd,input_section,reloff_ptr,rel_size)4415d2201f2fSdrahn aout_link_input_section (finfo, input_bfd, input_section, reloff_ptr,
4416d2201f2fSdrahn 			 rel_size)
4417d2201f2fSdrahn      struct aout_final_link_info *finfo;
4418d2201f2fSdrahn      bfd *input_bfd;
4419d2201f2fSdrahn      asection *input_section;
4420d2201f2fSdrahn      file_ptr *reloff_ptr;
4421d2201f2fSdrahn      bfd_size_type rel_size;
4422d2201f2fSdrahn {
4423d2201f2fSdrahn   bfd_size_type input_size;
4424d2201f2fSdrahn   PTR relocs;
4425d2201f2fSdrahn 
4426d2201f2fSdrahn   /* Get the section contents.  */
4427d2201f2fSdrahn   input_size = bfd_section_size (input_bfd, input_section);
4428d2201f2fSdrahn   if (! bfd_get_section_contents (input_bfd, input_section,
4429d2201f2fSdrahn 				  (PTR) finfo->contents,
4430d2201f2fSdrahn 				  (file_ptr) 0, input_size))
4431d2201f2fSdrahn     return FALSE;
4432d2201f2fSdrahn 
4433d2201f2fSdrahn   /* Read in the relocs if we haven't already done it.  */
4434d2201f2fSdrahn   if (aout_section_data (input_section) != NULL
4435d2201f2fSdrahn       && aout_section_data (input_section)->relocs != NULL)
4436d2201f2fSdrahn     relocs = aout_section_data (input_section)->relocs;
4437d2201f2fSdrahn   else
4438d2201f2fSdrahn     {
4439d2201f2fSdrahn       relocs = finfo->relocs;
4440d2201f2fSdrahn       if (rel_size > 0)
4441d2201f2fSdrahn 	{
4442d2201f2fSdrahn 	  if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
4443d2201f2fSdrahn 	      || bfd_bread (relocs, rel_size, input_bfd) != rel_size)
4444d2201f2fSdrahn 	    return FALSE;
4445d2201f2fSdrahn 	}
4446d2201f2fSdrahn     }
4447d2201f2fSdrahn 
4448d2201f2fSdrahn   /* Relocate the section contents.  */
4449d2201f2fSdrahn   if (! pdp11_aout_link_input_section (finfo, input_bfd, input_section,
4450d2201f2fSdrahn 				       (struct pdp11_aout_reloc_external *) relocs,
4451d2201f2fSdrahn 				       rel_size, finfo->contents))
4452d2201f2fSdrahn     return FALSE;
4453d2201f2fSdrahn 
4454d2201f2fSdrahn   /* Write out the section contents.  */
4455d2201f2fSdrahn   if (! bfd_set_section_contents (finfo->output_bfd,
4456d2201f2fSdrahn 				  input_section->output_section,
4457d2201f2fSdrahn 				  (PTR) finfo->contents,
4458d2201f2fSdrahn 				  (file_ptr) input_section->output_offset,
4459d2201f2fSdrahn 				  input_size))
4460d2201f2fSdrahn     return FALSE;
4461d2201f2fSdrahn 
4462*cf2f2c56Smiod   /* If we are producing relocatable output, the relocs were
4463d2201f2fSdrahn      modified, and we now write them out.  */
4464*cf2f2c56Smiod   if (finfo->info->relocatable && rel_size > 0)
4465d2201f2fSdrahn     {
4466d2201f2fSdrahn       if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
4467d2201f2fSdrahn 	return FALSE;
4468d2201f2fSdrahn       if (bfd_bwrite (relocs, rel_size, finfo->output_bfd) != rel_size)
4469d2201f2fSdrahn 	return FALSE;
4470d2201f2fSdrahn       *reloff_ptr += rel_size;
4471d2201f2fSdrahn 
4472d2201f2fSdrahn       /* Assert that the relocs have not run into the symbols, and
4473d2201f2fSdrahn 	 that if these are the text relocs they have not run into the
4474d2201f2fSdrahn 	 data relocs.  */
4475d2201f2fSdrahn       BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
4476d2201f2fSdrahn 		  && (reloff_ptr != &finfo->treloff
4477d2201f2fSdrahn 		      || (*reloff_ptr
4478d2201f2fSdrahn 			  <= obj_datasec (finfo->output_bfd)->rel_filepos)));
4479d2201f2fSdrahn     }
4480d2201f2fSdrahn 
4481d2201f2fSdrahn   return TRUE;
4482d2201f2fSdrahn }
4483d2201f2fSdrahn 
4484d2201f2fSdrahn /* Get the section corresponding to a reloc index.  */
4485d2201f2fSdrahn 
4486d2201f2fSdrahn static INLINE asection *
aout_reloc_type_to_section(abfd,type)4487d2201f2fSdrahn aout_reloc_type_to_section (abfd, type)
4488d2201f2fSdrahn      bfd *abfd;
4489d2201f2fSdrahn      int type;
4490d2201f2fSdrahn {
4491d2201f2fSdrahn   switch (type)
4492d2201f2fSdrahn     {
4493d2201f2fSdrahn     case RTEXT:
4494d2201f2fSdrahn       return obj_textsec (abfd);
4495d2201f2fSdrahn     case RDATA:
4496d2201f2fSdrahn       return obj_datasec (abfd);
4497d2201f2fSdrahn     case RBSS:
4498d2201f2fSdrahn       return obj_bsssec (abfd);
4499d2201f2fSdrahn     case RABS:
4500d2201f2fSdrahn       return bfd_abs_section_ptr;
4501d2201f2fSdrahn     case REXT:
4502d2201f2fSdrahn       return bfd_und_section_ptr;
4503d2201f2fSdrahn     default:
4504d2201f2fSdrahn       abort ();
4505d2201f2fSdrahn     }
4506d2201f2fSdrahn }
4507d2201f2fSdrahn 
4508d2201f2fSdrahn static bfd_boolean
pdp11_aout_link_input_section(finfo,input_bfd,input_section,relocs,rel_size,contents)4509d2201f2fSdrahn pdp11_aout_link_input_section (finfo, input_bfd, input_section, relocs,
4510d2201f2fSdrahn 			       rel_size, contents)
4511d2201f2fSdrahn      struct aout_final_link_info *finfo;
4512d2201f2fSdrahn      bfd *input_bfd;
4513d2201f2fSdrahn      asection *input_section;
4514d2201f2fSdrahn      struct pdp11_aout_reloc_external *relocs;
4515d2201f2fSdrahn      bfd_size_type rel_size;
4516d2201f2fSdrahn      bfd_byte *contents;
4517d2201f2fSdrahn {
4518d2201f2fSdrahn   bfd_boolean (*check_dynamic_reloc)
4519d2201f2fSdrahn     PARAMS ((struct bfd_link_info *, bfd *, asection *,
4520d2201f2fSdrahn 	     struct aout_link_hash_entry *, PTR, bfd_byte *, bfd_boolean *,
4521d2201f2fSdrahn 	     bfd_vma *));
4522d2201f2fSdrahn   bfd *output_bfd;
4523*cf2f2c56Smiod   bfd_boolean relocatable;
4524d2201f2fSdrahn   struct external_nlist *syms;
4525d2201f2fSdrahn   char *strings;
4526d2201f2fSdrahn   struct aout_link_hash_entry **sym_hashes;
4527d2201f2fSdrahn   int *symbol_map;
4528d2201f2fSdrahn   bfd_size_type reloc_count;
4529d2201f2fSdrahn   register struct pdp11_aout_reloc_external *rel;
4530d2201f2fSdrahn   struct pdp11_aout_reloc_external *rel_end;
4531d2201f2fSdrahn 
4532d2201f2fSdrahn   output_bfd = finfo->output_bfd;
4533d2201f2fSdrahn   check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
4534d2201f2fSdrahn 
4535d2201f2fSdrahn   BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_SIZE);
4536d2201f2fSdrahn   BFD_ASSERT (input_bfd->xvec->header_byteorder
4537d2201f2fSdrahn 	      == output_bfd->xvec->header_byteorder);
4538d2201f2fSdrahn 
4539*cf2f2c56Smiod   relocatable = finfo->info->relocatable;
4540d2201f2fSdrahn   syms = obj_aout_external_syms (input_bfd);
4541d2201f2fSdrahn   strings = obj_aout_external_strings (input_bfd);
4542d2201f2fSdrahn   sym_hashes = obj_aout_sym_hashes (input_bfd);
4543d2201f2fSdrahn   symbol_map = finfo->symbol_map;
4544d2201f2fSdrahn 
4545d2201f2fSdrahn   reloc_count = rel_size / RELOC_SIZE;
4546d2201f2fSdrahn   rel = relocs;
4547d2201f2fSdrahn   rel_end = (struct pdp11_aout_reloc_external *)(((char *)rel) + rel_size);
4548d2201f2fSdrahn   for (; rel < rel_end; ((char *)rel) += RELOC_SIZE)
4549d2201f2fSdrahn     {
4550d2201f2fSdrahn       bfd_vma r_addr;
4551d2201f2fSdrahn       int r_index;
4552d2201f2fSdrahn       int r_type;
4553d2201f2fSdrahn       int r_pcrel;
4554d2201f2fSdrahn       int r_extern;
4555d2201f2fSdrahn       reloc_howto_type *howto;
4556d2201f2fSdrahn       struct aout_link_hash_entry *h = NULL;
4557d2201f2fSdrahn       bfd_vma relocation;
4558d2201f2fSdrahn       bfd_reloc_status_type r;
4559d2201f2fSdrahn       int reloc_entry;
4560d2201f2fSdrahn 
4561d2201f2fSdrahn       reloc_entry = GET_WORD (input_bfd, (PTR)rel);
4562d2201f2fSdrahn       if (reloc_entry == 0)
4563d2201f2fSdrahn 	continue;
4564d2201f2fSdrahn 
4565d2201f2fSdrahn       {
4566d2201f2fSdrahn 	unsigned int howto_idx;
4567d2201f2fSdrahn 
4568d2201f2fSdrahn 	r_index = (reloc_entry & RIDXMASK) >> 4;
4569d2201f2fSdrahn 	r_type = reloc_entry & RTYPE;
4570d2201f2fSdrahn 	r_pcrel = reloc_entry & RELFLG;
4571d2201f2fSdrahn 	r_addr = (char *)rel - (char *)relocs;
4572d2201f2fSdrahn 
4573d2201f2fSdrahn 	r_extern = (r_type == REXT);
4574d2201f2fSdrahn 
4575d2201f2fSdrahn 	howto_idx = r_pcrel;
4576d2201f2fSdrahn 	BFD_ASSERT (howto_idx < TABLE_SIZE (howto_table_pdp11));
4577d2201f2fSdrahn 	howto = howto_table_pdp11 + howto_idx;
4578d2201f2fSdrahn       }
4579d2201f2fSdrahn 
4580*cf2f2c56Smiod       if (relocatable)
4581d2201f2fSdrahn 	{
4582*cf2f2c56Smiod 	  /* We are generating a relocatable output file, and must
4583d2201f2fSdrahn 	     modify the reloc accordingly.  */
4584d2201f2fSdrahn 	  if (r_extern)
4585d2201f2fSdrahn 	    {
4586d2201f2fSdrahn 	      /* If we know the symbol this relocation is against,
4587d2201f2fSdrahn 		 convert it into a relocation against a section.  This
4588d2201f2fSdrahn 		 is what the native linker does.  */
4589d2201f2fSdrahn 	      h = sym_hashes[r_index];
4590d2201f2fSdrahn 	      if (h != (struct aout_link_hash_entry *) NULL
4591d2201f2fSdrahn 		  && (h->root.type == bfd_link_hash_defined
4592d2201f2fSdrahn 		      || h->root.type == bfd_link_hash_defweak))
4593d2201f2fSdrahn 		{
4594d2201f2fSdrahn 		  asection *output_section;
4595d2201f2fSdrahn 
4596d2201f2fSdrahn 		  /* Compute a new r_index.  */
4597d2201f2fSdrahn 		  output_section = h->root.u.def.section->output_section;
4598d2201f2fSdrahn 		  if (output_section == obj_textsec (output_bfd))
4599d2201f2fSdrahn 		    r_type = N_TEXT;
4600d2201f2fSdrahn 		  else if (output_section == obj_datasec (output_bfd))
4601d2201f2fSdrahn 		    r_type = N_DATA;
4602d2201f2fSdrahn 		  else if (output_section == obj_bsssec (output_bfd))
4603d2201f2fSdrahn 		    r_type = N_BSS;
4604d2201f2fSdrahn 		  else
4605d2201f2fSdrahn 		    r_type = N_ABS;
4606d2201f2fSdrahn 
4607d2201f2fSdrahn 		  /* Add the symbol value and the section VMA to the
4608d2201f2fSdrahn 		     addend stored in the contents.  */
4609d2201f2fSdrahn 		  relocation = (h->root.u.def.value
4610d2201f2fSdrahn 				+ output_section->vma
4611d2201f2fSdrahn 				+ h->root.u.def.section->output_offset);
4612d2201f2fSdrahn 		}
4613d2201f2fSdrahn 	      else
4614d2201f2fSdrahn 		{
4615d2201f2fSdrahn 		  /* We must change r_index according to the symbol
4616d2201f2fSdrahn 		     map.  */
4617d2201f2fSdrahn 		  r_index = symbol_map[r_index];
4618d2201f2fSdrahn 
4619d2201f2fSdrahn 		  if (r_index == -1)
4620d2201f2fSdrahn 		    {
4621d2201f2fSdrahn 		      if (h != NULL)
4622d2201f2fSdrahn 			{
4623d2201f2fSdrahn 			  /* We decided to strip this symbol, but it
4624d2201f2fSdrahn                              turns out that we can't.  Note that we
4625d2201f2fSdrahn                              lose the other and desc information here.
4626d2201f2fSdrahn                              I don't think that will ever matter for a
4627d2201f2fSdrahn                              global symbol.  */
4628d2201f2fSdrahn 			  if (h->indx < 0)
4629d2201f2fSdrahn 			    {
4630d2201f2fSdrahn 			      h->indx = -2;
4631d2201f2fSdrahn 			      h->written = FALSE;
4632d2201f2fSdrahn 			      if (! aout_link_write_other_symbol (h,
4633d2201f2fSdrahn 								  (PTR) finfo))
4634d2201f2fSdrahn 				return FALSE;
4635d2201f2fSdrahn 			    }
4636d2201f2fSdrahn 			  r_index = h->indx;
4637d2201f2fSdrahn 			}
4638d2201f2fSdrahn 		      else
4639d2201f2fSdrahn 			{
4640d2201f2fSdrahn 			  const char *name;
4641d2201f2fSdrahn 
4642d2201f2fSdrahn 			  name = strings + GET_WORD (input_bfd,
4643d2201f2fSdrahn 						     syms[r_index].e_strx);
4644d2201f2fSdrahn 			  if (! ((*finfo->info->callbacks->unattached_reloc)
4645d2201f2fSdrahn 				 (finfo->info, name, input_bfd, input_section,
4646d2201f2fSdrahn 				  r_addr)))
4647d2201f2fSdrahn 			    return FALSE;
4648d2201f2fSdrahn 			  r_index = 0;
4649d2201f2fSdrahn 			}
4650d2201f2fSdrahn 		    }
4651d2201f2fSdrahn 
4652d2201f2fSdrahn 		  relocation = 0;
4653d2201f2fSdrahn 		}
4654d2201f2fSdrahn 
4655d2201f2fSdrahn 	      /* Write out the new r_index value.  */
4656d2201f2fSdrahn 	      reloc_entry = GET_WORD (input_bfd, rel->e_reloc_entry);
4657d2201f2fSdrahn 	      reloc_entry &= RIDXMASK;
4658d2201f2fSdrahn 	      reloc_entry |= r_index << 4;
4659d2201f2fSdrahn 	      PUT_WORD (input_bfd, reloc_entry, rel->e_reloc_entry);
4660d2201f2fSdrahn 	    }
4661d2201f2fSdrahn 	  else
4662d2201f2fSdrahn 	    {
4663d2201f2fSdrahn 	      asection *section;
4664d2201f2fSdrahn 
4665d2201f2fSdrahn 	      /* This is a relocation against a section.  We must
4666d2201f2fSdrahn 		 adjust by the amount that the section moved.  */
4667d2201f2fSdrahn 	      section = aout_reloc_type_to_section (input_bfd, r_type);
4668d2201f2fSdrahn 	      relocation = (section->output_section->vma
4669d2201f2fSdrahn 			    + section->output_offset
4670d2201f2fSdrahn 			    - section->vma);
4671d2201f2fSdrahn 	    }
4672d2201f2fSdrahn 
4673d2201f2fSdrahn 	  /* Change the address of the relocation.  */
4674d2201f2fSdrahn #if 0
4675d2201f2fSdrahn 	  PUT_WORD (output_bfd,
4676d2201f2fSdrahn 		    r_addr + input_section->output_offset,
4677d2201f2fSdrahn 		    rel->r_address);
4678d2201f2fSdrahn #else
4679d2201f2fSdrahn fprintf (stderr, "TODO: change the address of the relocation\n");
4680d2201f2fSdrahn #endif
4681d2201f2fSdrahn 
4682d2201f2fSdrahn 	  /* Adjust a PC relative relocation by removing the reference
4683d2201f2fSdrahn 	     to the original address in the section and including the
4684d2201f2fSdrahn 	     reference to the new address.  */
4685d2201f2fSdrahn 	  if (r_pcrel)
4686d2201f2fSdrahn 	    relocation -= (input_section->output_section->vma
4687d2201f2fSdrahn 			   + input_section->output_offset
4688d2201f2fSdrahn 			   - input_section->vma);
4689d2201f2fSdrahn 
4690d2201f2fSdrahn #ifdef MY_relocatable_reloc
4691d2201f2fSdrahn 	  MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr);
4692d2201f2fSdrahn #endif
4693d2201f2fSdrahn 
4694d2201f2fSdrahn 	  if (relocation == 0)
4695d2201f2fSdrahn 	    r = bfd_reloc_ok;
4696d2201f2fSdrahn 	  else
4697d2201f2fSdrahn 	    r = MY_relocate_contents (howto,
4698d2201f2fSdrahn 				      input_bfd, relocation,
4699d2201f2fSdrahn 				      contents + r_addr);
4700d2201f2fSdrahn 	}
4701d2201f2fSdrahn       else
4702d2201f2fSdrahn 	{
4703d2201f2fSdrahn 	  bfd_boolean hundef;
4704d2201f2fSdrahn 
4705d2201f2fSdrahn 	  /* We are generating an executable, and must do a full
4706d2201f2fSdrahn 	     relocation.  */
4707d2201f2fSdrahn 	  hundef = FALSE;
4708d2201f2fSdrahn 	  if (r_extern)
4709d2201f2fSdrahn 	    {
4710d2201f2fSdrahn 	      h = sym_hashes[r_index];
4711d2201f2fSdrahn 
4712d2201f2fSdrahn 	      if (h != (struct aout_link_hash_entry *) NULL
4713d2201f2fSdrahn 		  && (h->root.type == bfd_link_hash_defined
4714d2201f2fSdrahn 		      || h->root.type == bfd_link_hash_defweak))
4715d2201f2fSdrahn 		{
4716d2201f2fSdrahn 		  relocation = (h->root.u.def.value
4717d2201f2fSdrahn 				+ h->root.u.def.section->output_section->vma
4718d2201f2fSdrahn 				+ h->root.u.def.section->output_offset);
4719d2201f2fSdrahn 		}
4720d2201f2fSdrahn 	      else if (h != (struct aout_link_hash_entry *) NULL
4721d2201f2fSdrahn 		       && h->root.type == bfd_link_hash_undefweak)
4722d2201f2fSdrahn 		relocation = 0;
4723d2201f2fSdrahn 	      else
4724d2201f2fSdrahn 		{
4725d2201f2fSdrahn 		  hundef = TRUE;
4726d2201f2fSdrahn 		  relocation = 0;
4727d2201f2fSdrahn 		}
4728d2201f2fSdrahn 	    }
4729d2201f2fSdrahn 	  else
4730d2201f2fSdrahn 	    {
4731d2201f2fSdrahn 	      asection *section;
4732d2201f2fSdrahn 
4733d2201f2fSdrahn 	      section = aout_reloc_type_to_section (input_bfd, r_type);
4734d2201f2fSdrahn 	      relocation = (section->output_section->vma
4735d2201f2fSdrahn 			    + section->output_offset
4736d2201f2fSdrahn 			    - section->vma);
4737d2201f2fSdrahn 	      if (r_pcrel)
4738d2201f2fSdrahn 		relocation += input_section->vma;
4739d2201f2fSdrahn 	    }
4740d2201f2fSdrahn 
4741d2201f2fSdrahn 	  if (check_dynamic_reloc != NULL)
4742d2201f2fSdrahn 	    {
4743d2201f2fSdrahn 	      bfd_boolean skip;
4744d2201f2fSdrahn 
4745d2201f2fSdrahn 	      if (! ((*check_dynamic_reloc)
4746d2201f2fSdrahn 		     (finfo->info, input_bfd, input_section, h,
4747d2201f2fSdrahn 		      (PTR) rel, contents, &skip, &relocation)))
4748d2201f2fSdrahn 		return FALSE;
4749d2201f2fSdrahn 	      if (skip)
4750d2201f2fSdrahn 		continue;
4751d2201f2fSdrahn 	    }
4752d2201f2fSdrahn 
4753d2201f2fSdrahn 	  /* Now warn if a global symbol is undefined.  We could not
4754d2201f2fSdrahn              do this earlier, because check_dynamic_reloc might want
4755d2201f2fSdrahn              to skip this reloc.  */
4756d2201f2fSdrahn 	  if (hundef && ! finfo->info->shared)
4757d2201f2fSdrahn 	    {
4758d2201f2fSdrahn 	      const char *name;
4759d2201f2fSdrahn 
4760d2201f2fSdrahn 	      if (h != NULL)
4761d2201f2fSdrahn 		name = h->root.root.string;
4762d2201f2fSdrahn 	      else
4763d2201f2fSdrahn 		name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
4764d2201f2fSdrahn 	      if (! ((*finfo->info->callbacks->undefined_symbol)
4765d2201f2fSdrahn 		     (finfo->info, name, input_bfd, input_section,
4766d2201f2fSdrahn 		      r_addr, TRUE)))
4767d2201f2fSdrahn 		return FALSE;
4768d2201f2fSdrahn 	    }
4769d2201f2fSdrahn 
4770d2201f2fSdrahn 	  r = MY_final_link_relocate (howto,
4771d2201f2fSdrahn 				      input_bfd, input_section,
4772d2201f2fSdrahn 				      contents, r_addr, relocation,
4773d2201f2fSdrahn 				      (bfd_vma) 0);
4774d2201f2fSdrahn 	}
4775d2201f2fSdrahn 
4776d2201f2fSdrahn       if (r != bfd_reloc_ok)
4777d2201f2fSdrahn 	{
4778d2201f2fSdrahn 	  switch (r)
4779d2201f2fSdrahn 	    {
4780d2201f2fSdrahn 	    default:
4781d2201f2fSdrahn 	    case bfd_reloc_outofrange:
4782d2201f2fSdrahn 	      abort ();
4783d2201f2fSdrahn 	    case bfd_reloc_overflow:
4784d2201f2fSdrahn 	      {
4785d2201f2fSdrahn 		const char *name;
4786d2201f2fSdrahn 
4787d2201f2fSdrahn 		if (h != NULL)
4788d2201f2fSdrahn 		  name = h->root.root.string;
4789d2201f2fSdrahn 		else if (r_extern)
4790d2201f2fSdrahn 		  name = strings + GET_WORD (input_bfd,
4791d2201f2fSdrahn 					     syms[r_index].e_strx);
4792d2201f2fSdrahn 		else
4793d2201f2fSdrahn 		  {
4794d2201f2fSdrahn 		    asection *s;
4795d2201f2fSdrahn 
4796d2201f2fSdrahn 		    s = aout_reloc_type_to_section (input_bfd, r_type);
4797d2201f2fSdrahn 		    name = bfd_section_name (input_bfd, s);
4798d2201f2fSdrahn 		  }
4799d2201f2fSdrahn 		if (! ((*finfo->info->callbacks->reloc_overflow)
4800d2201f2fSdrahn 		       (finfo->info, name, howto->name,
4801d2201f2fSdrahn 			(bfd_vma) 0, input_bfd, input_section, r_addr)))
4802d2201f2fSdrahn 		  return FALSE;
4803d2201f2fSdrahn 	      }
4804d2201f2fSdrahn 	      break;
4805d2201f2fSdrahn 	    }
4806d2201f2fSdrahn 	}
4807d2201f2fSdrahn     }
4808d2201f2fSdrahn 
4809d2201f2fSdrahn   return TRUE;
4810d2201f2fSdrahn }
4811d2201f2fSdrahn 
4812d2201f2fSdrahn /* Handle a link order which is supposed to generate a reloc.  */
4813d2201f2fSdrahn 
4814d2201f2fSdrahn static bfd_boolean
aout_link_reloc_link_order(finfo,o,p)4815d2201f2fSdrahn aout_link_reloc_link_order (finfo, o, p)
4816d2201f2fSdrahn      struct aout_final_link_info *finfo;
4817d2201f2fSdrahn      asection *o;
4818d2201f2fSdrahn      struct bfd_link_order *p;
4819d2201f2fSdrahn {
4820d2201f2fSdrahn   struct bfd_link_order_reloc *pr;
4821d2201f2fSdrahn   int r_index;
4822d2201f2fSdrahn   int r_extern;
4823d2201f2fSdrahn   reloc_howto_type *howto;
4824d2201f2fSdrahn   file_ptr *reloff_ptr;
4825d2201f2fSdrahn   struct reloc_std_external srel;
4826d2201f2fSdrahn   PTR rel_ptr;
4827d2201f2fSdrahn   bfd_size_type rel_size;
4828d2201f2fSdrahn 
4829d2201f2fSdrahn   pr = p->u.reloc.p;
4830d2201f2fSdrahn 
4831d2201f2fSdrahn   if (p->type == bfd_section_reloc_link_order)
4832d2201f2fSdrahn     {
4833d2201f2fSdrahn       r_extern = 0;
4834d2201f2fSdrahn       if (bfd_is_abs_section (pr->u.section))
4835d2201f2fSdrahn 	r_index = N_ABS | N_EXT;
4836d2201f2fSdrahn       else
4837d2201f2fSdrahn 	{
4838d2201f2fSdrahn 	  BFD_ASSERT (pr->u.section->owner == finfo->output_bfd);
4839d2201f2fSdrahn 	  r_index = pr->u.section->target_index;
4840d2201f2fSdrahn 	}
4841d2201f2fSdrahn     }
4842d2201f2fSdrahn   else
4843d2201f2fSdrahn     {
4844d2201f2fSdrahn       struct aout_link_hash_entry *h;
4845d2201f2fSdrahn 
4846d2201f2fSdrahn       BFD_ASSERT (p->type == bfd_symbol_reloc_link_order);
4847d2201f2fSdrahn       r_extern = 1;
4848d2201f2fSdrahn       h = ((struct aout_link_hash_entry *)
4849d2201f2fSdrahn 	   bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info,
4850d2201f2fSdrahn 					 pr->u.name, FALSE, FALSE, TRUE));
4851d2201f2fSdrahn       if (h != (struct aout_link_hash_entry *) NULL
4852d2201f2fSdrahn 	  && h->indx >= 0)
4853d2201f2fSdrahn 	r_index = h->indx;
4854d2201f2fSdrahn       else if (h != NULL)
4855d2201f2fSdrahn 	{
4856d2201f2fSdrahn 	  /* We decided to strip this symbol, but it turns out that we
4857d2201f2fSdrahn 	     can't.  Note that we lose the other and desc information
4858d2201f2fSdrahn 	     here.  I don't think that will ever matter for a global
4859d2201f2fSdrahn 	     symbol.  */
4860d2201f2fSdrahn 	  h->indx = -2;
4861d2201f2fSdrahn 	  h->written = FALSE;
4862d2201f2fSdrahn 	  if (! aout_link_write_other_symbol (h, (PTR) finfo))
4863d2201f2fSdrahn 	    return FALSE;
4864d2201f2fSdrahn 	  r_index = h->indx;
4865d2201f2fSdrahn 	}
4866d2201f2fSdrahn       else
4867d2201f2fSdrahn 	{
4868d2201f2fSdrahn 	  if (! ((*finfo->info->callbacks->unattached_reloc)
4869d2201f2fSdrahn 		 (finfo->info, pr->u.name, (bfd *) NULL,
4870d2201f2fSdrahn 		  (asection *) NULL, (bfd_vma) 0)))
4871d2201f2fSdrahn 	    return FALSE;
4872d2201f2fSdrahn 	  r_index = 0;
4873d2201f2fSdrahn 	}
4874d2201f2fSdrahn     }
4875d2201f2fSdrahn 
4876d2201f2fSdrahn   howto = bfd_reloc_type_lookup (finfo->output_bfd, pr->reloc);
4877d2201f2fSdrahn   if (howto == 0)
4878d2201f2fSdrahn     {
4879d2201f2fSdrahn       bfd_set_error (bfd_error_bad_value);
4880d2201f2fSdrahn       return FALSE;
4881d2201f2fSdrahn     }
4882d2201f2fSdrahn 
4883d2201f2fSdrahn   if (o == obj_textsec (finfo->output_bfd))
4884d2201f2fSdrahn     reloff_ptr = &finfo->treloff;
4885d2201f2fSdrahn   else if (o == obj_datasec (finfo->output_bfd))
4886d2201f2fSdrahn     reloff_ptr = &finfo->dreloff;
4887d2201f2fSdrahn   else
4888d2201f2fSdrahn     abort ();
4889d2201f2fSdrahn 
4890d2201f2fSdrahn #ifdef MY_put_reloc
4891d2201f2fSdrahn   MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto,
4892d2201f2fSdrahn 	       &srel);
4893d2201f2fSdrahn #else
4894d2201f2fSdrahn   {
4895d2201f2fSdrahn     int r_pcrel;
4896d2201f2fSdrahn     int r_baserel;
4897d2201f2fSdrahn     int r_jmptable;
4898d2201f2fSdrahn     int r_relative;
4899d2201f2fSdrahn     int r_length;
4900d2201f2fSdrahn 
4901d2201f2fSdrahn     fprintf (stderr, "TODO: line %d in bfd/pdp11.c\n", __LINE__);
4902d2201f2fSdrahn 
4903d2201f2fSdrahn     r_pcrel = howto->pc_relative;
4904d2201f2fSdrahn     r_baserel = (howto->type & 8) != 0;
4905d2201f2fSdrahn     r_jmptable = (howto->type & 16) != 0;
4906d2201f2fSdrahn     r_relative = (howto->type & 32) != 0;
4907d2201f2fSdrahn     r_length = howto->size;
4908d2201f2fSdrahn 
4909d2201f2fSdrahn     PUT_WORD (finfo->output_bfd, p->offset, srel.r_address);
4910d2201f2fSdrahn     if (bfd_header_big_endian (finfo->output_bfd))
4911d2201f2fSdrahn       {
4912d2201f2fSdrahn 	srel.r_index[0] = r_index >> 16;
4913d2201f2fSdrahn 	srel.r_index[1] = r_index >> 8;
4914d2201f2fSdrahn 	srel.r_index[2] = r_index;
4915d2201f2fSdrahn 	srel.r_type[0] =
4916d2201f2fSdrahn 	  ((r_extern ?     RELOC_STD_BITS_EXTERN_BIG : 0)
4917d2201f2fSdrahn 	   | (r_pcrel ?    RELOC_STD_BITS_PCREL_BIG : 0)
4918d2201f2fSdrahn 	   | (r_baserel ?  RELOC_STD_BITS_BASEREL_BIG : 0)
4919d2201f2fSdrahn 	   | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
4920d2201f2fSdrahn 	   | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
4921d2201f2fSdrahn 	   | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG));
4922d2201f2fSdrahn       }
4923d2201f2fSdrahn     else
4924d2201f2fSdrahn       {
4925d2201f2fSdrahn 	srel.r_index[2] = r_index >> 16;
4926d2201f2fSdrahn 	srel.r_index[1] = r_index >> 8;
4927d2201f2fSdrahn 	srel.r_index[0] = r_index;
4928d2201f2fSdrahn 	srel.r_type[0] =
4929d2201f2fSdrahn 	  ((r_extern ?     RELOC_STD_BITS_EXTERN_LITTLE : 0)
4930d2201f2fSdrahn 	   | (r_pcrel ?    RELOC_STD_BITS_PCREL_LITTLE : 0)
4931d2201f2fSdrahn 	   | (r_baserel ?  RELOC_STD_BITS_BASEREL_LITTLE : 0)
4932d2201f2fSdrahn 	   | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
4933d2201f2fSdrahn 	   | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
4934d2201f2fSdrahn 	   | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE));
4935d2201f2fSdrahn       }
4936d2201f2fSdrahn   }
4937d2201f2fSdrahn #endif
4938d2201f2fSdrahn   rel_ptr = (PTR) &srel;
4939d2201f2fSdrahn 
4940d2201f2fSdrahn   /* We have to write the addend into the object file, since
4941d2201f2fSdrahn      standard a.out relocs are in place.  It would be more
4942d2201f2fSdrahn      reliable if we had the current contents of the file here,
4943d2201f2fSdrahn      rather than assuming zeroes, but we can't read the file since
4944d2201f2fSdrahn      it was opened using bfd_openw.  */
4945d2201f2fSdrahn   if (pr->addend != 0)
4946d2201f2fSdrahn     {
4947d2201f2fSdrahn       bfd_size_type size;
4948d2201f2fSdrahn       bfd_reloc_status_type r;
4949d2201f2fSdrahn       bfd_byte *buf;
4950d2201f2fSdrahn       bfd_boolean ok;
4951d2201f2fSdrahn 
4952d2201f2fSdrahn       size = bfd_get_reloc_size (howto);
4953d2201f2fSdrahn       buf = (bfd_byte *) bfd_zmalloc (size);
4954d2201f2fSdrahn       if (buf == (bfd_byte *) NULL)
4955d2201f2fSdrahn 	return FALSE;
4956d2201f2fSdrahn       r = MY_relocate_contents (howto, finfo->output_bfd,
4957d2201f2fSdrahn 				pr->addend, buf);
4958d2201f2fSdrahn       switch (r)
4959d2201f2fSdrahn 	{
4960d2201f2fSdrahn 	case bfd_reloc_ok:
4961d2201f2fSdrahn 	  break;
4962d2201f2fSdrahn 	default:
4963d2201f2fSdrahn 	case bfd_reloc_outofrange:
4964d2201f2fSdrahn 	  abort ();
4965d2201f2fSdrahn 	case bfd_reloc_overflow:
4966d2201f2fSdrahn 	  if (! ((*finfo->info->callbacks->reloc_overflow)
4967d2201f2fSdrahn 		 (finfo->info,
4968d2201f2fSdrahn 		  (p->type == bfd_section_reloc_link_order
4969d2201f2fSdrahn 		   ? bfd_section_name (finfo->output_bfd,
4970d2201f2fSdrahn 				       pr->u.section)
4971d2201f2fSdrahn 		   : pr->u.name),
4972d2201f2fSdrahn 		  howto->name, pr->addend, (bfd *) NULL,
4973d2201f2fSdrahn 		  (asection *) NULL, (bfd_vma) 0)))
4974d2201f2fSdrahn 	    {
4975d2201f2fSdrahn 	      free (buf);
4976d2201f2fSdrahn 	      return FALSE;
4977d2201f2fSdrahn 	    }
4978d2201f2fSdrahn 	  break;
4979d2201f2fSdrahn 	}
4980d2201f2fSdrahn       ok = bfd_set_section_contents (finfo->output_bfd, o,
4981d2201f2fSdrahn 				     (PTR) buf,
4982d2201f2fSdrahn 				     (file_ptr) p->offset,
4983d2201f2fSdrahn 				     size);
4984d2201f2fSdrahn       free (buf);
4985d2201f2fSdrahn       if (! ok)
4986d2201f2fSdrahn 	return FALSE;
4987d2201f2fSdrahn     }
4988d2201f2fSdrahn 
4989d2201f2fSdrahn   rel_size = obj_reloc_entry_size (finfo->output_bfd);
4990d2201f2fSdrahn   if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0
4991d2201f2fSdrahn       || bfd_bwrite (rel_ptr, rel_size, finfo->output_bfd) != rel_size)
4992d2201f2fSdrahn     return FALSE;
4993d2201f2fSdrahn 
4994d2201f2fSdrahn   *reloff_ptr += rel_size;
4995d2201f2fSdrahn 
4996d2201f2fSdrahn   /* Assert that the relocs have not run into the symbols, and that n
4997d2201f2fSdrahn      the text relocs have not run into the data relocs.  */
4998d2201f2fSdrahn   BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (finfo->output_bfd)
4999d2201f2fSdrahn 	      && (reloff_ptr != &finfo->treloff
5000d2201f2fSdrahn 		  || (*reloff_ptr
5001d2201f2fSdrahn 		      <= obj_datasec (finfo->output_bfd)->rel_filepos)));
5002d2201f2fSdrahn 
5003d2201f2fSdrahn   return TRUE;
5004d2201f2fSdrahn }
5005d2201f2fSdrahn /* end of modified aoutx.h */
5006d2201f2fSdrahn 
5007*cf2f2c56Smiod static bfd_vma
bfd_getp32(const void * p)5008*cf2f2c56Smiod bfd_getp32 (const void *p)
5009d2201f2fSdrahn {
5010*cf2f2c56Smiod   const bfd_byte *addr = p;
5011*cf2f2c56Smiod   unsigned long v;
5012*cf2f2c56Smiod   v = (unsigned long) addr[1] << 24;
5013*cf2f2c56Smiod   v |= (unsigned long) addr[0] << 16;
5014*cf2f2c56Smiod   v |= (unsigned long) addr[3] << 8;
5015*cf2f2c56Smiod   v |= (unsigned long) addr[2];
5016*cf2f2c56Smiod   return v;
5017d2201f2fSdrahn }
5018d2201f2fSdrahn 
5019d2201f2fSdrahn #define COERCE32(x) (((bfd_signed_vma) (x) ^ 0x80000000) - 0x80000000)
5020d2201f2fSdrahn 
5021*cf2f2c56Smiod static bfd_signed_vma
bfd_getp_signed_32(const void * p)5022*cf2f2c56Smiod bfd_getp_signed_32 (const void *p)
5023d2201f2fSdrahn {
5024*cf2f2c56Smiod   const bfd_byte *addr = p;
5025*cf2f2c56Smiod   unsigned long v;
5026*cf2f2c56Smiod   v = (unsigned long) addr[1] << 24;
5027*cf2f2c56Smiod   v |= (unsigned long) addr[0] << 16;
5028*cf2f2c56Smiod   v |= (unsigned long) addr[3] << 8;
5029*cf2f2c56Smiod   v |= (unsigned long) addr[2];
5030*cf2f2c56Smiod   return COERCE32 (v);
5031d2201f2fSdrahn }
5032d2201f2fSdrahn 
5033*cf2f2c56Smiod static void
bfd_putp32(bfd_vma data,void * p)5034*cf2f2c56Smiod bfd_putp32 (bfd_vma data, void *p)
5035d2201f2fSdrahn {
5036*cf2f2c56Smiod   bfd_byte *addr = p;
5037*cf2f2c56Smiod   addr[0] = (data >> 16) & 0xff;
5038*cf2f2c56Smiod   addr[1] = (data >> 24) & 0xff;
5039*cf2f2c56Smiod   addr[2] = (data >> 0) & 0xff;
5040*cf2f2c56Smiod   addr[3] = (data >> 8) & 0xff;
5041d2201f2fSdrahn }
5042