1 /* BFD semi-generic back-end for a.out binaries
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Written by Cygnus Support.
5 This file is part of BFD, the Binary File Descriptor library.
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
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
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.
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
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 @section a.out backends
24 BFD supports a number of different flavours of a.out format, though
25 the major differences are only the sizes of the structures on disk,
26 and the shape of the relocation information.
28 The support is split into a basic support file @code{aoutx.h} and
29 other files which derive functions from the base. One derivation file
30 is @code{aoutf1.h} (for a.out flavour 1), and adds to the basic a.out
31 functions support for sun3, sun4, 386 and 29k a.out files, to create a
32 target jump vector for a specific target.
34 This information is further split out into more specific files for each
35 machine, including @code{sunos.c} for sun3 and sun4, @code{newsos3.c} for
36 the Sony NEWS, and @code{demo64.c} for a demonstration of a 64 bit a.out
39 The base file @code{aoutx.h} defines general mechanisms for reading
40 and writing records to and from disk, and various other methods which
41 BFD requires. It is included by @code{aout32.c} and @code{aout64.c} to
42 form the names aout_32_swap_exec_header_in,
43 aout_64_swap_exec_header_in, etc.
45 As an example, this is what goes on to make the back end for a sun4, from aout32.c
55 aout_32_canonicalize_reloc
56 aout_32_find_nearest_line
58 aout_32_get_reloc_upper_bound
66 #define TARGET_NAME "a.out-sunos-big"
67 #define VECNAME sunos_big_vec
70 requires all the names from aout32.c, and produces the jump vector
76 The file host-aout.c is a special case. It is for a large set of hosts
77 that use ``more or less standard'' a.out files, and for which cross-debugging
78 is not interesting. It uses the standard 32-bit a.out support routines,
79 but determines the file offsets and addresses of the text, data,
80 and BSS sections, the machine architecture and machine type,
81 and the entry point address, in a host-dependent manner. Once these
82 values have been determined, generic code is used to handle the
85 When porting it to run on a new system, you must supply:
89 HOST_MACHINE_ARCH (optional)
90 HOST_MACHINE_MACHINE (optional)
94 in the file ../include/sys/h-XXX.h (for your host). These values, plus
95 the structures and macros defined in <a.out.h> on your host system, will
96 produce a BFD target that will access ordinary a.out files on your host.
98 To configure a new machine to use host-aout.c, specify:
100 TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
101 TDEPFILES= host-aout.o trad-core.o
103 in the config/mt-XXX file, and modify configure.in to use the
104 mt-XXX file (by setting "bfd_target=XXX") when your configuration is
110 #define KEEPITTYPE int
114 #include <ansidecl.h>
116 struct external_exec
;
119 #include "aout/aout64.h"
120 #include "aout/stab_gnu.h"
123 void (*bfd_error_trap
)();
126 @subsection relocations
127 The file @code{aoutx.h} caters for both the @emph{standard} and
128 @emph{extended} forms of a.out relocation records.
130 The standard records are characterised by containing only an address,
131 a symbol index and a type field. The extended records (used on 29ks
132 and sparcs) also have a full integer for an addend.
134 #define CTOR_TABLE_RELOC_IDX 2
137 static reloc_howto_type howto_table_ext
[] =
139 HOWTO(RELOC_8
, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false),
140 HOWTO(RELOC_16
, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false),
141 HOWTO(RELOC_32
, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false),
142 HOWTO(RELOC_DISP8
, 0, 0, 8, true, 0, false, true,0,"DISP8", false, 0,0x000000ff, false),
143 HOWTO(RELOC_DISP16
, 0, 1, 16, true, 0, false, true,0,"DISP16", false, 0,0x0000ffff, false),
144 HOWTO(RELOC_DISP32
, 0, 2, 32, true, 0, false, true,0,"DISP32", false, 0,0xffffffff, false),
145 HOWTO(RELOC_WDISP30
,2, 2, 30, true, 0, false, true,0,"WDISP30", false, 0,0x3fffffff, false),
146 HOWTO(RELOC_WDISP22
,2, 2, 22, true, 0, false, true,0,"WDISP22", false, 0,0x003fffff, false),
147 HOWTO(RELOC_HI22
, 10, 2, 22, false, 0, false, true,0,"HI22", false, 0,0x003fffff, false),
148 HOWTO(RELOC_22
, 0, 2, 22, false, 0, false, true,0,"22", false, 0,0x003fffff, false),
149 HOWTO(RELOC_13
, 0, 2, 13, false, 0, false, true,0,"13", false, 0,0x00001fff, false),
150 HOWTO(RELOC_LO10
, 0, 2, 10, false, 0, false, true,0,"LO10", false, 0,0x000003ff, false),
151 HOWTO(RELOC_SFA_BASE
,0, 2, 32, false, 0, false, true,0,"SFA_BASE", false, 0,0xffffffff, false),
152 HOWTO(RELOC_SFA_OFF13
,0,2, 32, false, 0, false, true,0,"SFA_OFF13",false, 0,0xffffffff, false),
153 HOWTO(RELOC_BASE10
, 0, 2, 16, false, 0, false, true,0,"BASE10", false, 0,0x0000ffff, false),
154 HOWTO(RELOC_BASE13
, 0, 2, 13, false, 0, false, true,0,"BASE13", false, 0,0x00001fff, false),
155 HOWTO(RELOC_BASE22
, 0, 2, 0, false, 0, false, true,0,"BASE22", false, 0,0x00000000, false),
156 HOWTO(RELOC_PC10
, 0, 2, 10, false, 0, false, true,0,"PC10", false, 0,0x000003ff, false),
157 HOWTO(RELOC_PC22
, 0, 2, 22, false, 0, false, true,0,"PC22", false, 0,0x003fffff, false),
158 HOWTO(RELOC_JMP_TBL
,0, 2, 32, false, 0, false, true,0,"JMP_TBL", false, 0,0xffffffff, false),
159 HOWTO(RELOC_SEGOFF16
,0, 2, 0, false, 0, false, true,0,"SEGOFF16", false, 0,0x00000000, false),
160 HOWTO(RELOC_GLOB_DAT
,0, 2, 0, false, 0, false, true,0,"GLOB_DAT", false, 0,0x00000000, false),
161 HOWTO(RELOC_JMP_SLOT
,0, 2, 0, false, 0, false, true,0,"JMP_SLOT", false, 0,0x00000000, false),
162 HOWTO(RELOC_RELATIVE
,0, 2, 0, false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
166 /* Convert standard reloc records to "arelent" format (incl byte swap). */
168 static reloc_howto_type howto_table_std
[] = {
169 /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */
170 HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
171 HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
172 HOWTO( 2, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
173 HOWTO( 3, 0, 3, 64, false, 0, true, true,0,"64", true, 0xdeaddead,0xdeaddead, false),
174 HOWTO( 4, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
175 HOWTO( 5, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
176 HOWTO( 6, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
177 HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedface,0xfeedface, false),
181 bfd_error_vector_type bfd_error_vector
;
184 @subsection Internal Entry Points
185 @code{aoutx.h} exports several routines for accessing the contents of
186 an a.out file, which are gathered and exported in turn by various
187 format specific files (eg sunos.c).
191 *i aout_<size>_swap_exec_header_in
192 Swaps the information in an executable header taken from a raw byte stream memory image,
193 into the internal exec_header structure.
194 *; PROTO(void, aout_<size>_swap_exec_header_in,
196 struct external_exec *raw_bytes,
197 struct internal_exec *execp));
201 DEFUN(NAME(aout
,swap_exec_header_in
),(abfd
, raw_bytes
, execp
),
203 struct external_exec
*raw_bytes AND
204 struct internal_exec
*execp
)
206 struct external_exec
*bytes
= (struct external_exec
*)raw_bytes
;
208 /* Now fill in fields in the execp, from the bytes in the raw data. */
209 execp
->a_info
= bfd_h_get_32 (abfd
, bytes
->e_info
);
210 execp
->a_text
= GET_WORD (abfd
, bytes
->e_text
);
211 execp
->a_data
= GET_WORD (abfd
, bytes
->e_data
);
212 execp
->a_bss
= GET_WORD (abfd
, bytes
->e_bss
);
213 execp
->a_syms
= GET_WORD (abfd
, bytes
->e_syms
);
214 execp
->a_entry
= GET_WORD (abfd
, bytes
->e_entry
);
215 execp
->a_trsize
= GET_WORD (abfd
, bytes
->e_trsize
);
216 execp
->a_drsize
= GET_WORD (abfd
, bytes
->e_drsize
);
220 *i aout_<size>_swap_exec_header_out
221 Swaps the information in an internal exec header structure into the
222 supplied buffer ready for writing to disk.
223 *; PROTO(void, aout_<size>_swap_exec_header_out,
225 struct internal_exec *execp,
226 struct external_exec *raw_bytes));
229 DEFUN(NAME(aout
,swap_exec_header_out
),(abfd
, execp
, raw_bytes
),
231 struct internal_exec
*execp AND
232 struct external_exec
*raw_bytes
)
234 struct external_exec
*bytes
= (struct external_exec
*)raw_bytes
;
236 /* Now fill in fields in the raw data, from the fields in the exec struct. */
237 bfd_h_put_32 (abfd
, execp
->a_info
, bytes
->e_info
);
238 PUT_WORD (abfd
, execp
->a_text
, bytes
->e_text
);
239 PUT_WORD (abfd
, execp
->a_data
, bytes
->e_data
);
240 PUT_WORD (abfd
, execp
->a_bss
, bytes
->e_bss
);
241 PUT_WORD (abfd
, execp
->a_syms
, bytes
->e_syms
);
242 PUT_WORD (abfd
, execp
->a_entry
, bytes
->e_entry
);
243 PUT_WORD (abfd
, execp
->a_trsize
, bytes
->e_trsize
);
244 PUT_WORD (abfd
, execp
->a_drsize
, bytes
->e_drsize
);
249 struct internal_exec e
;
254 *i aout_<size>_some_aout_object_p
256 Some A.OUT variant thinks that the file whose format we're checking
257 is an a.out file. Do some more checking, and set up for access if
258 it really is. Call back to the calling environments "finish up"
259 function just before returning, to handle any last-minute setup.
261 *; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
263 bfd_target *(*callback_to_real_object_p)()));
267 DEFUN(NAME(aout
,some_aout_object_p
),(abfd
, execp
, callback_to_real_object_p
),
269 struct internal_exec
*execp AND
270 bfd_target
*(*callback_to_real_object_p
) ())
272 struct container
*rawptr
;
275 rawptr
= (struct container
*) bfd_zalloc (abfd
, sizeof (struct container
));
276 if (rawptr
== NULL
) {
277 bfd_error
= no_memory
;
281 set_tdata (abfd
, &rawptr
->a
);
282 exec_hdr (abfd
) = &rawptr
->e
;
283 *exec_hdr (abfd
) = *execp
; /* Copy in the internal_exec struct */
284 execp
= exec_hdr (abfd
); /* Switch to using the newly malloc'd one */
286 /* Set the file flags */
287 abfd
->flags
= NO_FLAGS
;
288 if (execp
->a_drsize
|| execp
->a_trsize
)
289 abfd
->flags
|= HAS_RELOC
;
290 /* Setting of EXEC_P has been deferred to the bottom of this function */
292 abfd
->flags
|= HAS_LINENO
| HAS_DEBUG
| HAS_SYMS
| HAS_LOCALS
;
294 if (N_MAGIC (*execp
) == ZMAGIC
) abfd
->flags
|= D_PAGED
;
295 if (N_MAGIC (*execp
) == NMAGIC
) abfd
->flags
|= WP_TEXT
;
297 bfd_get_start_address (abfd
) = execp
->a_entry
;
299 obj_aout_symbols (abfd
) = (aout_symbol_type
*)NULL
;
300 bfd_get_symcount (abfd
) = execp
->a_syms
/ sizeof (struct external_nlist
);
302 /* Set the default architecture and machine type. These can be
303 overridden in the callback routine. */
305 bfd_default_set_arch_mach(abfd
, bfd_arch_unknown
, 0);
307 /* The default relocation entry size is that of traditional V7 Unix. */
308 obj_reloc_entry_size (abfd
) = RELOC_STD_SIZE
;
310 /* The default symbol entry size is that of traditional Unix. */
311 obj_symbol_entry_size (abfd
) = EXTERNAL_NLIST_SIZE
;
313 /* create the sections. This is raunchy, but bfd_close wants to reclaim
315 obj_textsec (abfd
) = (asection
*)NULL
;
316 obj_datasec (abfd
) = (asection
*)NULL
;
317 obj_bsssec (abfd
) = (asection
*)NULL
;
318 (void)bfd_make_section(abfd
, ".text");
319 (void)bfd_make_section(abfd
, ".data");
320 (void)bfd_make_section(abfd
, ".bss");
322 abfd
->sections
= obj_textsec (abfd
);
323 obj_textsec (abfd
)->next
= obj_datasec (abfd
);
324 obj_datasec (abfd
)->next
= obj_bsssec (abfd
);
326 obj_datasec (abfd
)->size
= execp
->a_data
;
327 obj_bsssec (abfd
)->size
= execp
->a_bss
;
329 obj_textsec (abfd
)->flags
= (execp
->a_trsize
!= 0 ?
330 (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_HAS_CONTENTS
) :
331 (SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
));
332 obj_datasec (abfd
)->flags
= (execp
->a_drsize
!= 0 ?
333 (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_HAS_CONTENTS
) :
334 (SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
));
335 obj_bsssec (abfd
)->flags
= SEC_ALLOC
;
337 #ifdef THIS_IS_ONLY_DOCUMENTATION
338 /* The common code can't fill in these things because they depend
339 on either the start address of the text segment, the rounding
340 up of virtual addersses between segments, or the starting file
341 position of the text segment -- all of which varies among different
342 versions of a.out. */
344 /* Call back to the format-dependent code to fill in the rest of the
345 fields and do any further cleanup. Things that should be filled
346 in by the callback: */
348 struct exec
*execp
= exec_hdr (abfd
);
350 obj_textsec (abfd
)->size
= N_TXTSIZE(*execp
);
351 /* data and bss are already filled in since they're so standard */
353 /* The virtual memory addresses of the sections */
354 obj_textsec (abfd
)->vma
= N_TXTADDR(*execp
);
355 obj_datasec (abfd
)->vma
= N_DATADDR(*execp
);
356 obj_bsssec (abfd
)->vma
= N_BSSADDR(*execp
);
358 /* The file offsets of the sections */
359 obj_textsec (abfd
)->filepos
= N_TXTOFF(*execp
);
360 obj_datasec (abfd
)->filepos
= N_DATOFF(*execp
);
362 /* The file offsets of the relocation info */
363 obj_textsec (abfd
)->rel_filepos
= N_TRELOFF(*execp
);
364 obj_datasec (abfd
)->rel_filepos
= N_DRELOFF(*execp
);
366 /* The file offsets of the string table and symbol table. */
367 obj_str_filepos (abfd
) = N_STROFF (*execp
);
368 obj_sym_filepos (abfd
) = N_SYMOFF (*execp
);
370 /* Determine the architecture and machine type of the object file. */
371 switch (N_MACHTYPE (*exec_hdr (abfd
))) {
373 abfd
->obj_arch
= bfd_arch_obscure
;
377 /* Determine the size of a relocation entry */
378 switch (abfd
->obj_arch
) {
381 obj_reloc_entry_size (abfd
) = RELOC_EXT_SIZE
;
383 obj_reloc_entry_size (abfd
) = RELOC_STD_SIZE
;
386 adata(abfd
)->page_size
= PAGE_SIZE
;
387 adata(abfd
)->segment_size
= SEGMENT_SIZE
;
388 adata(abfd
)->exec_bytes_size
= EXEC_BYTES_SIZE
;
392 /* The architecture is encoded in various ways in various a.out variants,
393 or is not encoded at all in some of them. The relocation size depends
394 on the architecture and the a.out variant. Finally, the return value
395 is the bfd_target vector in use. If an error occurs, return zero and
396 set bfd_error to the appropriate error code.
398 Formats such as b.out, which have additional fields in the a.out
399 header, should cope with them in this callback as well. */
400 #endif /* DOCUMENTATION */
402 result
= (*callback_to_real_object_p
)(abfd
);
404 /* Now that the segment addresses have been worked out, take a better
405 guess at whether the file is executable. If the entry point
406 is within the text segment, assume it is. (This makes files
407 executable even if their entry point address is 0, as long as
408 their text starts at zero.)
410 At some point we should probably break down and stat the file and
411 declare it executable if (one of) its 'x' bits are on... */
412 if ((execp
->a_entry
>= obj_textsec(abfd
)->vma
) &&
413 (execp
->a_entry
< obj_textsec(abfd
)->vma
+ obj_textsec(abfd
)->size
))
414 abfd
->flags
|= EXEC_P
;
419 *i aout_<size>_mkobject
421 This routine initializes a BFD for use with a.out files.
423 *; PROTO(boolean, aout_<size>_mkobject, (bfd *));
427 DEFUN(NAME(aout
,mkobject
),(abfd
),
430 struct container
*rawptr
;
432 bfd_error
= system_call_error
;
434 /* Use an intermediate variable for clarity */
435 rawptr
= (struct container
*)bfd_zalloc (abfd
, sizeof (struct container
));
437 if (rawptr
== NULL
) {
438 bfd_error
= no_memory
;
442 set_tdata (abfd
, rawptr
);
443 exec_hdr (abfd
) = &(rawptr
->e
);
445 /* For simplicity's sake we just make all the sections right here. */
447 obj_textsec (abfd
) = (asection
*)NULL
;
448 obj_datasec (abfd
) = (asection
*)NULL
;
449 obj_bsssec (abfd
) = (asection
*)NULL
;
450 bfd_make_section (abfd
, ".text");
451 bfd_make_section (abfd
, ".data");
452 bfd_make_section (abfd
, ".bss");
459 *i aout_<size>_machine_type
461 Keep track of machine architecture and machine type for a.out's.
462 Return the machine_type for a particular arch&machine, or M_UNKNOWN
463 if that exact arch&machine can't be represented in a.out format.
465 If the architecture is understood, machine type 0 (default) should
466 always be understood.
468 *; PROTO(enum machine_type, aout_<size>_machine_type,
469 (enum bfd_architecture arch,
470 unsigned long machine));
474 DEFUN(NAME(aout
,machine_type
),(arch
, machine
),
475 enum bfd_architecture arch AND
476 unsigned long machine
)
478 enum machine_type arch_flags
;
480 arch_flags
= M_UNKNOWN
;
484 if (machine
== 0) arch_flags
= M_SPARC
;
489 case 0: arch_flags
= M_68010
; break;
490 case 68000: arch_flags
= M_UNKNOWN
; break;
491 case 68010: arch_flags
= M_68010
; break;
492 case 68020: arch_flags
= M_68020
; break;
493 default: arch_flags
= M_UNKNOWN
; break;
498 if (machine
== 0) arch_flags
= M_386
;
502 if (machine
== 0) arch_flags
= M_29K
;
506 arch_flags
= M_UNKNOWN
;
514 *i aout_<size>_set_arch_mach
516 Sets the architecture and the machine of the BFD to those values
517 supplied. Verifies that the format can support the architecture
520 *; PROTO(boolean, aout_<size>_set_arch_mach,
522 enum bfd_architecture,
523 unsigned long machine));
527 DEFUN(NAME(aout
,set_arch_mach
),(abfd
, arch
, machine
),
529 enum bfd_architecture arch AND
530 unsigned long machine
)
532 bfd_default_set_arch_mach(abfd
, arch
, machine
);
533 if (arch
!= bfd_arch_unknown
&&
534 NAME(aout
,machine_type
) (arch
, machine
) == M_UNKNOWN
)
535 return false; /* We can't represent this type */
536 return true; /* We're easy ... */
540 *i aout_<size>new_section_hook
542 Called by the BFD in response to a @code{bfd_make_section} request.
543 *; PROTO(boolean, aout_<size>_new_section_hook,
548 DEFUN(NAME(aout
,new_section_hook
),(abfd
, newsect
),
552 /* align to double at least */
553 newsect
->alignment_power
= 3;
555 if (bfd_get_format (abfd
) == bfd_object
) {
556 if (obj_textsec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".text")) {
557 obj_textsec(abfd
)= newsect
;
561 if (obj_datasec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".data")) {
562 obj_datasec(abfd
) = newsect
;
566 if (obj_bsssec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".bss")) {
567 obj_bsssec(abfd
) = newsect
;
572 /* We allow more than three sections internally */
577 DEFUN(NAME(aout
,set_section_contents
),(abfd
, section
, location
, offset
, count
),
585 bfd_size_type text_header_size
; /* exec_bytes_size if if included in
587 bfd_size_type text_size
;
588 if (abfd
->output_has_begun
== false)
589 { /* set by bfd.c handler */
590 switch (abfd
->direction
)
594 bfd_error
= invalid_operation
;
600 case write_direction
:
601 if ((obj_textsec (abfd
) == NULL
) || (obj_datasec (abfd
) == NULL
))
603 bfd_error
= invalid_operation
;
606 obj_textsec(abfd
)->size
=
607 align_power(obj_textsec(abfd
)->size
,
608 obj_textsec(abfd
)->alignment_power
);
609 text_size
= obj_textsec (abfd
)->size
;
610 /* Rule (heuristic) for when to pad to a new page.
611 * Note that there are (at least) two ways demand-paged
612 * (ZMAGIC) files have been handled. Most Berkeley-based systems
613 * start the text segment at (PAGE_SIZE). However, newer
614 * versions of SUNOS start the text segment right after the
615 * exec header; the latter is counted in the text segment size,
616 * and is paged in by the kernel with the rest of the text. */
617 if (!(abfd
->flags
& D_PAGED
))
618 { /* Not demand-paged. */
619 obj_textsec(abfd
)->filepos
= adata(abfd
)->exec_bytes_size
;
621 else if (obj_textsec(abfd
)->vma
% adata(abfd
)->page_size
622 < adata(abfd
)->exec_bytes_size
)
623 { /* Old-style demand-paged. */
624 obj_textsec(abfd
)->filepos
= adata(abfd
)->page_size
;
627 { /* Sunos-style demand-paged. */
628 obj_textsec(abfd
)->filepos
= adata(abfd
)->exec_bytes_size
;
629 text_size
+= adata(abfd
)->exec_bytes_size
;
631 text_end
= obj_textsec(abfd
)->size
+ obj_textsec(abfd
)->filepos
;
632 if (abfd
->flags
& (D_PAGED
|WP_TEXT
))
634 bfd_size_type text_pad
=
635 BFD_ALIGN(text_size
, adata(abfd
)->segment_size
)
637 text_end
+= text_pad
;
638 obj_textsec(abfd
)->size
+= text_pad
;
640 obj_datasec(abfd
)->filepos
= text_end
;
641 obj_datasec(abfd
)->size
=
642 align_power(obj_datasec(abfd
)->size
,
643 obj_datasec(abfd
)->alignment_power
);
647 /* regardless, once we know what we're doing, we might as well get going */
648 if (section
!= obj_bsssec(abfd
))
650 bfd_seek (abfd
, section
->filepos
+ offset
, SEEK_SET
);
653 return (bfd_write ((PTR
)location
, 1, count
, abfd
) == count
) ?
661 /* Classify stabs symbols */
663 #define sym_in_text_section(sym) \
664 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
666 #define sym_in_data_section(sym) \
667 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
669 #define sym_in_bss_section(sym) \
670 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
672 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
673 zero in the "value" field. Nonzeroes there are fortrancommon
675 #define sym_is_undefined(sym) \
676 ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
678 /* Symbol is a global definition if N_EXT is on and if it has
679 a nonzero type field. */
680 #define sym_is_global_defn(sym) \
681 (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
683 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
685 #define sym_is_debugger_info(sym) \
686 ((sym)->type & ~(N_EXT | N_TYPE))
688 #define sym_is_fortrancommon(sym) \
689 (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
691 /* Symbol is absolute if it has N_ABS set */
692 #define sym_is_absolute(sym) \
693 (((sym)->type & N_TYPE)== N_ABS)
696 #define sym_is_indirect(sym) \
697 (((sym)->type & N_ABS)== N_ABS)
699 /* Only in their own functions for ease of debugging; when sym flags have
700 stabilised these should be inlined into their (single) caller */
703 DEFUN(translate_from_native_sym_flags
,(sym_pointer
, cache_ptr
, abfd
),
704 struct external_nlist
*sym_pointer AND
705 aout_symbol_type
*cache_ptr AND
708 switch (cache_ptr
->type
& N_TYPE
) {
714 char *copy
= bfd_alloc(abfd
, strlen(cache_ptr
->symbol
.name
)+1);
716 arelent_chain
*reloc
= (arelent_chain
*)bfd_alloc(abfd
, sizeof(arelent_chain
));
717 strcpy(copy
, cache_ptr
->symbol
.name
);
718 section
= bfd_get_section_by_name (abfd
, copy
);
720 section
= bfd_make_section(abfd
,copy
);
722 switch ( (cache_ptr
->type
& N_TYPE
) ) {
724 section
->flags
= SEC_CONSTRUCTOR
;
725 reloc
->relent
.section
= (asection
*)NULL
;
726 cache_ptr
->symbol
.section
= (asection
*)NULL
;
729 section
->flags
= SEC_CONSTRUCTOR_TEXT
;
730 reloc
->relent
.section
= (asection
*)obj_textsec(abfd
);
731 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
734 section
->flags
= SEC_CONSTRUCTOR_DATA
;
735 reloc
->relent
.section
= (asection
*)obj_datasec(abfd
);
736 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
739 section
->flags
= SEC_CONSTRUCTOR_BSS
;
740 reloc
->relent
.section
= (asection
*)obj_bsssec(abfd
);
741 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
744 cache_ptr
->symbol
.section
= reloc
->relent
.section
;
745 reloc
->relent
.addend
= cache_ptr
->symbol
.value
;
747 /* We modify the symbol to belong to a section depending upon the
748 name of the symbol - probably __CTOR__ or __DTOR__ but we don't
749 really care, and add to the size of the section to contain a
750 pointer to the symbol. Build a reloc entry to relocate to this
751 symbol attached to this section. */
754 section
->reloc_count
++;
755 section
->alignment_power
= 2;
756 reloc
->relent
.sym_ptr_ptr
= (asymbol
**)NULL
;
757 reloc
->next
= section
->constructor_chain
;
758 section
->constructor_chain
= reloc
;
759 reloc
->relent
.address
= section
->size
;
760 section
->size
+= sizeof(int *);
762 reloc
->relent
.howto
= howto_table_ext
+CTOR_TABLE_RELOC_IDX
;
763 cache_ptr
->symbol
.flags
|= BSF_DEBUGGING
| BSF_CONSTRUCTOR
;
767 if (cache_ptr
->type
== N_WARNING
)
769 /* This symbol is the text of a warning message, the next symbol
770 is the symbol to associate the warning with */
771 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
| BSF_WARNING
;
772 cache_ptr
->symbol
.value
= (bfd_vma
)((cache_ptr
+1));
773 /* We furgle with the next symbol in place. We don't want it to be undefined, we'll trample the type */
774 (sym_pointer
+1)->e_type
[0] = 0xff;
777 if ((cache_ptr
->type
| N_EXT
) == (N_INDR
| N_EXT
)) {
778 /* Two symbols in a row for an INDR message. The first symbol
779 contains the name we will match, the second symbol contains the
780 name the first name is translated into. It is supplied to us
781 undefined. This is good, since we want to pull in any files which
783 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
| BSF_INDIRECT
;
784 cache_ptr
->symbol
.value
= (bfd_vma
)((cache_ptr
+1));
789 if (sym_is_debugger_info (cache_ptr
)) {
790 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
;
791 /* Work out the section correct for this symbol */
792 switch (cache_ptr
->type
& N_TYPE
)
796 cache_ptr
->symbol
.section
= obj_textsec (abfd
);
797 cache_ptr
->symbol
.value
-= obj_textsec(abfd
)->vma
;
800 cache_ptr
->symbol
.value
-= obj_datasec(abfd
)->vma
;
801 cache_ptr
->symbol
.section
= obj_datasec (abfd
);
804 cache_ptr
->symbol
.section
= obj_bsssec (abfd
);
805 cache_ptr
->symbol
.value
-= obj_bsssec(abfd
)->vma
;
809 cache_ptr
->symbol
.section
= 0;
815 if (sym_is_fortrancommon (cache_ptr
))
817 cache_ptr
->symbol
.flags
= BSF_FORT_COMM
;
818 cache_ptr
->symbol
.section
= (asection
*)NULL
;
821 if (sym_is_undefined (cache_ptr
)) {
822 cache_ptr
->symbol
.flags
= BSF_UNDEFINED
;
824 else if (sym_is_global_defn (cache_ptr
)) {
825 cache_ptr
->symbol
.flags
= BSF_GLOBAL
| BSF_EXPORT
;
828 else if (sym_is_absolute (cache_ptr
)) {
829 cache_ptr
->symbol
.flags
= BSF_ABSOLUTE
;
832 cache_ptr
->symbol
.flags
= BSF_LOCAL
;
835 /* In a.out, the value of a symbol is always relative to the
836 * start of the file, if this is a data symbol we'll subtract
837 * the size of the text section to get the section relative
838 * value. If this is a bss symbol (which would be strange)
839 * we'll subtract the size of the previous two sections
840 * to find the section relative address.
843 if (sym_in_text_section (cache_ptr
)) {
844 cache_ptr
->symbol
.value
-= obj_textsec(abfd
)->vma
;
845 cache_ptr
->symbol
.section
= obj_textsec (abfd
);
847 else if (sym_in_data_section (cache_ptr
)){
848 cache_ptr
->symbol
.value
-= obj_datasec(abfd
)->vma
;
849 cache_ptr
->symbol
.section
= obj_datasec (abfd
);
851 else if (sym_in_bss_section(cache_ptr
)) {
852 cache_ptr
->symbol
.section
= obj_bsssec (abfd
);
853 cache_ptr
->symbol
.value
-= obj_bsssec(abfd
)->vma
;
856 cache_ptr
->symbol
.section
= (asection
*)NULL
;
857 cache_ptr
->symbol
.flags
|= BSF_ABSOLUTE
;
865 DEFUN(translate_to_native_sym_flags
,(sym_pointer
, cache_ptr
, abfd
),
866 struct external_nlist
*sym_pointer AND
867 asymbol
*cache_ptr AND
870 bfd_vma value
= cache_ptr
->value
;
872 if (bfd_get_section(cache_ptr
)) {
873 if (bfd_get_output_section(cache_ptr
) == obj_bsssec (abfd
)) {
874 sym_pointer
->e_type
[0] |= N_BSS
;
876 else if (bfd_get_output_section(cache_ptr
) == obj_datasec (abfd
)) {
877 sym_pointer
->e_type
[0] |= N_DATA
;
879 else if (bfd_get_output_section(cache_ptr
) == obj_textsec (abfd
)) {
880 sym_pointer
->e_type
[0] |= N_TEXT
;
883 bfd_error_vector
.nonrepresentable_section(abfd
,
884 bfd_get_output_section(cache_ptr
)->name
);
886 /* Turn the symbol from section relative to absolute again */
889 cache_ptr
->section
->output_section
->vma
890 + cache_ptr
->section
->output_offset
;
893 sym_pointer
->e_type
[0] |= N_ABS
;
895 if (cache_ptr
->flags
& (BSF_WARNING
)) {
896 (sym_pointer
+1)->e_type
[0] = 1;
898 if (cache_ptr
->flags
& (BSF_FORT_COMM
| BSF_UNDEFINED
)) {
899 sym_pointer
->e_type
[0] = (N_UNDF
| N_EXT
);
902 if (cache_ptr
->flags
& BSF_ABSOLUTE
) {
903 sym_pointer
->e_type
[0] |= N_ABS
;
906 if (cache_ptr
->flags
& (BSF_GLOBAL
| BSF_EXPORT
)) {
907 sym_pointer
->e_type
[0] |= N_EXT
;
909 if (cache_ptr
->flags
& BSF_DEBUGGING
) {
910 sym_pointer
->e_type
[0]= ((aout_symbol_type
*)cache_ptr
)->type
;
913 PUT_WORD(abfd
, value
, sym_pointer
->e_value
);
916 /* Native-level interface to symbols. */
918 /* We read the symbols into a buffer, which is discarded when this
919 function exits. We read the strings into a buffer large enough to
920 hold them all plus all the cached symbol entries. */
923 DEFUN(NAME(aout
,make_empty_symbol
),(abfd
),
926 aout_symbol_type
*new =
927 (aout_symbol_type
*)bfd_zalloc (abfd
, sizeof (aout_symbol_type
));
928 new->symbol
.the_bfd
= abfd
;
934 DEFUN(NAME(aout
,slurp_symbol_table
),(abfd
),
937 bfd_size_type symbol_size
;
938 bfd_size_type string_size
;
939 unsigned char string_chars
[BYTES_IN_WORD
];
940 struct external_nlist
*syms
;
942 aout_symbol_type
*cached
;
944 /* If there's no work to be done, don't do any */
945 if (obj_aout_symbols (abfd
) != (aout_symbol_type
*)NULL
) return true;
946 symbol_size
= exec_hdr(abfd
)->a_syms
;
947 if (symbol_size
== 0) {
948 bfd_error
= no_symbols
;
952 bfd_seek (abfd
, obj_str_filepos (abfd
), SEEK_SET
);
953 if (bfd_read ((PTR
)string_chars
, BYTES_IN_WORD
, 1, abfd
) != BYTES_IN_WORD
)
955 string_size
= GET_WORD (abfd
, string_chars
);
957 strings
=(char *) bfd_alloc(abfd
, string_size
+ 1);
958 cached
= (aout_symbol_type
*)
959 bfd_zalloc(abfd
, (bfd_size_type
)(bfd_get_symcount (abfd
) * sizeof(aout_symbol_type
)));
961 /* malloc this, so we can free it if simply. The symbol caching
962 might want to allocate onto the bfd's obstack */
963 syms
= (struct external_nlist
*) bfd_xmalloc(symbol_size
);
964 bfd_seek (abfd
, obj_sym_filepos (abfd
), SEEK_SET
);
965 if (bfd_read ((PTR
)syms
, 1, symbol_size
, abfd
) != symbol_size
) {
967 if (syms
) free (syms
);
968 if (cached
) bfd_release (abfd
, cached
);
969 if (strings
)bfd_release (abfd
, strings
);
973 bfd_seek (abfd
, obj_str_filepos (abfd
), SEEK_SET
);
974 if (bfd_read ((PTR
)strings
, 1, string_size
, abfd
) != string_size
) {
978 /* OK, now walk the new symtable, cacheing symbol properties */
980 register struct external_nlist
*sym_pointer
;
981 register struct external_nlist
*sym_end
= syms
+ bfd_get_symcount (abfd
);
982 register aout_symbol_type
*cache_ptr
= cached
;
984 /* Run through table and copy values */
985 for (sym_pointer
= syms
, cache_ptr
= cached
;
986 sym_pointer
< sym_end
; sym_pointer
++, cache_ptr
++)
988 bfd_vma x
= GET_WORD(abfd
, sym_pointer
->e_strx
);
989 cache_ptr
->symbol
.the_bfd
= abfd
;
991 cache_ptr
->symbol
.name
= x
+ strings
;
993 cache_ptr
->symbol
.name
= (char *)NULL
;
995 cache_ptr
->symbol
.value
= GET_SWORD(abfd
, sym_pointer
->e_value
);
996 cache_ptr
->desc
= bfd_get_16(abfd
, sym_pointer
->e_desc
);
997 cache_ptr
->other
=bfd_get_8(abfd
, sym_pointer
->e_other
);
998 cache_ptr
->type
= bfd_get_8(abfd
, sym_pointer
->e_type
);
999 cache_ptr
->symbol
.udata
= 0;
1000 translate_from_native_sym_flags (sym_pointer
, cache_ptr
, abfd
);
1004 obj_aout_symbols (abfd
) = cached
;
1012 DEFUN(NAME(aout
,write_syms
),(abfd
),
1015 unsigned int count
;
1016 asymbol
**generic
= bfd_get_outsymbols (abfd
);
1018 bfd_size_type stindex
= BYTES_IN_WORD
; /* initial string length */
1020 for (count
= 0; count
< bfd_get_symcount (abfd
); count
++) {
1021 asymbol
*g
= generic
[count
];
1022 struct external_nlist nsp
;
1025 unsigned int length
= strlen(g
->name
) +1;
1026 PUT_WORD (abfd
, stindex
, (unsigned char *)nsp
.e_strx
);
1030 PUT_WORD (abfd
, 0, (unsigned char *)nsp
.e_strx
);
1033 if (g
->the_bfd
->xvec
->flavour
== abfd
->xvec
->flavour
)
1035 bfd_h_put_16(abfd
, aout_symbol(g
)->desc
, nsp
.e_desc
);
1036 bfd_h_put_8(abfd
, aout_symbol(g
)->other
, nsp
.e_other
);
1037 bfd_h_put_8(abfd
, aout_symbol(g
)->type
, nsp
.e_type
);
1041 bfd_h_put_16(abfd
,0, nsp
.e_desc
);
1042 bfd_h_put_8(abfd
, 0, nsp
.e_other
);
1043 bfd_h_put_8(abfd
, 0, nsp
.e_type
);
1046 translate_to_native_sym_flags (&nsp
, g
, abfd
);
1048 bfd_write((PTR
)&nsp
,1,EXTERNAL_NLIST_SIZE
, abfd
);
1051 /* Now output the strings. Be sure to put string length into correct
1052 byte ordering before writing it. */
1054 char buffer
[BYTES_IN_WORD
];
1055 PUT_WORD (abfd
, stindex
, (unsigned char *)buffer
);
1057 bfd_write((PTR
)buffer
, 1, BYTES_IN_WORD
, abfd
);
1059 generic
= bfd_get_outsymbols(abfd
);
1060 for (count
= 0; count
< bfd_get_symcount(abfd
); count
++)
1062 asymbol
*g
= *(generic
++);
1066 size_t length
= strlen(g
->name
)+1;
1067 bfd_write((PTR
)g
->name
, 1, length
, abfd
);
1069 if ((g
->flags
& BSF_FAKE
)==0) {
1070 g
->KEEPIT
= (KEEPITTYPE
) count
;
1078 DEFUN(NAME(aout
,get_symtab
),(abfd
, location
),
1082 unsigned int counter
= 0;
1083 aout_symbol_type
*symbase
;
1085 if (!NAME(aout
,slurp_symbol_table
)(abfd
)) return 0;
1087 for (symbase
= obj_aout_symbols(abfd
); counter
++ < bfd_get_symcount (abfd
);)
1088 *(location
++) = (asymbol
*)( symbase
++);
1090 return bfd_get_symcount(abfd
);
1094 /* Standard reloc stuff */
1095 /* Output standard relocation information to a file in target byte order. */
1098 DEFUN(NAME(aout
,swap_std_reloc_out
),(abfd
, g
, natptr
),
1101 struct reloc_std_external
*natptr
)
1105 unsigned int r_length
;
1107 int r_baserel
, r_jmptable
, r_relative
;
1108 unsigned int r_addend
;
1110 PUT_WORD(abfd
, g
->address
, natptr
->r_address
);
1112 r_length
= g
->howto
->size
; /* Size as a power of two */
1113 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
1114 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
1119 r_addend
= g
->addend
; /* Start here, see how it goes */
1121 /* name was clobbered by aout_write_syms to be symbol index */
1123 if (g
->sym_ptr_ptr
!= NULL
)
1125 if ((*(g
->sym_ptr_ptr
))->section
) {
1126 /* put the section offset into the addend for output */
1127 r_addend
+= (*(g
->sym_ptr_ptr
))->section
->vma
;
1130 r_index
= ((*(g
->sym_ptr_ptr
))->KEEPIT
);
1135 if (g
->section
== NULL
) {
1136 /* It is possible to have a reloc with nothing, we generate an
1139 r_index
= N_ABS
| N_EXT
;
1141 else if(g
->section
->output_section
== obj_textsec(abfd
)) {
1142 r_index
= N_TEXT
| N_EXT
;
1143 r_addend
+= g
->section
->output_section
->vma
;
1145 else if (g
->section
->output_section
== obj_datasec(abfd
)) {
1146 r_index
= N_DATA
| N_EXT
;
1147 r_addend
+= g
->section
->output_section
->vma
;
1149 else if (g
->section
->output_section
== obj_bsssec(abfd
)) {
1150 r_index
= N_BSS
| N_EXT
;
1151 r_addend
+= g
->section
->output_section
->vma
;
1155 r_index
= N_ABS
| N_EXT
;
1159 /* now the fun stuff */
1160 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1161 natptr
->r_index
[0] = r_index
>> 16;
1162 natptr
->r_index
[1] = r_index
>> 8;
1163 natptr
->r_index
[2] = r_index
;
1165 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
1166 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
1167 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
1168 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
1169 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
1170 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
1172 natptr
->r_index
[2] = r_index
>> 16;
1173 natptr
->r_index
[1] = r_index
>> 8;
1174 natptr
->r_index
[0] = r_index
;
1176 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
1177 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
1178 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
1179 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
1180 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
1181 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
1186 /* Extended stuff */
1187 /* Output extended relocation information to a file in target byte order. */
1190 DEFUN(NAME(aout
,swap_ext_reloc_out
),(abfd
, g
, natptr
),
1193 register struct reloc_ext_external
*natptr
)
1197 unsigned int r_type
;
1198 unsigned int r_addend
;
1200 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
1202 /* Find a type in the output format which matches the input howto -
1203 at the moment we assume input format == output format FIXME!! */
1204 r_type
= (enum reloc_type
) g
->howto
->type
;
1206 r_addend
= g
->addend
; /* Start here, see how it goes */
1208 /* name was clobbered by aout_write_syms to be symbol index*/
1210 if (g
->sym_ptr_ptr
!= NULL
)
1212 if ((*(g
->sym_ptr_ptr
))->section
) {
1213 /* put the section offset into the addend for output */
1214 r_addend
+= (*(g
->sym_ptr_ptr
))->section
->vma
;
1217 r_index
= stoi((*(g
->sym_ptr_ptr
))->KEEPIT
);
1222 if (g
->section
== NULL
) {
1224 r_index
= N_ABS
| N_EXT
;
1226 else if(g
->section
->output_section
== obj_textsec(abfd
)) {
1227 r_index
= N_TEXT
| N_EXT
;
1228 r_addend
+= g
->section
->output_section
->vma
;
1230 else if (g
->section
->output_section
== obj_datasec(abfd
)) {
1231 r_index
= N_DATA
| N_EXT
;
1232 r_addend
+= g
->section
->output_section
->vma
;
1234 else if (g
->section
->output_section
== obj_bsssec(abfd
)) {
1235 r_index
= N_BSS
| N_EXT
;
1236 r_addend
+= g
->section
->output_section
->vma
;
1240 r_index
= N_ABS
| N_EXT
;
1244 /* now the fun stuff */
1245 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1246 natptr
->r_index
[0] = r_index
>> 16;
1247 natptr
->r_index
[1] = r_index
>> 8;
1248 natptr
->r_index
[2] = r_index
;
1250 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
1251 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
1253 natptr
->r_index
[2] = r_index
>> 16;
1254 natptr
->r_index
[1] = r_index
>> 8;
1255 natptr
->r_index
[0] = r_index
;
1257 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
1258 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
1261 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
1264 #define MOVE_ADDRESS(ad) \
1266 cache_ptr->sym_ptr_ptr = symbols + r_index; \
1267 cache_ptr->section = (asection *)NULL; \
1268 cache_ptr->addend = ad; \
1270 cache_ptr->sym_ptr_ptr = (asymbol **)NULL; \
1271 switch (r_index) { \
1273 case N_TEXT | N_EXT: \
1274 cache_ptr->section = obj_textsec(abfd); \
1275 cache_ptr->addend = ad - su->textsec->vma; \
1278 case N_DATA | N_EXT: \
1279 cache_ptr->section = obj_datasec(abfd); \
1280 cache_ptr->addend = ad - su->datasec->vma; \
1283 case N_BSS | N_EXT: \
1284 cache_ptr->section = obj_bsssec(abfd); \
1285 cache_ptr->addend = ad - su->bsssec->vma; \
1288 case N_ABS | N_EXT: \
1289 cache_ptr->section = NULL; /* No section */ \
1290 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1294 cache_ptr->section = NULL; /* No section */ \
1295 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1302 DEFUN(NAME(aout
,swap_ext_reloc_in
), (abfd
, bytes
, cache_ptr
, symbols
),
1304 struct reloc_ext_external
*bytes AND
1305 arelent
*cache_ptr AND
1310 unsigned int r_type
;
1311 struct aoutdata
*su
= (struct aoutdata
*)(abfd
->tdata
);
1313 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
1315 /* now the fun stuff */
1316 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1317 r_index
= (bytes
->r_index
[0] << 16)
1318 | (bytes
->r_index
[1] << 8)
1319 | bytes
->r_index
[2];
1320 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
1321 r_type
= (bytes
->r_type
[0] & RELOC_EXT_BITS_TYPE_BIG
)
1322 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
1324 r_index
= (bytes
->r_index
[2] << 16)
1325 | (bytes
->r_index
[1] << 8)
1326 | bytes
->r_index
[0];
1327 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_EXT_BITS_EXTERN_LITTLE
));
1328 r_type
= (bytes
->r_type
[0] & RELOC_EXT_BITS_TYPE_LITTLE
)
1329 >> RELOC_EXT_BITS_TYPE_SH_LITTLE
;
1332 cache_ptr
->howto
= howto_table_ext
+ r_type
;
1333 MOVE_ADDRESS(GET_SWORD(abfd
,bytes
->r_addend
));
1337 DEFUN(NAME(aout
,swap_std_reloc_in
), (abfd
, bytes
, cache_ptr
, symbols
),
1339 struct reloc_std_external
*bytes AND
1340 arelent
*cache_ptr AND
1345 unsigned int r_length
;
1347 int r_baserel
, r_jmptable
, r_relative
;
1348 struct aoutdata
*su
= (struct aoutdata
*)(abfd
->tdata
);
1350 cache_ptr
->address
= (int32_type
)(bfd_h_get_32 (abfd
, bytes
->r_address
));
1352 /* now the fun stuff */
1353 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1354 r_index
= (bytes
->r_index
[0] << 16)
1355 | (bytes
->r_index
[1] << 8)
1356 | bytes
->r_index
[2];
1357 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_EXTERN_BIG
));
1358 r_pcrel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_PCREL_BIG
));
1359 r_baserel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_BASEREL_BIG
));
1360 r_jmptable
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
1361 r_relative
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
1362 r_length
= (bytes
->r_type
[0] & RELOC_STD_BITS_LENGTH_BIG
)
1363 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
1365 r_index
= (bytes
->r_index
[2] << 16)
1366 | (bytes
->r_index
[1] << 8)
1367 | bytes
->r_index
[0];
1368 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_EXTERN_LITTLE
));
1369 r_pcrel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_PCREL_LITTLE
));
1370 r_baserel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_BASEREL_LITTLE
));
1371 r_jmptable
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_JMPTABLE_LITTLE
));
1372 r_relative
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_RELATIVE_LITTLE
));
1373 r_length
= (bytes
->r_type
[0] & RELOC_STD_BITS_LENGTH_LITTLE
)
1374 >> RELOC_STD_BITS_LENGTH_SH_LITTLE
;
1377 cache_ptr
->howto
= howto_table_std
+ r_length
+ 4 * r_pcrel
;
1378 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
1386 DEFUN(NAME(aout
,slurp_reloc_table
),(abfd
, asect
, symbols
),
1392 bfd_size_type reloc_size
;
1394 arelent
*reloc_cache
;
1397 if (asect
->relocation
) return true;
1399 if (asect
->flags
& SEC_CONSTRUCTOR
) return true;
1401 if (asect
== obj_datasec (abfd
)) {
1402 reloc_size
= exec_hdr(abfd
)->a_drsize
;
1406 if (asect
== obj_textsec (abfd
)) {
1407 reloc_size
= exec_hdr(abfd
)->a_trsize
;
1411 bfd_error
= invalid_operation
;
1415 bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
);
1416 each_size
= obj_reloc_entry_size (abfd
);
1418 count
= reloc_size
/ each_size
;
1421 reloc_cache
= (arelent
*) bfd_zalloc (abfd
, (size_t)(count
* sizeof
1425 bfd_error
= no_memory
;
1429 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
1431 bfd_release (abfd
, reloc_cache
);
1435 if (bfd_read (relocs
, 1, reloc_size
, abfd
) != reloc_size
) {
1436 bfd_release (abfd
, relocs
);
1437 bfd_release (abfd
, reloc_cache
);
1438 bfd_error
= system_call_error
;
1442 if (each_size
== RELOC_EXT_SIZE
) {
1443 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
1444 unsigned int counter
= 0;
1445 arelent
*cache_ptr
= reloc_cache
;
1447 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++) {
1448 NAME(aout
,swap_ext_reloc_in
)(abfd
, rptr
, cache_ptr
, symbols
);
1451 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
1452 unsigned int counter
= 0;
1453 arelent
*cache_ptr
= reloc_cache
;
1455 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++) {
1456 NAME(aout
,swap_std_reloc_in
)(abfd
, rptr
, cache_ptr
, symbols
);
1461 bfd_release (abfd
,relocs
);
1462 asect
->relocation
= reloc_cache
;
1463 asect
->reloc_count
= count
;
1469 /* Write out a relocation section into an object file. */
1472 DEFUN(NAME(aout
,squirt_out_relocs
),(abfd
, section
),
1477 unsigned char *native
, *natptr
;
1480 unsigned int count
= section
->reloc_count
;
1483 if (count
== 0) return true;
1485 each_size
= obj_reloc_entry_size (abfd
);
1486 natsize
= each_size
* count
;
1487 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
1489 bfd_error
= no_memory
;
1493 generic
= section
->orelocation
;
1495 if (each_size
== RELOC_EXT_SIZE
)
1497 for (natptr
= native
;
1499 --count
, natptr
+= each_size
, ++generic
)
1500 NAME(aout
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*)natptr
);
1504 for (natptr
= native
;
1506 --count
, natptr
+= each_size
, ++generic
)
1507 NAME(aout
,swap_std_reloc_out
)(abfd
, *generic
, (struct reloc_std_external
*)natptr
);
1510 if ( bfd_write ((PTR
) native
, 1, natsize
, abfd
) != natsize
) {
1511 bfd_release(abfd
, native
);
1514 bfd_release (abfd
, native
);
1519 /* This is stupid. This function should be a boolean predicate */
1521 DEFUN(NAME(aout
,canonicalize_reloc
),(abfd
, section
, relptr
, symbols
),
1524 arelent
**relptr AND
1527 arelent
*tblptr
= section
->relocation
;
1530 if (!(tblptr
|| NAME(aout
,slurp_reloc_table
)(abfd
, section
, symbols
)))
1533 if (section
->flags
& SEC_CONSTRUCTOR
) {
1534 arelent_chain
*chain
= section
->constructor_chain
;
1535 for (count
= 0; count
< section
->reloc_count
; count
++) {
1536 *relptr
++ = &chain
->relent
;
1537 chain
= chain
->next
;
1541 tblptr
= section
->relocation
;
1542 if (!tblptr
) return 0;
1544 for (count
= 0; count
++ < section
->reloc_count
;)
1546 *relptr
++ = tblptr
++;
1551 return section
->reloc_count
;
1555 DEFUN(NAME(aout
,get_reloc_upper_bound
),(abfd
, asect
),
1559 if (bfd_get_format (abfd
) != bfd_object
) {
1560 bfd_error
= invalid_operation
;
1563 if (asect
->flags
& SEC_CONSTRUCTOR
) {
1564 return (sizeof (arelent
*) * (asect
->reloc_count
+1));
1568 if (asect
== obj_datasec (abfd
))
1569 return (sizeof (arelent
*) *
1570 ((exec_hdr(abfd
)->a_drsize
/ obj_reloc_entry_size (abfd
))
1573 if (asect
== obj_textsec (abfd
))
1574 return (sizeof (arelent
*) *
1575 ((exec_hdr(abfd
)->a_trsize
/ obj_reloc_entry_size (abfd
))
1578 bfd_error
= invalid_operation
;
1584 DEFUN(NAME(aout
,get_symtab_upper_bound
),(abfd
),
1587 if (!NAME(aout
,slurp_symbol_table
)(abfd
)) return 0;
1589 return (bfd_get_symcount (abfd
)+1) * (sizeof (aout_symbol_type
*));
1592 DEFUN(NAME(aout
,get_lineno
),(ignore_abfd
, ignore_symbol
),
1593 bfd
*ignore_abfd AND
1594 asymbol
*ignore_symbol
)
1596 return (alent
*)NULL
;
1601 DEFUN(NAME(aout
,print_symbol
),(ignore_abfd
, afile
, symbol
, how
),
1602 bfd
*ignore_abfd AND
1605 bfd_print_symbol_type how
)
1607 FILE *file
= (FILE *)afile
;
1610 case bfd_print_symbol_name
:
1612 fprintf(file
,"%s", symbol
->name
);
1614 case bfd_print_symbol_more
:
1615 fprintf(file
,"%4x %2x %2x",(unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1616 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1617 (unsigned)(aout_symbol(symbol
)->type
));
1619 case bfd_print_symbol_all
:
1621 CONST
char *section_name
= symbol
->section
== (asection
*)NULL
?
1622 (CONST
char *)"*abs" : symbol
->section
->name
;
1624 bfd_print_symbol_vandf((PTR
)file
,symbol
);
1626 fprintf(file
," %-5s %04x %02x %02x",
1628 (unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1629 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1630 (unsigned)(aout_symbol(symbol
)->type
& 0xff));
1632 fprintf(file
," %s", symbol
->name
);
1635 case bfd_print_symbol_nm
:
1637 int section_code
= bfd_decode_symclass (symbol
);
1639 if (section_code
== 'U')
1641 else if (symbol
->section
!= (asection
*)NULL
)
1642 fprintf_vma(file
, symbol
->value
+symbol
->section
->vma
);
1644 fprintf_vma(file
, symbol
->value
);
1645 if (section_code
== '?')
1647 int type_code
= aout_symbol(symbol
)->type
& 0xff;
1648 char *stab_name
= aout_stab_name(type_code
);
1650 if (stab_name
== NULL
)
1652 sprintf(buf
, "(%d)", type_code
);
1655 fprintf(file
," - %02x %04x %5s",
1656 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1657 (unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1661 fprintf(file
," %c", section_code
);
1663 fprintf(file
," %s", symbol
->name
);
1670 provided a BFD, a section and an offset into the section, calculate
1671 and return the name of the source file and the line nearest to the
1676 DEFUN(NAME(aout
,find_nearest_line
),(abfd
,
1684 asection
*section AND
1685 asymbol
**symbols AND
1687 CONST
char **filename_ptr AND
1688 CONST
char **functionname_ptr AND
1689 unsigned int *line_ptr
)
1691 /* Run down the file looking for the filename, function and linenumber */
1693 static char buffer
[100];
1694 static char filename_buffer
[200];
1695 bfd_vma high_line_vma
= ~0;
1696 bfd_vma low_func_vma
= 0;
1698 *filename_ptr
= abfd
->filename
;
1699 *functionname_ptr
= 0;
1701 if (symbols
!= (asymbol
**)NULL
) {
1702 for (p
= symbols
; *p
; p
++) {
1703 aout_symbol_type
*q
= (aout_symbol_type
*)(*p
);
1707 *filename_ptr
= q
->symbol
.name
;
1708 /* Look ahead to next symbol to check if that too is an N_SO. */
1712 q
= (aout_symbol_type
*)(*p
);
1713 if (q
->type
!= N_SO
)
1716 /* Found a second N_SO First is directory; second is filename. */
1717 if (q
->symbol
.name
[0] == '/')
1718 *filename_ptr
= q
->symbol
.name
;
1721 sprintf(filename_buffer
, "%.140s%.50s",
1722 *filename_ptr
, q
->symbol
.name
);
1723 *filename_ptr
= filename_buffer
;
1726 if (obj_textsec(abfd
) != section
) {
1734 /* We'll keep this if it resolves nearer than the one we have already */
1735 if (q
->symbol
.value
>= offset
&&
1736 q
->symbol
.value
< high_line_vma
) {
1737 *line_ptr
= q
->desc
;
1738 high_line_vma
= q
->symbol
.value
;
1743 /* We'll keep this if it is nearer than the one we have already */
1744 if (q
->symbol
.value
>= low_func_vma
&&
1745 q
->symbol
.value
<= offset
) {
1746 low_func_vma
= q
->symbol
.value
;
1747 func
= (asymbol
*)q
;
1749 if (*line_ptr
&& func
) {
1750 CONST
char *function
= func
->name
;
1752 strncpy(buffer
, function
, sizeof(buffer
)-1);
1753 buffer
[sizeof(buffer
)-1] = 0;
1754 /* Have to remove : stuff */
1755 p
= strchr(buffer
,':');
1756 if (p
!= NULL
) { *p
= '\0'; }
1757 *functionname_ptr
= buffer
;
1772 DEFUN(NAME(aout
,sizeof_headers
),(abfd
, execable
),
1776 return adata(abfd
)->exec_bytes_size
;