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