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 and
36 @code{demo64} for a demonstration of a 64 bit a.out format.
38 The base file @code{aoutx.h} defines general mechanisms for reading
39 and writing records to and from disk, and various other methods which
40 BFD requires. It is included by @code{aout32.c} and @code{aout64.c} to
41 form the names aout_32_swap_exec_header_in,
42 aout_64_swap_exec_header_in, etc.
44 As an example, this is what goes on to make the back end for a sun4, from aout32.c
54 aout_32_canonicalize_reloc
55 aout_32_find_nearest_line
57 aout_32_get_reloc_upper_bound
65 #define TARGET_NAME "a.out-sunos-big"
66 #define VECNAME sunos_big_vec
69 requires all the names from aout32.c, and produces the jump vector
75 The file host-aout.c is a special case. It is for a large set of hosts
76 that use ``more or less standard'' a.out files, and for which cross-debugging
77 is not interesting. It uses the standard 32-bit a.out support routines,
78 but determines the file offsets and addresses of the text, data,
79 and BSS sections, the machine architecture and machine type,
80 and the entry point address, in a host-dependent manner. Once these
81 values have been determined, generic code is used to handle the
84 When porting it to run on a new system, you must supply:
88 HOST_MACHINE_ARCH (optional)
89 HOST_MACHINE_MACHINE (optional)
93 in the file ../include/sys/h-XXX.h (for your host). These values, plus
94 the structures and macros defined in <a.out.h> on your host system, will
95 produce a BFD target that will access ordinary a.out files on your host.
97 To configure a new machine to use host-aout.c, specify:
99 TDEFINES = -DDEFAULT_VECTOR=host_aout_big_vec
100 TDEPFILES= host-aout.o trad-core.o
102 in the config/t-XXX file, and modify configure.in to use the
103 t-XXX file (by setting "bfd_target=XXX") when your configuration is
109 #define KEEPITTYPE int
113 #include <ansidecl.h>
115 struct external_exec
;
119 #include "stab.gnu.h"
122 void (*bfd_error_trap
)();
125 @subsection relocations
126 The file @code{aoutx.h} caters for both the @emph{standard} and
127 @emph{extended} forms of a.out relocation records.
129 The standard records are characterised by containing only an address,
130 a symbol index and a type field. The extended records (used on 29ks
131 and sparcs) also have a full integer for an addend.
133 #define CTOR_TABLE_RELOC_IDX 2
135 /* start-sanitize-v9 */
136 /* Provided the symbol, returns the value reffed */
138 DEFUN(get_symbol_value
,(symbol
, input_section
),
140 asection
*input_section
)
142 bfd_vma relocation
= 0;
144 if (symbol
!= (asymbol
*)NULL
) {
145 if (symbol
->flags
& BSF_FORT_COMM
) {
148 relocation
= symbol
->value
;
150 if (symbol
->section
!= (asection
*)NULL
) {
151 relocation
+= symbol
->section
->output_section
->vma
+
152 symbol
->section
->output_offset
;
156 /* No symbol, so use the input section value */
157 relocation
= input_section
->output_section
->vma
+ input_section
->output_offset
;
162 static bfd_reloc_status_enum_type
163 DEFUN(reloc64
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
165 arelent
*reloc_entry AND
166 asymbol
*symbol_in AND
167 unsigned char *data AND
168 asection
*input_section
)
170 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
171 bfd_vma value
= bfd_get_64(abfd
, (bfd_byte
*)data
+ reloc_entry
->address
);
172 value
+= sym_value
+ reloc_entry
->addend
;
173 bfd_put_64(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
177 static bfd_reloc_status_enum_type
178 DEFUN(disp64
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
180 arelent
*reloc_entry AND
181 asymbol
*symbol_in AND
182 unsigned char *data AND
183 asection
*input_section
)
185 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
187 /* bfd_get_64(abfd, (bfd_byte *)data + reloc_entry->address);*/
189 value
+= sym_value
+ reloc_entry
->addend
;
191 /* Subtract from the calculated value the pc */
192 value
-= reloc_entry
->address
+ input_section
->output_section
->vma
;
193 bfd_put_64(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
197 static bfd_reloc_status_enum_type
198 DEFUN(hhi22
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
200 arelent
*reloc_entry AND
201 asymbol
*symbol_in AND
202 unsigned char *data AND
203 asection
*input_section
)
205 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
207 bfd_vma value
= bfd_get_32(abfd
, (bfd_byte
*)data
+ reloc_entry
->address
);
209 value
= (value
& ~0x3fffff) | ( ((sym_value
+ reloc_entry
->addend
) >> 32+10) & 0x3fffff);
211 bfd_put_32(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
215 static bfd_reloc_status_enum_type
216 DEFUN(hlo10
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
218 arelent
*reloc_entry AND
219 asymbol
*symbol_in AND
220 unsigned char *data AND
221 asection
*input_section
)
223 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
225 bfd_vma value
= bfd_get_32(abfd
, (bfd_byte
*)data
+ reloc_entry
->address
);
227 value
= (value
& ~0x3ff) | (((sym_value
+ reloc_entry
->addend
) >> 32) & 0x3ff);
229 bfd_put_32(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
233 static bfd_reloc_status_enum_type
239 /* end-sanitize-v9 */
241 static reloc_howto_type howto_table_ext
[] =
243 HOWTO(RELOC_8
, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false),
244 HOWTO(RELOC_16
, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false),
245 HOWTO(RELOC_32
, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false),
246 HOWTO(RELOC_DISP8
, 0, 0, 8, true, 0, false, true,0,"DISP8", false, 0,0x000000ff, false),
247 HOWTO(RELOC_DISP16
, 0, 1, 16, true, 0, false, true,0,"DISP16", false, 0,0x0000ffff, false),
248 HOWTO(RELOC_DISP32
, 0, 2, 32, true, 0, false, true,0,"DISP32", false, 0,0xffffffff, false),
249 HOWTO(RELOC_WDISP30
,2, 2, 30, true, 0, false, true,0,"WDISP30", false, 0,0x3fffffff, false),
250 HOWTO(RELOC_WDISP22
,2, 2, 22, true, 0, false, true,0,"WDISP22", false, 0,0x003fffff, false),
251 HOWTO(RELOC_HI22
, 10, 2, 22, false, 0, false, true,0,"HI22", false, 0,0x003fffff, false),
252 HOWTO(RELOC_22
, 0, 2, 22, false, 0, false, true,0,"22", false, 0,0x003fffff, false),
253 HOWTO(RELOC_13
, 0, 2, 13, false, 0, false, true,0,"13", false, 0,0x00001fff, false),
254 HOWTO(RELOC_LO10
, 0, 2, 10, false, 0, false, true,0,"LO10", false, 0,0x000003ff, false),
255 HOWTO(RELOC_SFA_BASE
,0, 2, 32, false, 0, false, true,0,"SFA_BASE", false, 0,0xffffffff, false),
256 HOWTO(RELOC_SFA_OFF13
,0,2, 32, false, 0, false, true,0,"SFA_OFF13",false, 0,0xffffffff, false),
257 HOWTO(RELOC_BASE10
, 0, 2, 16, false, 0, false, true,0,"BASE10", false, 0,0x0000ffff, false),
258 HOWTO(RELOC_BASE13
, 0, 2, 13, false, 0, false, true,0,"BASE13", false, 0,0x00001fff, false),
259 HOWTO(RELOC_BASE22
, 0, 2, 0, false, 0, false, true,0,"BASE22", false, 0,0x00000000, false),
260 HOWTO(RELOC_PC10
, 0, 2, 10, false, 0, false, true,0,"PC10", false, 0,0x000003ff, false),
261 HOWTO(RELOC_PC22
, 0, 2, 22, false, 0, false, true,0,"PC22", false, 0,0x003fffff, false),
262 HOWTO(RELOC_JMP_TBL
,0, 2, 32, false, 0, false, true,0,"JMP_TBL", false, 0,0xffffffff, false),
263 HOWTO(RELOC_SEGOFF16
,0, 2, 0, false, 0, false, true,0,"SEGOFF16", false, 0,0x00000000, false),
264 HOWTO(RELOC_GLOB_DAT
,0, 2, 0, false, 0, false, true,0,"GLOB_DAT", false, 0,0x00000000, false),
265 HOWTO(RELOC_JMP_SLOT
,0, 2, 0, false, 0, false, true,0,"JMP_SLOT", false, 0,0x00000000, false),
266 HOWTO(RELOC_RELATIVE
,0, 2, 0, false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
268 /* start-sanitize-v9 */
270 HOWTO(RELOC_11
, 0, 2, 21, true, 0, false, true,r64
,"11", false, 0,/*0x00000000001fffff*/0, false),
271 HOWTO(RELOC_WDISP2_14
, 0, 2, 21, true, 0, false, true,r64
,"DISP2_14",false, 0,/*0x00000000001fffff*/0, false),
272 HOWTO(RELOC_WDISP19
, 0, 3, 64, true, 0, false, true,r64
,"DISP19", false, 0,/*0xffffffffffffffff*/0, false),
273 HOWTO(RELOC_HHI22
, 42, 3, 22, false, 0, false, true,hhi22
,"HHI22",false, 0,/*0x003fffff00000000*/0, false),
274 HOWTO(RELOC_HLO10
, 32, 3, 10, false, 0, false, true,hlo10
,"HLO10", false, 0,/*0x000003ff00000000*/0, false),
276 HOWTO(RELOC_JUMPTARG
,2, 13, 16, true, 0, false, true,0,"JUMPTARG", false, 0,0x0000ffff, false),
277 HOWTO(RELOC_CONST
, 0, 13, 16, false, 0, false, true,0,"CONST", false, 0,0x0000ffff, false),
278 HOWTO(RELOC_CONSTH
, 16, 13, 16, false, 0, false, true,0,"CONSTH", false, 0,0x0000ffff, false),
281 HOWTO(RELOC_64
, 0, 3, 64, false, 0, true, true,reloc64
,"64", false, 0,/*0xffffffffffffffff*/0, false),
282 HOWTO(RELOC_DISP64
, 0, 3, 64, true, 0, false, true,disp64
,"DISP64", false, 0,/*0xffffffffffffffff*/0, false),
283 HOWTO(RELOC_WDISP21
,2, 2, 21, true, 0, false, true,r64
,"WDISP21",false, 0,/*0x00000000001fffff*/0, false),
284 HOWTO(RELOC_DISP21
, 0, 2, 21, true, 0, false, true,r64
,"DISP21", false, 0,/*0x00000000001fffff*/0, false),
285 HOWTO(RELOC_DISP14
, 0, 2, 14, true, 0, false, true,r64
,"DISP21", false, 0,/*0x0000000000003fff*/0, false),
287 /* end-sanitize-v9 */
290 /* Convert standard reloc records to "arelent" format (incl byte swap). */
292 static reloc_howto_type howto_table_std
[] = {
293 /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */
294 HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
295 HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
296 HOWTO( 2, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
297 HOWTO( 3, 0, 3, 64, false, 0, true, true,0,"64", true, 0xdeaddead,0xdeaddead, false),
298 HOWTO( 4, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
299 HOWTO( 5, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
300 HOWTO( 6, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
301 HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedface,0xfeedface, false),
305 bfd_error_vector_type bfd_error_vector
;
308 @subsection Internal Entry Points
309 @code{aoutx.h} exports several routines for accessing the contents of
310 an a.out file, which are gathered and exported in turn by various
311 format specific files (eg sunos.c).
315 *i aout_<size>_swap_exec_header_in
316 Swaps the information in an executable header taken from a raw byte stream memory image,
317 into the internal exec_header structure.
318 *; PROTO(void, aout_<size>_swap_exec_header_in,
320 struct external_exec *raw_bytes,
321 struct internal_exec *execp));
325 DEFUN(NAME(aout
,swap_exec_header_in
),(abfd
, raw_bytes
, execp
),
327 struct external_exec
*raw_bytes AND
328 struct internal_exec
*execp
)
330 struct external_exec
*bytes
= (struct external_exec
*)raw_bytes
;
332 /* Now fill in fields in the execp, from the bytes in the raw data. */
333 execp
->a_info
= bfd_h_get_32 (abfd
, bytes
->e_info
);
334 execp
->a_text
= GET_WORD (abfd
, bytes
->e_text
);
335 execp
->a_data
= GET_WORD (abfd
, bytes
->e_data
);
336 execp
->a_bss
= GET_WORD (abfd
, bytes
->e_bss
);
337 execp
->a_syms
= GET_WORD (abfd
, bytes
->e_syms
);
338 execp
->a_entry
= GET_WORD (abfd
, bytes
->e_entry
);
339 execp
->a_trsize
= GET_WORD (abfd
, bytes
->e_trsize
);
340 execp
->a_drsize
= GET_WORD (abfd
, bytes
->e_drsize
);
344 *i aout_<size>_swap_exec_header_out
345 Swaps the information in an internal exec header structure into the
346 supplied buffer ready for writing to disk.
347 *; PROTO(void, aout_<size>_swap_exec_header_out,
349 struct internal_exec *execp,
350 struct external_exec *raw_bytes));
353 DEFUN(NAME(aout
,swap_exec_header_out
),(abfd
, execp
, raw_bytes
),
355 struct internal_exec
*execp AND
356 struct external_exec
*raw_bytes
)
358 struct external_exec
*bytes
= (struct external_exec
*)raw_bytes
;
360 /* Now fill in fields in the raw data, from the fields in the exec struct. */
361 bfd_h_put_32 (abfd
, execp
->a_info
, bytes
->e_info
);
362 PUT_WORD (abfd
, execp
->a_text
, bytes
->e_text
);
363 PUT_WORD (abfd
, execp
->a_data
, bytes
->e_data
);
364 PUT_WORD (abfd
, execp
->a_bss
, bytes
->e_bss
);
365 PUT_WORD (abfd
, execp
->a_syms
, bytes
->e_syms
);
366 PUT_WORD (abfd
, execp
->a_entry
, bytes
->e_entry
);
367 PUT_WORD (abfd
, execp
->a_trsize
, bytes
->e_trsize
);
368 PUT_WORD (abfd
, execp
->a_drsize
, bytes
->e_drsize
);
373 struct internal_exec e
;
378 *i aout_<size>_some_aout_object_p
380 Some A.OUT variant thinks that the file whose format we're checking
381 is an a.out file. Do some more checking, and set up for access if
382 it really is. Call back to the calling environments "finish up"
383 function just before returning, to handle any last-minute setup.
385 *; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
387 bfd_target *(*callback_to_real_object_p)()));
391 DEFUN(NAME(aout
,some_aout_object_p
),(abfd
, callback_to_real_object_p
),
393 bfd_target
*(*callback_to_real_object_p
) ())
395 struct external_exec exec_bytes
;
396 struct internal_exec
*execp
;
397 struct container
*rawptr
;
399 if (bfd_seek (abfd
, 0L, false) < 0) {
400 bfd_error
= system_call_error
;
404 if (bfd_read ((PTR
) &exec_bytes
, 1, EXEC_BYTES_SIZE
, abfd
)
405 != EXEC_BYTES_SIZE
) {
406 bfd_error
= wrong_format
;
410 /* Use an intermediate variable for clarity */
411 rawptr
= (struct container
*) bfd_zalloc (abfd
, sizeof (struct container
));
413 if (rawptr
== NULL
) {
414 bfd_error
= no_memory
;
418 set_tdata (abfd
, rawptr
);
419 exec_hdr (abfd
) = execp
= &(rawptr
->e
);
420 NAME(aout
,swap_exec_header_in
)(abfd
, &exec_bytes
, execp
);
422 /* Set the file flags */
423 abfd
->flags
= NO_FLAGS
;
424 if (execp
->a_drsize
|| execp
->a_trsize
)
425 abfd
->flags
|= HAS_RELOC
;
427 abfd
->flags
|= EXEC_P
;
429 abfd
->flags
|= HAS_LINENO
| HAS_DEBUG
| HAS_SYMS
| HAS_LOCALS
;
431 if (N_MAGIC (*execp
) == ZMAGIC
) abfd
->flags
|= D_PAGED
;
432 if (N_MAGIC (*execp
) == NMAGIC
) abfd
->flags
|= WP_TEXT
;
434 bfd_get_start_address (abfd
) = execp
->a_entry
;
436 obj_aout_symbols (abfd
) = (aout_symbol_type
*)NULL
;
437 bfd_get_symcount (abfd
) = execp
->a_syms
/ sizeof (struct external_nlist
);
439 /* Set the default architecture and machine type. These can be
440 overridden in the callback routine. */
441 abfd
->obj_arch
= bfd_arch_unknown
;
442 abfd
->obj_machine
= 0;
444 /* The default relocation entry size is that of traditional V7 Unix. */
445 obj_reloc_entry_size (abfd
) = RELOC_STD_SIZE
;
447 /* create the sections. This is raunchy, but bfd_close wants to reclaim
449 obj_textsec (abfd
) = (asection
*)NULL
;
450 obj_datasec (abfd
) = (asection
*)NULL
;
451 obj_bsssec (abfd
) = (asection
*)NULL
;
452 (void)bfd_make_section(abfd
, ".text");
453 (void)bfd_make_section(abfd
, ".data");
454 (void)bfd_make_section(abfd
, ".bss");
456 abfd
->sections
= obj_textsec (abfd
);
457 obj_textsec (abfd
)->next
= obj_datasec (abfd
);
458 obj_datasec (abfd
)->next
= obj_bsssec (abfd
);
460 obj_datasec (abfd
)->size
= execp
->a_data
;
461 obj_bsssec (abfd
)->size
= execp
->a_bss
;
462 obj_textsec (abfd
)->size
= execp
->a_text
;
464 if (abfd
->flags
& D_PAGED
) {
465 obj_textsec (abfd
)->size
-= EXEC_BYTES_SIZE
;
469 obj_textsec (abfd
)->flags
= (execp
->a_trsize
!= 0 ?
470 (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_HAS_CONTENTS
) :
471 (SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
));
472 obj_datasec (abfd
)->flags
= (execp
->a_drsize
!= 0 ?
473 (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_HAS_CONTENTS
) :
474 (SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
));
475 obj_bsssec (abfd
)->flags
= SEC_ALLOC
;
477 #ifdef THIS_IS_ONLY_DOCUMENTATION
478 /* Call back to the format-dependent code to fill in the rest of the
479 fields and do any further cleanup. Things that should be filled
480 in by the callback: */
482 struct exec
*execp
= exec_hdr (abfd
);
484 /* The virtual memory addresses of the sections */
485 obj_datasec (abfd
)->vma
= N_DATADDR(*execp
);
486 obj_bsssec (abfd
)->vma
= N_BSSADDR(*execp
);
487 obj_textsec (abfd
)->vma
= N_TXTADDR(*execp
);
489 /* The file offsets of the sections */
490 obj_textsec (abfd
)->filepos
= N_TXTOFF(*execp
);
491 obj_datasec (abfd
)->filepos
= N_DATOFF(*execp
);
493 /* The file offsets of the relocation info */
494 obj_textsec (abfd
)->rel_filepos
= N_TRELOFF(*execp
);
495 obj_datasec (abfd
)->rel_filepos
= N_DRELOFF(*execp
);
497 /* The file offsets of the string table and symbol table. */
498 obj_str_filepos (abfd
) = N_STROFF (*execp
);
499 obj_sym_filepos (abfd
) = N_SYMOFF (*execp
);
501 /* This common code can't fill in those things because they depend
502 on either the start address of the text segment, the rounding
503 up of virtual addersses between segments, or the starting file
504 position of the text segment -- all of which varies among different
505 versions of a.out. */
507 /* Determine the architecture and machine type of the object file. */
508 switch (N_MACHTYPE (*exec_hdr (abfd
))) {
510 abfd
->obj_arch
= bfd_arch_obscure
;
514 /* Determine the size of a relocation entry */
515 switch (abfd
->obj_arch
) {
518 obj_reloc_entry_size (abfd
) = RELOC_EXT_SIZE
;
520 obj_reloc_entry_size (abfd
) = RELOC_STD_SIZE
;
525 /* The architecture is encoded in various ways in various a.out variants,
526 or is not encoded at all in some of them. The relocation size depends
527 on the architecture and the a.out variant. Finally, the return value
528 is the bfd_target vector in use. If an error occurs, return zero and
529 set bfd_error to the appropriate error code.
531 Formats such as b.out, which have additional fields in the a.out
532 header, should cope with them in this callback as well. */
533 #endif /* DOCUMENTATION */
536 return (*callback_to_real_object_p
)(abfd
);
540 *i aout_<size>_mkobject
542 This routine initializes a BFD for use with a.out files.
544 *; PROTO(boolean, aout_<size>_mkobject, (bfd *));
548 DEFUN(NAME(aout
,mkobject
),(abfd
),
551 struct container
*rawptr
;
553 bfd_error
= system_call_error
;
555 /* Use an intermediate variable for clarity */
556 rawptr
= (struct container
*)bfd_zalloc (abfd
, sizeof (struct container
));
558 if (rawptr
== NULL
) {
559 bfd_error
= no_memory
;
563 set_tdata (abfd
, rawptr
);
564 exec_hdr (abfd
) = &(rawptr
->e
);
566 /* For simplicity's sake we just make all the sections right here. */
568 obj_textsec (abfd
) = (asection
*)NULL
;
569 obj_datasec (abfd
) = (asection
*)NULL
;
570 obj_bsssec (abfd
) = (asection
*)NULL
;
571 bfd_make_section (abfd
, ".text");
572 bfd_make_section (abfd
, ".data");
573 bfd_make_section (abfd
, ".bss");
580 *i aout_<size>_machine_type
582 Keep track of machine architecture and machine type for a.out's.
583 Return the machine_type for a particular arch&machine, or M_UNKNOWN
584 if that exact arch&machine can't be represented in a.out format.
586 If the architecture is understood, machine type 0 (default) should
587 always be understood.
589 *; PROTO(enum machine_type, aout_<size>_machine_type,
590 (enum bfd_architecture arch,
591 unsigned long machine));
595 DEFUN(NAME(aout
,machine_type
),(arch
, machine
),
596 enum bfd_architecture arch AND
597 unsigned long machine
)
599 enum machine_type arch_flags
;
601 arch_flags
= M_UNKNOWN
;
605 if (machine
== 0) arch_flags
= M_SPARC
;
610 case 0: arch_flags
= M_68010
; break;
611 case 68000: arch_flags
= M_UNKNOWN
; break;
612 case 68010: arch_flags
= M_68010
; break;
613 case 68020: arch_flags
= M_68020
; break;
614 default: arch_flags
= M_UNKNOWN
; break;
619 if (machine
== 0) arch_flags
= M_386
;
623 if (machine
== 0) arch_flags
= M_29K
;
627 arch_flags
= M_UNKNOWN
;
634 *i aout_<size>_set_arch_mach
636 Sets the architecture and the machine of the BFD to those values
637 supplied. Verifies that the format can support the architecture
640 *; PROTO(boolean, aout_<size>_set_arch_mach,
642 enum bfd_architecture,
643 unsigned long machine));
647 DEFUN(NAME(aout
,set_arch_mach
),(abfd
, arch
, machine
),
649 enum bfd_architecture arch AND
650 unsigned long machine
)
652 abfd
->obj_arch
= arch
;
653 abfd
->obj_machine
= machine
;
654 if (arch
!= bfd_arch_unknown
&&
655 NAME(aout
,machine_type
) (arch
, machine
) == M_UNKNOWN
)
656 return false; /* We can't represent this type */
657 return true; /* We're easy ... */
661 *i aout_<size>new_section_hook
663 Called by the BFD in response to a @code{bfd_make_section} request.
664 *; PROTO(boolean, aout_<size>_new_section_hook,
669 DEFUN(NAME(aout
,new_section_hook
),(abfd
, newsect
),
673 /* align to double at least */
674 newsect
->alignment_power
= 3;
676 if (bfd_get_format (abfd
) == bfd_object
) {
677 if (obj_textsec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".text")) {
678 obj_textsec(abfd
)= newsect
;
682 if (obj_datasec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".data")) {
683 obj_datasec(abfd
) = newsect
;
687 if (obj_bsssec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".bss")) {
688 obj_bsssec(abfd
) = newsect
;
693 /* We allow more than three sections internally */
698 DEFUN(NAME(aout
,set_section_contents
),(abfd
, section
, location
, offset
, count
),
705 if (abfd
->output_has_begun
== false)
706 { /* set by bfd.c handler */
707 switch (abfd
->direction
)
711 bfd_error
= invalid_operation
;
717 case write_direction
:
718 if ((obj_textsec (abfd
) == NULL
) || (obj_datasec (abfd
) == NULL
))
720 bfd_error
= invalid_operation
;
723 /*if (abfd->flags & D_PAGED) {
724 obj_textsec(abfd)->filepos = 0;
727 obj_textsec(abfd
)->filepos
= EXEC_BYTES_SIZE
;
729 obj_textsec(abfd
)->size
= align_power(obj_textsec(abfd
)->size
,
730 obj_textsec(abfd
)->alignment_power
);
731 obj_datasec(abfd
)->filepos
= obj_textsec (abfd
)->size
+ EXEC_BYTES_SIZE
;
732 obj_datasec(abfd
)->size
= align_power(obj_datasec(abfd
)->size
,
733 obj_datasec(abfd
)->alignment_power
);
737 /* regardless, once we know what we're doing, we might as well get going */
738 if (section
!= obj_bsssec(abfd
))
740 bfd_seek (abfd
, section
->filepos
+ offset
, SEEK_SET
);
743 return (bfd_write ((PTR
)location
, 1, count
, abfd
) == count
) ?
751 /* Classify stabs symbols */
753 #define sym_in_text_section(sym) \
754 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
756 #define sym_in_data_section(sym) \
757 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
759 #define sym_in_bss_section(sym) \
760 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
762 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
763 zero in the "value" field. Nonzeroes there are fortrancommon
765 #define sym_is_undefined(sym) \
766 ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
768 /* Symbol is a global definition if N_EXT is on and if it has
769 a nonzero type field. */
770 #define sym_is_global_defn(sym) \
771 (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
773 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
775 #define sym_is_debugger_info(sym) \
776 ((sym)->type & ~(N_EXT | N_TYPE))
778 #define sym_is_fortrancommon(sym) \
779 (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
781 /* Symbol is absolute if it has N_ABS set */
782 #define sym_is_absolute(sym) \
783 (((sym)->type & N_TYPE)== N_ABS)
786 #define sym_is_indirect(sym) \
787 (((sym)->type & N_ABS)== N_ABS)
789 /* Only in their own functions for ease of debugging; when sym flags have
790 stabilised these should be inlined into their (single) caller */
793 DEFUN(translate_from_native_sym_flags
,(sym_pointer
, cache_ptr
, abfd
),
794 struct external_nlist
*sym_pointer AND
795 aout_symbol_type
*cache_ptr AND
798 switch (cache_ptr
->type
& N_TYPE
) {
804 char *copy
= bfd_alloc(abfd
, strlen(cache_ptr
->symbol
.name
)+1);
806 arelent_chain
*reloc
= (arelent_chain
*)bfd_alloc(abfd
, sizeof(arelent_chain
));
807 strcpy(copy
, cache_ptr
->symbol
.name
);
808 section
= bfd_make_section(abfd
,copy
);
809 switch ( (cache_ptr
->type
& N_TYPE
) ) {
811 section
->flags
= SEC_CONSTRUCTOR
;
812 reloc
->relent
.section
= (asection
*)NULL
;
813 cache_ptr
->symbol
.section
= (asection
*)NULL
;
816 section
->flags
= SEC_CONSTRUCTOR_TEXT
;
817 reloc
->relent
.section
= (asection
*)obj_textsec(abfd
);
818 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
821 section
->flags
= SEC_CONSTRUCTOR_DATA
;
822 reloc
->relent
.section
= (asection
*)obj_datasec(abfd
);
823 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
826 section
->flags
= SEC_CONSTRUCTOR_BSS
;
827 reloc
->relent
.section
= (asection
*)obj_bsssec(abfd
);
828 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
831 cache_ptr
->symbol
.section
= reloc
->relent
.section
;
832 reloc
->relent
.addend
= cache_ptr
->symbol
.value
;
834 /* We modify the symbol to belong to a section depending upon the
835 name of the symbol - probably __CTOR__ or __DTOR__ but we don't
836 really care, and add to the size of the section to contain a
837 pointer to the symbol. Build a reloc entry to relocate to this
838 symbol attached to this section. */
841 section
->reloc_count
++;
842 section
->alignment_power
= 2;
843 reloc
->relent
.sym_ptr_ptr
= (asymbol
**)NULL
;
844 reloc
->next
= section
->constructor_chain
;
845 section
->constructor_chain
= reloc
;
846 reloc
->relent
.address
= section
->size
;
847 section
->size
+= sizeof(int *);
849 reloc
->relent
.howto
= howto_table_ext
+CTOR_TABLE_RELOC_IDX
;
850 cache_ptr
->symbol
.flags
|= BSF_DEBUGGING
| BSF_CONSTRUCTOR
;
854 if (cache_ptr
->type
== N_WARNING
)
856 /* This symbol is the text of a warning message, the next symbol
857 is the symbol to associate the warning with */
858 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
| BSF_WARNING
;
859 cache_ptr
->symbol
.value
= (bfd_vma
)((cache_ptr
+1));
860 /* We furgle with the next symbol in place. We don't want it to be undefined, we'll trample the type */
861 (sym_pointer
+1)->e_type
[0] = 0xff;
864 if ((cache_ptr
->type
| N_EXT
) == (N_INDR
| N_EXT
)) {
865 /* Two symbols in a row for an INDR message. The first symbol
866 contains the name we will match, the second symbol contains the
867 name the first name is translated into. It is supplied to us
868 undefined. This is good, since we want to pull in any files which
870 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
| BSF_INDIRECT
;
871 cache_ptr
->symbol
.value
= (bfd_vma
)((cache_ptr
+1));
876 if (sym_is_debugger_info (cache_ptr
)) {
877 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
;
878 /* Work out the section correct for this symbol */
879 switch (cache_ptr
->type
& N_TYPE
)
883 cache_ptr
->symbol
.section
= obj_textsec (abfd
);
884 cache_ptr
->symbol
.value
-= obj_textsec(abfd
)->vma
;
887 cache_ptr
->symbol
.value
-= obj_datasec(abfd
)->vma
;
888 cache_ptr
->symbol
.section
= obj_datasec (abfd
);
891 cache_ptr
->symbol
.section
= obj_bsssec (abfd
);
892 cache_ptr
->symbol
.value
-= obj_bsssec(abfd
)->vma
;
896 cache_ptr
->symbol
.section
= 0;
902 if (sym_is_fortrancommon (cache_ptr
))
904 cache_ptr
->symbol
.flags
= BSF_FORT_COMM
;
905 cache_ptr
->symbol
.section
= (asection
*)NULL
;
908 if (sym_is_undefined (cache_ptr
)) {
909 cache_ptr
->symbol
.flags
= BSF_UNDEFINED
;
911 else if (sym_is_global_defn (cache_ptr
)) {
912 cache_ptr
->symbol
.flags
= BSF_GLOBAL
| BSF_EXPORT
;
915 else if (sym_is_absolute (cache_ptr
)) {
916 cache_ptr
->symbol
.flags
= BSF_ABSOLUTE
;
919 cache_ptr
->symbol
.flags
= BSF_LOCAL
;
922 /* In a.out, the value of a symbol is always relative to the
923 * start of the file, if this is a data symbol we'll subtract
924 * the size of the text section to get the section relative
925 * value. If this is a bss symbol (which would be strange)
926 * we'll subtract the size of the previous two sections
927 * to find the section relative address.
930 if (sym_in_text_section (cache_ptr
)) {
931 cache_ptr
->symbol
.value
-= obj_textsec(abfd
)->vma
;
932 cache_ptr
->symbol
.section
= obj_textsec (abfd
);
934 else if (sym_in_data_section (cache_ptr
)){
935 cache_ptr
->symbol
.value
-= obj_datasec(abfd
)->vma
;
936 cache_ptr
->symbol
.section
= obj_datasec (abfd
);
938 else if (sym_in_bss_section(cache_ptr
)) {
939 cache_ptr
->symbol
.section
= obj_bsssec (abfd
);
940 cache_ptr
->symbol
.value
-= obj_bsssec(abfd
)->vma
;
943 cache_ptr
->symbol
.section
= (asection
*)NULL
;
944 cache_ptr
->symbol
.flags
|= BSF_ABSOLUTE
;
952 DEFUN(translate_to_native_sym_flags
,(sym_pointer
, cache_ptr
, abfd
),
953 struct external_nlist
*sym_pointer AND
954 asymbol
*cache_ptr AND
957 bfd_vma value
= cache_ptr
->value
;
959 if (bfd_get_section(cache_ptr
)) {
960 if (bfd_get_output_section(cache_ptr
) == obj_bsssec (abfd
)) {
961 sym_pointer
->e_type
[0] |= N_BSS
;
963 else if (bfd_get_output_section(cache_ptr
) == obj_datasec (abfd
)) {
964 sym_pointer
->e_type
[0] |= N_DATA
;
966 else if (bfd_get_output_section(cache_ptr
) == obj_textsec (abfd
)) {
967 sym_pointer
->e_type
[0] |= N_TEXT
;
970 bfd_error_vector
.nonrepresentable_section(abfd
,
971 bfd_get_output_section(cache_ptr
)->name
);
973 /* Turn the symbol from section relative to absolute again */
976 cache_ptr
->section
->output_section
->vma
977 + cache_ptr
->section
->output_offset
;
980 sym_pointer
->e_type
[0] |= N_ABS
;
982 if (cache_ptr
->flags
& (BSF_WARNING
)) {
983 (sym_pointer
+1)->e_type
[0] = 1;
985 if (cache_ptr
->flags
& (BSF_FORT_COMM
| BSF_UNDEFINED
)) {
986 sym_pointer
->e_type
[0] = (N_UNDF
| N_EXT
);
989 if (cache_ptr
->flags
& BSF_ABSOLUTE
) {
990 sym_pointer
->e_type
[0] |= N_ABS
;
993 if (cache_ptr
->flags
& (BSF_GLOBAL
| BSF_EXPORT
)) {
994 sym_pointer
->e_type
[0] |= N_EXT
;
996 if (cache_ptr
->flags
& BSF_DEBUGGING
) {
997 sym_pointer
->e_type
[0]= ((aout_symbol_type
*)cache_ptr
)->type
;
1000 PUT_WORD(abfd
, value
, sym_pointer
->e_value
);
1003 /* Native-level interface to symbols. */
1005 /* We read the symbols into a buffer, which is discarded when this
1006 function exits. We read the strings into a buffer large enough to
1007 hold them all plus all the cached symbol entries. */
1010 DEFUN(NAME(aout
,make_empty_symbol
),(abfd
),
1013 aout_symbol_type
*new =
1014 (aout_symbol_type
*)bfd_zalloc (abfd
, sizeof (aout_symbol_type
));
1015 new->symbol
.the_bfd
= abfd
;
1017 return &new->symbol
;
1021 DEFUN(NAME(aout
,slurp_symbol_table
),(abfd
),
1024 bfd_size_type symbol_size
;
1025 bfd_size_type string_size
;
1026 unsigned char string_chars
[BYTES_IN_WORD
];
1027 struct external_nlist
*syms
;
1029 aout_symbol_type
*cached
;
1031 /* If there's no work to be done, don't do any */
1032 if (obj_aout_symbols (abfd
) != (aout_symbol_type
*)NULL
) return true;
1033 symbol_size
= exec_hdr(abfd
)->a_syms
;
1034 if (symbol_size
== 0) {
1035 bfd_error
= no_symbols
;
1039 bfd_seek (abfd
, obj_str_filepos (abfd
), SEEK_SET
);
1040 if (bfd_read ((PTR
)string_chars
, BYTES_IN_WORD
, 1, abfd
) != BYTES_IN_WORD
)
1042 string_size
= GET_WORD (abfd
, string_chars
);
1044 strings
=(char *) bfd_alloc(abfd
, string_size
+ 1);
1045 cached
= (aout_symbol_type
*)
1046 bfd_zalloc(abfd
, (bfd_size_type
)(bfd_get_symcount (abfd
) * sizeof(aout_symbol_type
)));
1048 /* malloc this, so we can free it if simply. The symbol caching
1049 might want to allocate onto the bfd's obstack */
1050 syms
= (struct external_nlist
*) malloc(symbol_size
);
1051 bfd_seek (abfd
, obj_sym_filepos (abfd
), SEEK_SET
);
1052 if (bfd_read ((PTR
)syms
, 1, symbol_size
, abfd
) != symbol_size
) {
1054 if (syms
) free (syms
);
1055 if (cached
) bfd_release (abfd
, cached
);
1056 if (strings
)bfd_release (abfd
, strings
);
1060 bfd_seek (abfd
, obj_str_filepos (abfd
), SEEK_SET
);
1061 if (bfd_read ((PTR
)strings
, 1, string_size
, abfd
) != string_size
) {
1065 /* OK, now walk the new symtable, cacheing symbol properties */
1067 register struct external_nlist
*sym_pointer
;
1068 register struct external_nlist
*sym_end
= syms
+ bfd_get_symcount (abfd
);
1069 register aout_symbol_type
*cache_ptr
= cached
;
1071 /* Run through table and copy values */
1072 for (sym_pointer
= syms
, cache_ptr
= cached
;
1073 sym_pointer
< sym_end
; sym_pointer
++, cache_ptr
++)
1075 bfd_vma x
= GET_WORD(abfd
, sym_pointer
->e_strx
);
1076 cache_ptr
->symbol
.the_bfd
= abfd
;
1078 cache_ptr
->symbol
.name
= x
+ strings
;
1080 cache_ptr
->symbol
.name
= (char *)NULL
;
1082 cache_ptr
->symbol
.value
= GET_SWORD(abfd
, sym_pointer
->e_value
);
1083 cache_ptr
->desc
= bfd_get_16(abfd
, sym_pointer
->e_desc
);
1084 cache_ptr
->other
=bfd_get_8(abfd
, sym_pointer
->e_other
);
1085 cache_ptr
->type
= bfd_get_8(abfd
, sym_pointer
->e_type
);
1086 cache_ptr
->symbol
.udata
= 0;
1087 translate_from_native_sym_flags (sym_pointer
, cache_ptr
, abfd
);
1091 obj_aout_symbols (abfd
) = cached
;
1099 DEFUN(NAME(aout
,write_syms
),(abfd
),
1102 unsigned int count
;
1103 asymbol
**generic
= bfd_get_outsymbols (abfd
);
1105 bfd_size_type stindex
= BYTES_IN_WORD
; /* initial string length */
1107 for (count
= 0; count
< bfd_get_symcount (abfd
); count
++) {
1108 asymbol
*g
= generic
[count
];
1109 struct external_nlist nsp
;
1113 unsigned int length
= strlen(g
->name
) +1;
1114 PUT_WORD (abfd
, stindex
, (unsigned char *)nsp
.e_strx
);
1118 PUT_WORD (abfd
, 0, (unsigned char *)nsp
.e_strx
);
1121 if (g
->the_bfd
->xvec
->flavour
== abfd
->xvec
->flavour
)
1123 bfd_h_put_16(abfd
, aout_symbol(g
)->desc
, nsp
.e_desc
);
1124 bfd_h_put_8(abfd
, aout_symbol(g
)->other
, nsp
.e_other
);
1125 bfd_h_put_8(abfd
, aout_symbol(g
)->type
, nsp
.e_type
);
1129 bfd_h_put_16(abfd
,0, nsp
.e_desc
);
1130 bfd_h_put_8(abfd
, 0, nsp
.e_other
);
1131 bfd_h_put_8(abfd
, 0, nsp
.e_type
);
1136 translate_to_native_sym_flags (&nsp
, g
, abfd
);
1138 bfd_write((PTR
)&nsp
,1,EXTERNAL_LIST_SIZE
, abfd
);
1142 /* Now output the strings. Be sure to put string length into correct
1143 * byte ordering before writing it.
1146 char buffer
[BYTES_IN_WORD
];
1147 PUT_WORD (abfd
, stindex
, (unsigned char *)buffer
);
1149 bfd_write((PTR
)buffer
, 1, BYTES_IN_WORD
, abfd
);
1151 generic
= bfd_get_outsymbols(abfd
);
1152 for (count
= 0; count
< bfd_get_symcount(abfd
); count
++)
1154 asymbol
*g
= *(generic
++);
1158 size_t length
= strlen(g
->name
)+1;
1159 bfd_write((PTR
)g
->name
, 1, length
, abfd
);
1161 if ((g
->flags
& BSF_FAKE
)==0) {
1162 g
->KEEPIT
= (KEEPITTYPE
) count
;
1170 DEFUN(NAME(aout
,get_symtab
),(abfd
, location
),
1174 unsigned int counter
= 0;
1175 aout_symbol_type
*symbase
;
1177 if (!NAME(aout
,slurp_symbol_table
)(abfd
)) return 0;
1179 for (symbase
= obj_aout_symbols(abfd
); counter
++ < bfd_get_symcount (abfd
);)
1180 *(location
++) = (asymbol
*)( symbase
++);
1182 return bfd_get_symcount(abfd
);
1186 /* Standard reloc stuff */
1187 /* Output standard relocation information to a file in target byte order. */
1190 DEFUN(NAME(aout
,swap_std_reloc_out
),(abfd
, g
, natptr
),
1193 struct reloc_std_external
*natptr
)
1197 unsigned int r_length
;
1199 int r_baserel
, r_jmptable
, r_relative
;
1200 unsigned int r_addend
;
1202 PUT_WORD(abfd
, g
->address
, natptr
->r_address
);
1204 r_length
= g
->howto
->size
; /* Size as a power of two */
1205 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
1206 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
1211 r_addend
= g
->addend
; /* Start here, see how it goes */
1213 /* name was clobbered by aout_write_syms to be symbol index */
1215 if (g
->sym_ptr_ptr
!= NULL
)
1217 if ((*(g
->sym_ptr_ptr
))->section
) {
1218 /* put the section offset into the addend for output */
1219 r_addend
+= (*(g
->sym_ptr_ptr
))->section
->vma
;
1222 r_index
= ((*(g
->sym_ptr_ptr
))->KEEPIT
);
1227 if (g
->section
== NULL
) {
1228 /* It is possible to have a reloc with nothing, we generate an
1231 r_index
= N_ABS
| N_EXT
;
1233 else if(g
->section
->output_section
== obj_textsec(abfd
)) {
1234 r_index
= N_TEXT
| N_EXT
;
1235 r_addend
+= g
->section
->output_section
->vma
;
1237 else if (g
->section
->output_section
== obj_datasec(abfd
)) {
1238 r_index
= N_DATA
| N_EXT
;
1239 r_addend
+= g
->section
->output_section
->vma
;
1241 else if (g
->section
->output_section
== obj_bsssec(abfd
)) {
1242 r_index
= N_BSS
| N_EXT
;
1243 r_addend
+= g
->section
->output_section
->vma
;
1250 /* now the fun stuff */
1251 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1252 natptr
->r_index
[0] = r_index
>> 16;
1253 natptr
->r_index
[1] = r_index
>> 8;
1254 natptr
->r_index
[2] = r_index
;
1256 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
1257 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
1258 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
1259 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
1260 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
1261 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
1263 natptr
->r_index
[2] = r_index
>> 16;
1264 natptr
->r_index
[1] = r_index
>> 8;
1265 natptr
->r_index
[0] = r_index
;
1267 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
1268 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
1269 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
1270 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
1271 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
1272 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
1277 /* Extended stuff */
1278 /* Output extended relocation information to a file in target byte order. */
1281 DEFUN(NAME(aout
,swap_ext_reloc_out
),(abfd
, g
, natptr
),
1284 register struct reloc_ext_external
*natptr
)
1288 unsigned int r_type
;
1289 unsigned int r_addend
;
1291 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
1293 /* Find a type in the output format which matches the input howto -
1294 at the moment we assume input format == output format FIXME!! */
1295 r_type
= (enum reloc_type
) g
->howto
->type
;
1297 r_addend
= g
->addend
; /* Start here, see how it goes */
1299 /* name was clobbered by aout_write_syms to be symbol index*/
1301 if (g
->sym_ptr_ptr
!= NULL
)
1303 if ((*(g
->sym_ptr_ptr
))->section
) {
1304 /* put the section offset into the addend for output */
1305 r_addend
+= (*(g
->sym_ptr_ptr
))->section
->vma
;
1308 r_index
= stoi((*(g
->sym_ptr_ptr
))->KEEPIT
);
1313 if (g
->section
== NULL
) {
1315 r_index
= N_ABS
| N_EXT
;
1317 else if(g
->section
->output_section
== obj_textsec(abfd
)) {
1318 r_index
= N_TEXT
| N_EXT
;
1319 r_addend
+= g
->section
->output_section
->vma
;
1321 else if (g
->section
->output_section
== obj_datasec(abfd
)) {
1322 r_index
= N_DATA
| N_EXT
;
1323 r_addend
+= g
->section
->output_section
->vma
;
1325 else if (g
->section
->output_section
== obj_bsssec(abfd
)) {
1326 r_index
= N_BSS
| N_EXT
;
1327 r_addend
+= g
->section
->output_section
->vma
;
1334 /* now the fun stuff */
1335 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1336 natptr
->r_index
[0] = r_index
>> 16;
1337 natptr
->r_index
[1] = r_index
>> 8;
1338 natptr
->r_index
[2] = r_index
;
1340 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
1341 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
1343 natptr
->r_index
[2] = r_index
>> 16;
1344 natptr
->r_index
[1] = r_index
>> 8;
1345 natptr
->r_index
[0] = r_index
;
1347 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
1348 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
1351 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
1354 #define MOVE_ADDRESS(ad) \
1356 cache_ptr->sym_ptr_ptr = symbols + r_index; \
1357 cache_ptr->section = (asection *)NULL; \
1358 cache_ptr->addend = ad; \
1360 cache_ptr->sym_ptr_ptr = (asymbol **)NULL; \
1361 switch (r_index) { \
1363 case N_TEXT | N_EXT: \
1364 cache_ptr->section = obj_textsec(abfd); \
1365 cache_ptr->addend = ad - su->textsec->vma; \
1368 case N_DATA | N_EXT: \
1369 cache_ptr->section = obj_datasec(abfd); \
1370 cache_ptr->addend = ad - su->datasec->vma; \
1373 case N_BSS | N_EXT: \
1374 cache_ptr->section = obj_bsssec(abfd); \
1375 cache_ptr->addend = ad - su->bsssec->vma; \
1378 case N_ABS | N_EXT: \
1379 cache_ptr->section = NULL; /* No section */ \
1380 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1384 cache_ptr->section = NULL; /* No section */ \
1385 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1392 DEFUN(NAME(aout
,swap_ext_reloc_in
), (abfd
, bytes
, cache_ptr
, symbols
),
1394 struct reloc_ext_external
*bytes AND
1395 arelent
*cache_ptr AND
1400 unsigned int r_type
;
1401 struct aoutdata
*su
= (struct aoutdata
*)(abfd
->tdata
);
1403 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
1405 /* now the fun stuff */
1406 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1407 r_index
= (bytes
->r_index
[0] << 16)
1408 | (bytes
->r_index
[1] << 8)
1409 | bytes
->r_index
[2];
1410 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
1411 r_type
= (bytes
->r_type
[0] & RELOC_EXT_BITS_TYPE_BIG
)
1412 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
1414 r_index
= (bytes
->r_index
[2] << 16)
1415 | (bytes
->r_index
[1] << 8)
1416 | bytes
->r_index
[0];
1417 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_EXT_BITS_EXTERN_LITTLE
));
1418 r_type
= (bytes
->r_type
[0] & RELOC_EXT_BITS_TYPE_LITTLE
)
1419 >> RELOC_EXT_BITS_TYPE_SH_LITTLE
;
1422 cache_ptr
->howto
= howto_table_ext
+ r_type
;
1423 MOVE_ADDRESS(GET_SWORD(abfd
,bytes
->r_addend
));
1427 DEFUN(NAME(aout
,swap_std_reloc_in
), (abfd
, bytes
, cache_ptr
, symbols
),
1429 struct reloc_std_external
*bytes AND
1430 arelent
*cache_ptr AND
1435 unsigned int r_length
;
1437 int r_baserel
, r_jmptable
, r_relative
;
1438 struct aoutdata
*su
= (struct aoutdata
*)(abfd
->tdata
);
1440 cache_ptr
->address
= (int32_type
)(bfd_h_get_32 (abfd
, bytes
->r_address
));
1442 /* now the fun stuff */
1443 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1444 r_index
= (bytes
->r_index
[0] << 16)
1445 | (bytes
->r_index
[1] << 8)
1446 | bytes
->r_index
[2];
1447 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_EXTERN_BIG
));
1448 r_pcrel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_PCREL_BIG
));
1449 r_baserel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_BASEREL_BIG
));
1450 r_jmptable
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
1451 r_relative
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
1452 r_length
= (bytes
->r_type
[0] & RELOC_STD_BITS_LENGTH_BIG
)
1453 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
1455 r_index
= (bytes
->r_index
[2] << 16)
1456 | (bytes
->r_index
[1] << 8)
1457 | bytes
->r_index
[0];
1458 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_EXTERN_LITTLE
));
1459 r_pcrel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_PCREL_LITTLE
));
1460 r_baserel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_BASEREL_LITTLE
));
1461 r_jmptable
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_JMPTABLE_LITTLE
));
1462 r_relative
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_RELATIVE_LITTLE
));
1463 r_length
= (bytes
->r_type
[0] & RELOC_STD_BITS_LENGTH_LITTLE
)
1464 >> RELOC_STD_BITS_LENGTH_SH_LITTLE
;
1467 cache_ptr
->howto
= howto_table_std
+ r_length
+ 4 * r_pcrel
;
1468 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
1476 DEFUN(NAME(aout
,slurp_reloc_table
),(abfd
, asect
, symbols
),
1482 bfd_size_type reloc_size
;
1484 arelent
*reloc_cache
;
1487 if (asect
->relocation
) return true;
1489 if (asect
->flags
& SEC_CONSTRUCTOR
) return true;
1491 if (asect
== obj_datasec (abfd
)) {
1492 reloc_size
= exec_hdr(abfd
)->a_drsize
;
1496 if (asect
== obj_textsec (abfd
)) {
1497 reloc_size
= exec_hdr(abfd
)->a_trsize
;
1501 bfd_error
= invalid_operation
;
1505 bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
);
1506 each_size
= obj_reloc_entry_size (abfd
);
1508 count
= reloc_size
/ each_size
;
1511 reloc_cache
= (arelent
*) bfd_zalloc (abfd
, (size_t)(count
* sizeof
1515 bfd_error
= no_memory
;
1519 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
1521 bfd_release (abfd
, reloc_cache
);
1525 if (bfd_read (relocs
, 1, reloc_size
, abfd
) != reloc_size
) {
1526 bfd_release (abfd
, relocs
);
1527 bfd_release (abfd
, reloc_cache
);
1528 bfd_error
= system_call_error
;
1532 if (each_size
== RELOC_EXT_SIZE
) {
1533 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
1534 unsigned int counter
= 0;
1535 arelent
*cache_ptr
= reloc_cache
;
1537 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++) {
1538 NAME(aout
,swap_ext_reloc_in
)(abfd
, rptr
, cache_ptr
, symbols
);
1541 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
1542 unsigned int counter
= 0;
1543 arelent
*cache_ptr
= reloc_cache
;
1545 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++) {
1546 NAME(aout
,swap_std_reloc_in
)(abfd
, rptr
, cache_ptr
, symbols
);
1551 bfd_release (abfd
,relocs
);
1552 asect
->relocation
= reloc_cache
;
1553 asect
->reloc_count
= count
;
1559 /* Write out a relocation section into an object file. */
1562 DEFUN(NAME(aout
,squirt_out_relocs
),(abfd
, section
),
1567 unsigned char *native
, *natptr
;
1570 unsigned int count
= section
->reloc_count
;
1573 if (count
== 0) return true;
1575 each_size
= obj_reloc_entry_size (abfd
);
1576 natsize
= each_size
* count
;
1577 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
1579 bfd_error
= no_memory
;
1583 generic
= section
->orelocation
;
1585 if (each_size
== RELOC_EXT_SIZE
)
1587 for (natptr
= native
;
1589 --count
, natptr
+= each_size
, ++generic
)
1590 NAME(aout
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*)natptr
);
1594 for (natptr
= native
;
1596 --count
, natptr
+= each_size
, ++generic
)
1597 NAME(aout
,swap_std_reloc_out
)(abfd
, *generic
, (struct reloc_std_external
*)natptr
);
1600 if ( bfd_write ((PTR
) native
, 1, natsize
, abfd
) != natsize
) {
1601 bfd_release(abfd
, native
);
1604 bfd_release (abfd
, native
);
1609 /* This is stupid. This function should be a boolean predicate */
1611 DEFUN(NAME(aout
,canonicalize_reloc
),(abfd
, section
, relptr
, symbols
),
1614 arelent
**relptr AND
1617 arelent
*tblptr
= section
->relocation
;
1620 if (!(tblptr
|| NAME(aout
,slurp_reloc_table
)(abfd
, section
, symbols
)))
1623 if (section
->flags
& SEC_CONSTRUCTOR
) {
1624 arelent_chain
*chain
= section
->constructor_chain
;
1625 for (count
= 0; count
< section
->reloc_count
; count
++) {
1626 *relptr
++ = &chain
->relent
;
1627 chain
= chain
->next
;
1631 tblptr
= section
->relocation
;
1632 if (!tblptr
) return 0;
1634 for (count
= 0; count
++ < section
->reloc_count
;)
1636 *relptr
++ = tblptr
++;
1641 return section
->reloc_count
;
1645 DEFUN(NAME(aout
,get_reloc_upper_bound
),(abfd
, asect
),
1649 if (bfd_get_format (abfd
) != bfd_object
) {
1650 bfd_error
= invalid_operation
;
1653 if (asect
->flags
& SEC_CONSTRUCTOR
) {
1654 return (sizeof (arelent
*) * (asect
->reloc_count
+1));
1658 if (asect
== obj_datasec (abfd
))
1659 return (sizeof (arelent
*) *
1660 ((exec_hdr(abfd
)->a_drsize
/ obj_reloc_entry_size (abfd
))
1663 if (asect
== obj_textsec (abfd
))
1664 return (sizeof (arelent
*) *
1665 ((exec_hdr(abfd
)->a_trsize
/ obj_reloc_entry_size (abfd
))
1668 bfd_error
= invalid_operation
;
1674 DEFUN(NAME(aout
,get_symtab_upper_bound
),(abfd
),
1677 if (!NAME(aout
,slurp_symbol_table
)(abfd
)) return 0;
1679 return (bfd_get_symcount (abfd
)+1) * (sizeof (aout_symbol_type
*));
1682 DEFUN(NAME(aout
,get_lineno
),(ignore_abfd
, ignore_symbol
),
1683 bfd
*ignore_abfd AND
1684 asymbol
*ignore_symbol
)
1686 return (alent
*)NULL
;
1691 DEFUN(NAME(aout
,print_symbol
),(ignore_abfd
, afile
, symbol
, how
),
1692 bfd
*ignore_abfd AND
1695 bfd_print_symbol_enum_type how
)
1697 FILE *file
= (FILE *)afile
;
1700 case bfd_print_symbol_name_enum
:
1701 fprintf(file
,"%s", symbol
->name
);
1703 case bfd_print_symbol_type_enum
:
1704 fprintf(file
,"%4x %2x %2x",(unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1705 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1706 (unsigned)(aout_symbol(symbol
)->type
));
1708 case bfd_print_symbol_all_enum
:
1710 CONST
char *section_name
= symbol
->section
== (asection
*)NULL
?
1711 "*abs" : symbol
->section
->name
;
1713 bfd_print_symbol_vandf((PTR
)file
,symbol
);
1715 fprintf(file
," %-5s %04x %02x %02x %s",
1717 (unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1718 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1719 (unsigned)(aout_symbol(symbol
)->type
& 0xff),
1727 provided a BFD, a section and an offset into the section, calculate
1728 and return the name of the source file and the line nearest to the
1733 DEFUN(NAME(aout
,find_nearest_line
),(abfd
,
1741 asection
*section AND
1742 asymbol
**symbols AND
1744 CONST
char **filename_ptr AND
1745 CONST
char **functionname_ptr AND
1746 unsigned int *line_ptr
)
1748 /* Run down the file looking for the filename, function and linenumber */
1750 static char buffer
[100];
1751 bfd_vma high_line_vma
= ~0;
1752 bfd_vma low_func_vma
= 0;
1754 *filename_ptr
= abfd
->filename
;
1755 *functionname_ptr
= 0;
1757 if (symbols
!= (asymbol
**)NULL
) {
1758 for (p
= symbols
; *p
; p
++) {
1759 aout_symbol_type
*q
= (aout_symbol_type
*)(*p
);
1762 *filename_ptr
= q
->symbol
.name
;
1763 if (obj_textsec(abfd
) != section
) {
1771 /* We'll keep this if it resolves nearer than the one we have already */
1772 if (q
->symbol
.value
>= offset
&&
1773 q
->symbol
.value
< high_line_vma
) {
1774 *line_ptr
= q
->desc
;
1775 high_line_vma
= q
->symbol
.value
;
1780 /* We'll keep this if it is nearer than the one we have already */
1781 if (q
->symbol
.value
>= low_func_vma
&&
1782 q
->symbol
.value
<= offset
) {
1783 low_func_vma
= q
->symbol
.value
;
1784 func
= (asymbol
*)q
;
1786 if (*line_ptr
&& func
) {
1787 CONST
char *function
= func
->name
;
1789 strncpy(buffer
, function
, sizeof(buffer
)-1);
1790 buffer
[sizeof(buffer
)-1] = 0;
1791 /* Have to remove : stuff */
1792 p
= strchr(buffer
,':');
1793 if (p
!= NULL
) { *p
= NULL
; }
1794 *functionname_ptr
= buffer
;
1809 DEFUN(NAME(aout
,sizeof_headers
),(ignore_abfd
, execable
),
1810 bfd
*ignore_abfd AND
1813 return EXEC_BYTES_SIZE
;