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
78 #define KEEPITTYPE int
91 void (*bfd_error_trap
)();
94 @subsection relocations
95 The file @code{aoutx.h} caters for both the @emph{standard} and
96 @emph{extended} forms of a.out relocation records.
98 The standard records are characterised by containing only an address,
99 a symbol index and a type field. The extended records (used on 29ks
100 and sparcs) also have a full integer for an addend.
102 #define CTOR_TABLE_RELOC_IDX 2
104 /* start-sanitize-v9 */
105 /* Provided the symbol, returns the value reffed */
107 DEFUN(get_symbol_value
,(symbol
, input_section
),
109 asection
*input_section
)
111 bfd_vma relocation
= 0;
113 if (symbol
!= (asymbol
*)NULL
) {
114 if (symbol
->flags
& BSF_FORT_COMM
) {
117 relocation
= symbol
->value
;
119 if (symbol
->section
!= (asection
*)NULL
) {
120 relocation
+= symbol
->section
->output_section
->vma
+
121 symbol
->section
->output_offset
;
125 /* No symbol, so use the input section value */
126 relocation
= input_section
->output_section
->vma
+ input_section
->output_offset
;
131 static bfd_reloc_status_enum_type
132 DEFUN(reloc64
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
134 arelent
*reloc_entry AND
135 asymbol
*symbol_in AND
136 unsigned char *data AND
137 asection
*input_section
)
139 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
140 bfd_vma value
= bfd_get_64(abfd
, (bfd_byte
*)data
+ reloc_entry
->address
);
141 value
+= sym_value
+ reloc_entry
->addend
;
142 bfd_put_64(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
146 static bfd_reloc_status_enum_type
147 DEFUN(disp64
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
149 arelent
*reloc_entry AND
150 asymbol
*symbol_in AND
151 unsigned char *data AND
152 asection
*input_section
)
154 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
156 /* bfd_get_64(abfd, (bfd_byte *)data + reloc_entry->address);*/
158 value
+= sym_value
+ reloc_entry
->addend
;
160 /* Subtract from the calculated value the pc */
161 value
-= reloc_entry
->address
+ input_section
->output_section
->vma
;
162 bfd_put_64(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
166 static bfd_reloc_status_enum_type
167 DEFUN(hhi22
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
169 arelent
*reloc_entry AND
170 asymbol
*symbol_in AND
171 unsigned char *data AND
172 asection
*input_section
)
174 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
176 bfd_vma value
= bfd_get_32(abfd
, (bfd_byte
*)data
+ reloc_entry
->address
);
178 value
= (value
& ~0x3fffff) | ( ((sym_value
+ reloc_entry
->addend
) >> 32+10) & 0x3fffff);
180 bfd_put_32(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
184 static bfd_reloc_status_enum_type
185 DEFUN(hlo10
,(abfd
, reloc_entry
, symbol_in
, data
, input_section
),
187 arelent
*reloc_entry AND
188 asymbol
*symbol_in AND
189 unsigned char *data AND
190 asection
*input_section
)
192 bfd_vma sym_value
= get_symbol_value(symbol_in
, input_section
);
194 bfd_vma value
= bfd_get_32(abfd
, (bfd_byte
*)data
+ reloc_entry
->address
);
196 value
= (value
& ~0x3ff) | (((sym_value
+ reloc_entry
->addend
) >> 32) & 0x3ff);
198 bfd_put_32(abfd
, value
, (bfd_byte
*)data
+reloc_entry
->address
);
202 static bfd_reloc_status_enum_type
208 /* end-sanitize-v9 */
210 static reloc_howto_type howto_table_ext
[] =
212 HOWTO(RELOC_8
, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false),
213 HOWTO(RELOC_16
, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false),
214 HOWTO(RELOC_32
, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false),
215 HOWTO(RELOC_DISP8
, 0, 0, 8, true, 0, false, true,0,"DISP8", false, 0,0x000000ff, false),
216 HOWTO(RELOC_DISP16
, 0, 1, 16, true, 0, false, true,0,"DISP16", false, 0,0x0000ffff, false),
217 HOWTO(RELOC_DISP32
, 0, 2, 32, true, 0, false, true,0,"DISP32", false, 0,0xffffffff, false),
218 HOWTO(RELOC_WDISP30
,2, 2, 30, true, 0, false, true,0,"WDISP30", false, 0,0x3fffffff, false),
219 HOWTO(RELOC_WDISP22
,2, 2, 22, true, 0, false, true,0,"WDISP22", false, 0,0x003fffff, false),
220 HOWTO(RELOC_HI22
, 10, 2, 22, false, 0, false, true,0,"HI22", false, 0,0x003fffff, false),
221 HOWTO(RELOC_22
, 0, 2, 22, false, 0, false, true,0,"22", false, 0,0x003fffff, false),
222 HOWTO(RELOC_13
, 0, 2, 13, false, 0, false, true,0,"13", false, 0,0x00001fff, false),
223 HOWTO(RELOC_LO10
, 0, 2, 10, false, 0, false, true,0,"LO10", false, 0,0x000003ff, false),
224 HOWTO(RELOC_SFA_BASE
,0, 2, 32, false, 0, false, true,0,"SFA_BASE", false, 0,0xffffffff, false),
225 HOWTO(RELOC_SFA_OFF13
,0,2, 32, false, 0, false, true,0,"SFA_OFF13",false, 0,0xffffffff, false),
226 HOWTO(RELOC_BASE10
, 0, 2, 16, false, 0, false, true,0,"BASE10", false, 0,0x0000ffff, false),
227 HOWTO(RELOC_BASE13
, 0, 2, 13, false, 0, false, true,0,"BASE13", false, 0,0x00001fff, false),
228 HOWTO(RELOC_BASE22
, 0, 2, 0, false, 0, false, true,0,"BASE22", false, 0,0x00000000, false),
229 HOWTO(RELOC_PC10
, 0, 2, 10, false, 0, false, true,0,"PC10", false, 0,0x000003ff, false),
230 HOWTO(RELOC_PC22
, 0, 2, 22, false, 0, false, true,0,"PC22", false, 0,0x003fffff, false),
231 HOWTO(RELOC_JMP_TBL
,0, 2, 32, false, 0, false, true,0,"JMP_TBL", false, 0,0xffffffff, false),
232 HOWTO(RELOC_SEGOFF16
,0, 2, 0, false, 0, false, true,0,"SEGOFF16", false, 0,0x00000000, false),
233 HOWTO(RELOC_GLOB_DAT
,0, 2, 0, false, 0, false, true,0,"GLOB_DAT", false, 0,0x00000000, false),
234 HOWTO(RELOC_JMP_SLOT
,0, 2, 0, false, 0, false, true,0,"JMP_SLOT", false, 0,0x00000000, false),
235 HOWTO(RELOC_RELATIVE
,0, 2, 0, false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
237 /* start-sanitize-v9 */
239 HOWTO(RELOC_11
, 0, 2, 21, true, 0, false, true,r64
,"11", false, 0,/*0x00000000001fffff*/0, false),
240 HOWTO(RELOC_WDISP2_14
, 0, 2, 21, true, 0, false, true,r64
,"DISP2_14",false, 0,/*0x00000000001fffff*/0, false),
241 HOWTO(RELOC_WDISP19
, 0, 3, 64, true, 0, false, true,r64
,"DISP19", false, 0,/*0xffffffffffffffff*/0, false),
242 HOWTO(RELOC_HHI22
, 42, 3, 22, false, 0, false, true,hhi22
,"HHI22",false, 0,/*0x003fffff00000000*/0, false),
243 HOWTO(RELOC_HLO10
, 32, 3, 10, false, 0, false, true,hlo10
,"HLO10", false, 0,/*0x000003ff00000000*/0, false),
245 HOWTO(RELOC_JUMPTARG
,2, 13, 16, true, 0, false, true,0,"JUMPTARG", false, 0,0x0000ffff, false),
246 HOWTO(RELOC_CONST
, 0, 13, 16, false, 0, false, true,0,"CONST", false, 0,0x0000ffff, false),
247 HOWTO(RELOC_CONSTH
, 16, 13, 16, false, 0, false, true,0,"CONSTH", false, 0,0x0000ffff, false),
250 HOWTO(RELOC_64
, 0, 3, 64, false, 0, true, true,reloc64
,"64", false, 0,/*0xffffffffffffffff*/0, false),
251 HOWTO(RELOC_DISP64
, 0, 3, 64, true, 0, false, true,disp64
,"DISP64", false, 0,/*0xffffffffffffffff*/0, false),
252 HOWTO(RELOC_WDISP21
,2, 2, 21, true, 0, false, true,r64
,"WDISP21",false, 0,/*0x00000000001fffff*/0, false),
253 HOWTO(RELOC_DISP21
, 0, 2, 21, true, 0, false, true,r64
,"DISP21", false, 0,/*0x00000000001fffff*/0, false),
254 HOWTO(RELOC_DISP14
, 0, 2, 14, true, 0, false, true,r64
,"DISP21", false, 0,/*0x0000000000003fff*/0, false),
256 /* end-sanitize-v9 */
259 /* Convert standard reloc records to "arelent" format (incl byte swap). */
261 static reloc_howto_type howto_table_std
[] = {
262 /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */
263 HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
264 HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
265 HOWTO( 2, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
266 HOWTO( 3, 0, 3, 64, false, 0, true, true,0,"64", true, 0xdeaddead,0xdeaddead, false),
267 HOWTO( 4, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
268 HOWTO( 5, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
269 HOWTO( 6, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
270 HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedface,0xfeedface, false),
274 bfd_error_vector_type bfd_error_vector
;
277 @subsection Internal Entry Points
278 @code{aoutx.h} exports several routines for accessing the contents of
279 an a.out file, which are gathered and exported in turn by various
280 format specific files (eg sunos.c).
284 *i aout_<size>_swap_exec_header_in
285 Swaps the information in an executable header taken from a raw byte stream memory image,
286 into the internal exec_header structure.
287 *; PROTO(void, aout_<size>_swap_exec_header_in,
289 struct external_exec *raw_bytes,
290 struct internal_exec *execp));
294 DEFUN(NAME(aout
,swap_exec_header_in
),(abfd
, raw_bytes
, execp
),
296 struct external_exec
*raw_bytes AND
297 struct internal_exec
*execp
)
299 struct external_exec
*bytes
= (struct external_exec
*)raw_bytes
;
301 /* Now fill in fields in the execp, from the bytes in the raw data. */
302 execp
->a_info
= bfd_h_get_32 (abfd
, bytes
->e_info
);
303 execp
->a_text
= GET_WORD (abfd
, bytes
->e_text
);
304 execp
->a_data
= GET_WORD (abfd
, bytes
->e_data
);
305 execp
->a_bss
= GET_WORD (abfd
, bytes
->e_bss
);
306 execp
->a_syms
= GET_WORD (abfd
, bytes
->e_syms
);
307 execp
->a_entry
= GET_WORD (abfd
, bytes
->e_entry
);
308 execp
->a_trsize
= GET_WORD (abfd
, bytes
->e_trsize
);
309 execp
->a_drsize
= GET_WORD (abfd
, bytes
->e_drsize
);
313 *i aout_<size>_swap_exec_header_out
314 Swaps the information in an internal exec header structure into the
315 supplied buffer ready for writing to disk.
316 *; PROTO(void, aout_<size>_swap_exec_header_out,
318 struct internal_exec *execp,
319 struct external_exec *raw_bytes));
322 DEFUN(NAME(aout
,swap_exec_header_out
),(abfd
, execp
, raw_bytes
),
324 struct internal_exec
*execp AND
325 struct external_exec
*raw_bytes
)
327 struct external_exec
*bytes
= (struct external_exec
*)raw_bytes
;
329 /* Now fill in fields in the raw data, from the fields in the exec struct. */
330 bfd_h_put_32 (abfd
, execp
->a_info
, bytes
->e_info
);
331 PUT_WORD (abfd
, execp
->a_text
, bytes
->e_text
);
332 PUT_WORD (abfd
, execp
->a_data
, bytes
->e_data
);
333 PUT_WORD (abfd
, execp
->a_bss
, bytes
->e_bss
);
334 PUT_WORD (abfd
, execp
->a_syms
, bytes
->e_syms
);
335 PUT_WORD (abfd
, execp
->a_entry
, bytes
->e_entry
);
336 PUT_WORD (abfd
, execp
->a_trsize
, bytes
->e_trsize
);
337 PUT_WORD (abfd
, execp
->a_drsize
, bytes
->e_drsize
);
342 struct internal_exec e
;
347 *i aout_<size>_some_aout_object_p
349 Some A.OUT variant thinks that the file whose format we're checking
350 is an a.out file. Do some more checking, and set up for access if
351 it really is. Call back to the calling environments "finish up"
352 function just before returning, to handle any last-minute setup.
354 *; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
356 bfd_target *(*callback_to_real_object_p)()));
360 DEFUN(NAME(aout
,some_aout_object_p
),(abfd
, callback_to_real_object_p
),
362 bfd_target
*(*callback_to_real_object_p
) ())
364 struct external_exec exec_bytes
;
365 struct internal_exec
*execp
;
366 struct container
*rawptr
;
368 if (bfd_seek (abfd
, 0L, false) < 0) {
369 bfd_error
= system_call_error
;
373 if (bfd_read ((PTR
) &exec_bytes
, 1, EXEC_BYTES_SIZE
, abfd
)
374 != EXEC_BYTES_SIZE
) {
375 bfd_error
= wrong_format
;
379 /* Use an intermediate variable for clarity */
380 rawptr
= (struct container
*) bfd_zalloc (abfd
, sizeof (struct container
));
382 if (rawptr
== NULL
) {
383 bfd_error
= no_memory
;
387 set_tdata (abfd
, rawptr
);
388 exec_hdr (abfd
) = execp
= &(rawptr
->e
);
389 NAME(aout
,swap_exec_header_in
)(abfd
, &exec_bytes
, execp
);
391 /* Set the file flags */
392 abfd
->flags
= NO_FLAGS
;
393 if (execp
->a_drsize
|| execp
->a_trsize
)
394 abfd
->flags
|= HAS_RELOC
;
396 abfd
->flags
|= EXEC_P
;
398 abfd
->flags
|= HAS_LINENO
| HAS_DEBUG
| HAS_SYMS
| HAS_LOCALS
;
400 if (N_MAGIC (*execp
) == ZMAGIC
) abfd
->flags
|= D_PAGED
;
401 if (N_MAGIC (*execp
) == NMAGIC
) abfd
->flags
|= WP_TEXT
;
403 bfd_get_start_address (abfd
) = execp
->a_entry
;
405 obj_aout_symbols (abfd
) = (aout_symbol_type
*)NULL
;
406 bfd_get_symcount (abfd
) = execp
->a_syms
/ sizeof (struct external_nlist
);
408 /* Set the default architecture and machine type. These can be
409 overridden in the callback routine. */
410 abfd
->obj_arch
= bfd_arch_unknown
;
411 abfd
->obj_machine
= 0;
413 /* The default relocation entry size is that of traditional V7 Unix. */
414 obj_reloc_entry_size (abfd
) = RELOC_STD_SIZE
;
416 /* create the sections. This is raunchy, but bfd_close wants to reclaim
418 obj_textsec (abfd
) = (asection
*)NULL
;
419 obj_datasec (abfd
) = (asection
*)NULL
;
420 obj_bsssec (abfd
) = (asection
*)NULL
;
421 (void)bfd_make_section(abfd
, ".text");
422 (void)bfd_make_section(abfd
, ".data");
423 (void)bfd_make_section(abfd
, ".bss");
425 abfd
->sections
= obj_textsec (abfd
);
426 obj_textsec (abfd
)->next
= obj_datasec (abfd
);
427 obj_datasec (abfd
)->next
= obj_bsssec (abfd
);
429 obj_datasec (abfd
)->size
= execp
->a_data
;
430 obj_bsssec (abfd
)->size
= execp
->a_bss
;
431 obj_textsec (abfd
)->size
= execp
->a_text
;
433 if (abfd
->flags
& D_PAGED
) {
434 obj_textsec (abfd
)->size
-= EXEC_BYTES_SIZE
;
438 obj_textsec (abfd
)->flags
= (execp
->a_trsize
!= 0 ?
439 (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_HAS_CONTENTS
) :
440 (SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
));
441 obj_datasec (abfd
)->flags
= (execp
->a_drsize
!= 0 ?
442 (SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_HAS_CONTENTS
) :
443 (SEC_ALLOC
| SEC_LOAD
| SEC_HAS_CONTENTS
));
444 obj_bsssec (abfd
)->flags
= SEC_ALLOC
;
446 #ifdef THIS_IS_ONLY_DOCUMENTATION
447 /* Call back to the format-dependent code to fill in the rest of the
448 fields and do any further cleanup. Things that should be filled
449 in by the callback: */
451 struct exec
*execp
= exec_hdr (abfd
);
453 /* The virtual memory addresses of the sections */
454 obj_datasec (abfd
)->vma
= N_DATADDR(*execp
);
455 obj_bsssec (abfd
)->vma
= N_BSSADDR(*execp
);
456 obj_textsec (abfd
)->vma
= N_TXTADDR(*execp
);
458 /* The file offsets of the sections */
459 obj_textsec (abfd
)->filepos
= N_TXTOFF(*execp
);
460 obj_datasec (abfd
)->filepos
= N_DATOFF(*execp
);
462 /* The file offsets of the relocation info */
463 obj_textsec (abfd
)->rel_filepos
= N_TRELOFF(*execp
);
464 obj_datasec (abfd
)->rel_filepos
= N_DRELOFF(*execp
);
466 /* The file offsets of the string table and symbol table. */
467 obj_str_filepos (abfd
) = N_STROFF (*execp
);
468 obj_sym_filepos (abfd
) = N_SYMOFF (*execp
);
470 /* This common code can't fill in those things because they depend
471 on either the start address of the text segment, the rounding
472 up of virtual addersses between segments, or the starting file
473 position of the text segment -- all of which varies among different
474 versions of a.out. */
476 /* Determine the architecture and machine type of the object file. */
477 switch (N_MACHTYPE (*exec_hdr (abfd
))) {
479 abfd
->obj_arch
= bfd_arch_obscure
;
483 /* Determine the size of a relocation entry */
484 switch (abfd
->obj_arch
) {
487 obj_reloc_entry_size (abfd
) = RELOC_EXT_SIZE
;
489 obj_reloc_entry_size (abfd
) = RELOC_STD_SIZE
;
494 /* The architecture is encoded in various ways in various a.out variants,
495 or is not encoded at all in some of them. The relocation size depends
496 on the architecture and the a.out variant. Finally, the return value
497 is the bfd_target vector in use. If an error occurs, return zero and
498 set bfd_error to the appropriate error code.
500 Formats such as b.out, which have additional fields in the a.out
501 header, should cope with them in this callback as well. */
502 #endif /* DOCUMENTATION */
505 return (*callback_to_real_object_p
)(abfd
);
509 *i aout_<size>_mkobject
511 This routine initializes a BFD for use with a.out files.
513 *; PROTO(boolean, aout_<size>_mkobject, (bfd *));
517 DEFUN(NAME(aout
,mkobject
),(abfd
),
520 struct container
*rawptr
;
522 bfd_error
= system_call_error
;
524 /* Use an intermediate variable for clarity */
525 rawptr
= (struct container
*)bfd_zalloc (abfd
, sizeof (struct container
));
527 if (rawptr
== NULL
) {
528 bfd_error
= no_memory
;
532 set_tdata (abfd
, rawptr
);
533 exec_hdr (abfd
) = &(rawptr
->e
);
535 /* For simplicity's sake we just make all the sections right here. */
537 obj_textsec (abfd
) = (asection
*)NULL
;
538 obj_datasec (abfd
) = (asection
*)NULL
;
539 obj_bsssec (abfd
) = (asection
*)NULL
;
540 bfd_make_section (abfd
, ".text");
541 bfd_make_section (abfd
, ".data");
542 bfd_make_section (abfd
, ".bss");
549 *i aout_<size>_machine_type
551 Keep track of machine architecture and machine type for a.out's.
552 Return the machine_type for a particular arch&machine, or M_UNKNOWN
553 if that exact arch&machine can't be represented in a.out format.
555 If the architecture is understood, machine type 0 (default) should
556 always be understood.
558 *; PROTO(enum machine_type, aout_<size>_machine_type,
559 (enum bfd_architecture arch,
560 unsigned long machine));
564 DEFUN(NAME(aout
,machine_type
),(arch
, machine
),
565 enum bfd_architecture arch AND
566 unsigned long machine
)
568 enum machine_type arch_flags
;
570 arch_flags
= M_UNKNOWN
;
574 if (machine
== 0) arch_flags
= M_SPARC
;
579 case 0: arch_flags
= M_68010
; break;
580 case 68000: arch_flags
= M_UNKNOWN
; break;
581 case 68010: arch_flags
= M_68010
; break;
582 case 68020: arch_flags
= M_68020
; break;
583 default: arch_flags
= M_UNKNOWN
; break;
588 if (machine
== 0) arch_flags
= M_386
;
592 if (machine
== 0) arch_flags
= M_29K
;
596 arch_flags
= M_UNKNOWN
;
603 *i aout_<size>_set_arch_mach
605 Sets the architecture and the machine of the BFD to those values
606 supplied. Verifies that the format can support the architecture
609 *; PROTO(boolean, aout_<size>_set_arch_mach,
611 enum bfd_architecture,
612 unsigned long machine));
616 DEFUN(NAME(aout
,set_arch_mach
),(abfd
, arch
, machine
),
618 enum bfd_architecture arch AND
619 unsigned long machine
)
621 abfd
->obj_arch
= arch
;
622 abfd
->obj_machine
= machine
;
623 if (arch
!= bfd_arch_unknown
&&
624 NAME(aout
,machine_type
) (arch
, machine
) == M_UNKNOWN
)
625 return false; /* We can't represent this type */
626 return true; /* We're easy ... */
630 *i aout_<size>new_section_hook
632 Called by the BFD in response to a @code{bfd_make_section} request.
633 *; PROTO(boolean, aout_<size>_new_section_hook,
638 DEFUN(NAME(aout
,new_section_hook
),(abfd
, newsect
),
642 /* align to double at least */
643 newsect
->alignment_power
= 3;
645 if (bfd_get_format (abfd
) == bfd_object
) {
646 if (obj_textsec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".text")) {
647 obj_textsec(abfd
)= newsect
;
651 if (obj_datasec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".data")) {
652 obj_datasec(abfd
) = newsect
;
656 if (obj_bsssec(abfd
) == NULL
&& !strcmp(newsect
->name
, ".bss")) {
657 obj_bsssec(abfd
) = newsect
;
662 /* We allow more than three sections internally */
667 DEFUN(NAME(aout
,set_section_contents
),(abfd
, section
, location
, offset
, count
),
674 if (abfd
->output_has_begun
== false)
675 { /* set by bfd.c handler */
676 if ((obj_textsec (abfd
) == NULL
) || (obj_datasec (abfd
) == NULL
))
678 bfd_error
= invalid_operation
;
681 /* if (abfd->flags & D_PAGED) {
682 obj_textsec(abfd)->filepos = 0;
685 obj_textsec(abfd
)->filepos
= EXEC_BYTES_SIZE
;
687 obj_textsec(abfd
)->size
= align_power(obj_textsec(abfd
)->size
,
688 obj_textsec(abfd
)->alignment_power
);
689 obj_datasec(abfd
)->filepos
= obj_textsec (abfd
)->size
+ EXEC_BYTES_SIZE
;
690 obj_datasec(abfd
)->size
= align_power(obj_datasec(abfd
)->size
,
691 obj_datasec(abfd
)->alignment_power
);
695 /* regardless, once we know what we're doing, we might as well get going */
696 if (section
!= obj_bsssec(abfd
))
698 bfd_seek (abfd
, section
->filepos
+ offset
, SEEK_SET
);
701 return (bfd_write ((PTR
)location
, 1, count
, abfd
) == count
) ?
709 /* Classify stabs symbols */
711 #define sym_in_text_section(sym) \
712 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
714 #define sym_in_data_section(sym) \
715 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
717 #define sym_in_bss_section(sym) \
718 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
720 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
721 zero in the "value" field. Nonzeroes there are fortrancommon
723 #define sym_is_undefined(sym) \
724 ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
726 /* Symbol is a global definition if N_EXT is on and if it has
727 a nonzero type field. */
728 #define sym_is_global_defn(sym) \
729 (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
731 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
733 #define sym_is_debugger_info(sym) \
734 ((sym)->type & ~(N_EXT | N_TYPE))
736 #define sym_is_fortrancommon(sym) \
737 (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
739 /* Symbol is absolute if it has N_ABS set */
740 #define sym_is_absolute(sym) \
741 (((sym)->type & N_TYPE)== N_ABS)
744 #define sym_is_indirect(sym) \
745 (((sym)->type & N_ABS)== N_ABS)
747 /* Only in their own functions for ease of debugging; when sym flags have
748 stabilised these should be inlined into their (single) caller */
751 DEFUN(translate_from_native_sym_flags
,(sym_pointer
, cache_ptr
, abfd
),
752 struct external_nlist
*sym_pointer AND
753 aout_symbol_type
*cache_ptr AND
756 switch (cache_ptr
->type
& N_TYPE
) {
762 char *copy
= bfd_alloc(abfd
, strlen(cache_ptr
->symbol
.name
)+1);
764 arelent_chain
*reloc
= (arelent_chain
*)bfd_alloc(abfd
, sizeof(arelent_chain
));
765 strcpy(copy
, cache_ptr
->symbol
.name
);
766 section
= bfd_make_section(abfd
,copy
);
767 switch ( (cache_ptr
->type
& N_TYPE
) ) {
769 section
->flags
= SEC_CONSTRUCTOR
;
770 reloc
->relent
.section
= (asection
*)NULL
;
771 cache_ptr
->symbol
.section
= (asection
*)NULL
;
774 section
->flags
= SEC_CONSTRUCTOR_TEXT
;
775 reloc
->relent
.section
= (asection
*)obj_textsec(abfd
);
776 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
779 section
->flags
= SEC_CONSTRUCTOR_DATA
;
780 reloc
->relent
.section
= (asection
*)obj_datasec(abfd
);
781 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
784 section
->flags
= SEC_CONSTRUCTOR_BSS
;
785 reloc
->relent
.section
= (asection
*)obj_bsssec(abfd
);
786 cache_ptr
->symbol
.value
-= reloc
->relent
.section
->vma
;
789 cache_ptr
->symbol
.section
= reloc
->relent
.section
;
790 reloc
->relent
.addend
= cache_ptr
->symbol
.value
;
792 /* We modify the symbol to belong to a section depending upon the
793 name of the symbol - probably __CTOR__ or __DTOR__ but we don't
794 really care, and add to the size of the section to contain a
795 pointer to the symbol. Build a reloc entry to relocate to this
796 symbol attached to this section. */
799 section
->reloc_count
++;
800 section
->alignment_power
= 2;
801 reloc
->relent
.sym_ptr_ptr
= (asymbol
**)NULL
;
802 reloc
->next
= section
->constructor_chain
;
803 section
->constructor_chain
= reloc
;
804 reloc
->relent
.address
= section
->size
;
805 section
->size
+= sizeof(int *);
807 reloc
->relent
.howto
= howto_table_ext
+CTOR_TABLE_RELOC_IDX
;
808 cache_ptr
->symbol
.flags
|= BSF_DEBUGGING
| BSF_CONSTRUCTOR
;
812 if (cache_ptr
->type
== N_WARNING
)
814 /* This symbol is the text of a warning message, the next symbol
815 is the symbol to associate the warning with */
816 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
| BSF_WARNING
;
817 cache_ptr
->symbol
.value
= (bfd_vma
)((cache_ptr
+1));
818 /* We furgle with the next symbol in place. We don't want it to be undefined, we'll trample the type */
819 (sym_pointer
+1)->e_type
[0] = 0xff;
822 if ((cache_ptr
->type
| N_EXT
) == (N_INDR
| N_EXT
)) {
823 /* Two symbols in a row for an INDR message. The first symbol
824 contains the name we will match, the second symbol contains the
825 name the first name is translated into. It is supplied to us
826 undefined. This is good, since we want to pull in any files which
828 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
| BSF_INDIRECT
;
829 cache_ptr
->symbol
.value
= (bfd_vma
)((cache_ptr
+1));
834 if (sym_is_debugger_info (cache_ptr
)) {
835 cache_ptr
->symbol
.flags
= BSF_DEBUGGING
;
836 /* Work out the section correct for this symbol */
837 switch (cache_ptr
->type
& N_TYPE
)
841 cache_ptr
->symbol
.section
= obj_textsec (abfd
);
842 cache_ptr
->symbol
.value
-= obj_textsec(abfd
)->vma
;
845 cache_ptr
->symbol
.value
-= obj_datasec(abfd
)->vma
;
846 cache_ptr
->symbol
.section
= obj_datasec (abfd
);
849 cache_ptr
->symbol
.section
= obj_bsssec (abfd
);
850 cache_ptr
->symbol
.value
-= obj_bsssec(abfd
)->vma
;
854 cache_ptr
->symbol
.section
= 0;
860 if (sym_is_fortrancommon (cache_ptr
))
862 cache_ptr
->symbol
.flags
= BSF_FORT_COMM
;
863 cache_ptr
->symbol
.section
= (asection
*)NULL
;
866 if (sym_is_undefined (cache_ptr
)) {
867 cache_ptr
->symbol
.flags
= BSF_UNDEFINED
;
869 else if (sym_is_global_defn (cache_ptr
)) {
870 cache_ptr
->symbol
.flags
= BSF_GLOBAL
| BSF_EXPORT
;
873 else if (sym_is_absolute (cache_ptr
)) {
874 cache_ptr
->symbol
.flags
= BSF_ABSOLUTE
;
877 cache_ptr
->symbol
.flags
= BSF_LOCAL
;
880 /* In a.out, the value of a symbol is always relative to the
881 * start of the file, if this is a data symbol we'll subtract
882 * the size of the text section to get the section relative
883 * value. If this is a bss symbol (which would be strange)
884 * we'll subtract the size of the previous two sections
885 * to find the section relative address.
888 if (sym_in_text_section (cache_ptr
)) {
889 cache_ptr
->symbol
.value
-= obj_textsec(abfd
)->vma
;
890 cache_ptr
->symbol
.section
= obj_textsec (abfd
);
892 else if (sym_in_data_section (cache_ptr
)){
893 cache_ptr
->symbol
.value
-= obj_datasec(abfd
)->vma
;
894 cache_ptr
->symbol
.section
= obj_datasec (abfd
);
896 else if (sym_in_bss_section(cache_ptr
)) {
897 cache_ptr
->symbol
.section
= obj_bsssec (abfd
);
898 cache_ptr
->symbol
.value
-= obj_bsssec(abfd
)->vma
;
901 cache_ptr
->symbol
.section
= (asection
*)NULL
;
902 cache_ptr
->symbol
.flags
|= BSF_ABSOLUTE
;
910 DEFUN(translate_to_native_sym_flags
,(sym_pointer
, cache_ptr
, abfd
),
911 struct external_nlist
*sym_pointer AND
912 asymbol
*cache_ptr AND
915 bfd_vma value
= cache_ptr
->value
;
917 if (bfd_get_section(cache_ptr
)) {
918 if (bfd_get_output_section(cache_ptr
) == obj_bsssec (abfd
)) {
919 sym_pointer
->e_type
[0] |= N_BSS
;
921 else if (bfd_get_output_section(cache_ptr
) == obj_datasec (abfd
)) {
922 sym_pointer
->e_type
[0] |= N_DATA
;
924 else if (bfd_get_output_section(cache_ptr
) == obj_textsec (abfd
)) {
925 sym_pointer
->e_type
[0] |= N_TEXT
;
928 bfd_error_vector
.nonrepresentable_section(abfd
,
929 bfd_get_output_section(cache_ptr
)->name
);
931 /* Turn the symbol from section relative to absolute again */
934 cache_ptr
->section
->output_section
->vma
935 + cache_ptr
->section
->output_offset
;
938 sym_pointer
->e_type
[0] |= N_ABS
;
940 if (cache_ptr
->flags
& (BSF_WARNING
)) {
941 (sym_pointer
+1)->e_type
[0] = 1;
943 if (cache_ptr
->flags
& (BSF_FORT_COMM
| BSF_UNDEFINED
)) {
944 sym_pointer
->e_type
[0] = (N_UNDF
| N_EXT
);
947 if (cache_ptr
->flags
& BSF_ABSOLUTE
) {
948 sym_pointer
->e_type
[0] |= N_ABS
;
951 if (cache_ptr
->flags
& (BSF_GLOBAL
| BSF_EXPORT
)) {
952 sym_pointer
->e_type
[0] |= N_EXT
;
954 if (cache_ptr
->flags
& BSF_DEBUGGING
) {
955 sym_pointer
->e_type
[0]= ((aout_symbol_type
*)cache_ptr
)->type
;
958 PUT_WORD(abfd
, value
, sym_pointer
->e_value
);
961 /* Native-level interface to symbols. */
963 /* We read the symbols into a buffer, which is discarded when this
964 function exits. We read the strings into a buffer large enough to
965 hold them all plus all the cached symbol entries. */
968 DEFUN(NAME(aout
,make_empty_symbol
),(abfd
),
971 aout_symbol_type
*new =
972 (aout_symbol_type
*)bfd_zalloc (abfd
, sizeof (aout_symbol_type
));
973 new->symbol
.the_bfd
= abfd
;
979 DEFUN(NAME(aout
,slurp_symbol_table
),(abfd
),
982 bfd_size_type symbol_size
;
983 bfd_size_type string_size
;
984 unsigned char string_chars
[BYTES_IN_WORD
];
985 struct external_nlist
*syms
;
987 aout_symbol_type
*cached
;
989 /* If there's no work to be done, don't do any */
990 if (obj_aout_symbols (abfd
) != (aout_symbol_type
*)NULL
) return true;
991 symbol_size
= exec_hdr(abfd
)->a_syms
;
992 if (symbol_size
== 0) {
993 bfd_error
= no_symbols
;
997 bfd_seek (abfd
, obj_str_filepos (abfd
), SEEK_SET
);
998 if (bfd_read ((PTR
)string_chars
, BYTES_IN_WORD
, 1, abfd
) != BYTES_IN_WORD
)
1000 string_size
= GET_WORD (abfd
, string_chars
);
1002 strings
=(char *) bfd_alloc(abfd
, string_size
+ 1);
1003 cached
= (aout_symbol_type
*)
1004 bfd_zalloc(abfd
, (bfd_size_type
)(bfd_get_symcount (abfd
) * sizeof(aout_symbol_type
)));
1006 /* malloc this, so we can free it if simply. The symbol caching
1007 might want to allocate onto the bfd's obstack */
1008 syms
= (struct external_nlist
*) malloc(symbol_size
);
1009 bfd_seek (abfd
, obj_sym_filepos (abfd
), SEEK_SET
);
1010 if (bfd_read ((PTR
)syms
, 1, symbol_size
, abfd
) != symbol_size
) {
1012 if (syms
) free (syms
);
1013 if (cached
) bfd_release (abfd
, cached
);
1014 if (strings
)bfd_release (abfd
, strings
);
1018 bfd_seek (abfd
, obj_str_filepos (abfd
), SEEK_SET
);
1019 if (bfd_read ((PTR
)strings
, 1, string_size
, abfd
) != string_size
) {
1023 /* OK, now walk the new symtable, cacheing symbol properties */
1025 register struct external_nlist
*sym_pointer
;
1026 register struct external_nlist
*sym_end
= syms
+ bfd_get_symcount (abfd
);
1027 register aout_symbol_type
*cache_ptr
= cached
;
1029 /* Run through table and copy values */
1030 for (sym_pointer
= syms
, cache_ptr
= cached
;
1031 sym_pointer
< sym_end
; sym_pointer
++, cache_ptr
++)
1033 bfd_vma x
= GET_WORD(abfd
, sym_pointer
->e_strx
);
1034 cache_ptr
->symbol
.the_bfd
= abfd
;
1036 cache_ptr
->symbol
.name
= x
+ strings
;
1038 cache_ptr
->symbol
.name
= (char *)NULL
;
1040 cache_ptr
->symbol
.value
= GET_SWORD(abfd
, sym_pointer
->e_value
);
1041 cache_ptr
->desc
= bfd_get_16(abfd
, sym_pointer
->e_desc
);
1042 cache_ptr
->other
=bfd_get_8(abfd
, sym_pointer
->e_other
);
1043 cache_ptr
->type
= bfd_get_8(abfd
, sym_pointer
->e_type
);
1044 cache_ptr
->symbol
.udata
= 0;
1045 translate_from_native_sym_flags (sym_pointer
, cache_ptr
, abfd
);
1049 obj_aout_symbols (abfd
) = cached
;
1057 DEFUN(NAME(aout
,write_syms
),(abfd
),
1060 unsigned int count
;
1061 asymbol
**generic
= bfd_get_outsymbols (abfd
);
1063 bfd_size_type stindex
= BYTES_IN_WORD
; /* initial string length */
1065 for (count
= 0; count
< bfd_get_symcount (abfd
); count
++) {
1066 asymbol
*g
= generic
[count
];
1067 struct external_nlist nsp
;
1071 unsigned int length
= strlen(g
->name
) +1;
1072 PUT_WORD (abfd
, stindex
, (unsigned char *)nsp
.e_strx
);
1076 PUT_WORD (abfd
, 0, (unsigned char *)nsp
.e_strx
);
1079 if (g
->the_bfd
->xvec
->flavour
== abfd
->xvec
->flavour
)
1081 bfd_h_put_16(abfd
, aout_symbol(g
)->desc
, nsp
.e_desc
);
1082 bfd_h_put_8(abfd
, aout_symbol(g
)->other
, nsp
.e_other
);
1083 bfd_h_put_8(abfd
, aout_symbol(g
)->type
, nsp
.e_type
);
1087 bfd_h_put_16(abfd
,0, nsp
.e_desc
);
1088 bfd_h_put_8(abfd
, 0, nsp
.e_other
);
1089 bfd_h_put_8(abfd
, 0, nsp
.e_type
);
1094 translate_to_native_sym_flags (&nsp
, g
, abfd
);
1096 bfd_write((PTR
)&nsp
,1,EXTERNAL_LIST_SIZE
, abfd
);
1100 /* Now output the strings. Be sure to put string length into correct
1101 * byte ordering before writing it.
1104 char buffer
[BYTES_IN_WORD
];
1105 PUT_WORD (abfd
, stindex
, (unsigned char *)buffer
);
1107 bfd_write((PTR
)buffer
, 1, BYTES_IN_WORD
, abfd
);
1109 generic
= bfd_get_outsymbols(abfd
);
1110 for (count
= 0; count
< bfd_get_symcount(abfd
); count
++)
1112 asymbol
*g
= *(generic
++);
1116 size_t length
= strlen(g
->name
)+1;
1117 bfd_write((PTR
)g
->name
, 1, length
, abfd
);
1119 if ((g
->flags
& BSF_FAKE
)==0) {
1120 g
->KEEPIT
= (KEEPITTYPE
) count
;
1128 DEFUN(NAME(aout
,get_symtab
),(abfd
, location
),
1132 unsigned int counter
= 0;
1133 aout_symbol_type
*symbase
;
1135 if (!NAME(aout
,slurp_symbol_table
)(abfd
)) return 0;
1137 for (symbase
= obj_aout_symbols(abfd
); counter
++ < bfd_get_symcount (abfd
);)
1138 *(location
++) = (asymbol
*)( symbase
++);
1140 return bfd_get_symcount(abfd
);
1144 /* Standard reloc stuff */
1145 /* Output standard relocation information to a file in target byte order. */
1148 DEFUN(NAME(aout
,swap_std_reloc_out
),(abfd
, g
, natptr
),
1151 struct reloc_std_external
*natptr
)
1155 unsigned int r_length
;
1157 int r_baserel
, r_jmptable
, r_relative
;
1158 unsigned int r_addend
;
1160 PUT_WORD(abfd
, g
->address
, natptr
->r_address
);
1162 r_length
= g
->howto
->size
; /* Size as a power of two */
1163 r_pcrel
= (int) g
->howto
->pc_relative
; /* Relative to PC? */
1164 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
1169 r_addend
= g
->addend
; /* Start here, see how it goes */
1171 /* name was clobbered by aout_write_syms to be symbol index */
1173 if (g
->sym_ptr_ptr
!= NULL
)
1175 if ((*(g
->sym_ptr_ptr
))->section
) {
1176 /* put the section offset into the addend for output */
1177 r_addend
+= (*(g
->sym_ptr_ptr
))->section
->vma
;
1180 r_index
= ((*(g
->sym_ptr_ptr
))->KEEPIT
);
1185 if (g
->section
== NULL
) {
1186 /* It is possible to have a reloc with nothing, we generate an
1189 r_index
= N_ABS
| N_EXT
;
1191 else if(g
->section
->output_section
== obj_textsec(abfd
)) {
1192 r_index
= N_TEXT
| N_EXT
;
1193 r_addend
+= g
->section
->output_section
->vma
;
1195 else if (g
->section
->output_section
== obj_datasec(abfd
)) {
1196 r_index
= N_DATA
| N_EXT
;
1197 r_addend
+= g
->section
->output_section
->vma
;
1199 else if (g
->section
->output_section
== obj_bsssec(abfd
)) {
1200 r_index
= N_BSS
| N_EXT
;
1201 r_addend
+= g
->section
->output_section
->vma
;
1208 /* now the fun stuff */
1209 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1210 natptr
->r_index
[0] = r_index
>> 16;
1211 natptr
->r_index
[1] = r_index
>> 8;
1212 natptr
->r_index
[2] = r_index
;
1214 (r_extern
? RELOC_STD_BITS_EXTERN_BIG
: 0)
1215 | (r_pcrel
? RELOC_STD_BITS_PCREL_BIG
: 0)
1216 | (r_baserel
? RELOC_STD_BITS_BASEREL_BIG
: 0)
1217 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_BIG
: 0)
1218 | (r_relative
? RELOC_STD_BITS_RELATIVE_BIG
: 0)
1219 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_BIG
);
1221 natptr
->r_index
[2] = r_index
>> 16;
1222 natptr
->r_index
[1] = r_index
>> 8;
1223 natptr
->r_index
[0] = r_index
;
1225 (r_extern
? RELOC_STD_BITS_EXTERN_LITTLE
: 0)
1226 | (r_pcrel
? RELOC_STD_BITS_PCREL_LITTLE
: 0)
1227 | (r_baserel
? RELOC_STD_BITS_BASEREL_LITTLE
: 0)
1228 | (r_jmptable
? RELOC_STD_BITS_JMPTABLE_LITTLE
: 0)
1229 | (r_relative
? RELOC_STD_BITS_RELATIVE_LITTLE
: 0)
1230 | (r_length
<< RELOC_STD_BITS_LENGTH_SH_LITTLE
);
1235 /* Extended stuff */
1236 /* Output extended relocation information to a file in target byte order. */
1239 DEFUN(NAME(aout
,swap_ext_reloc_out
),(abfd
, g
, natptr
),
1242 register struct reloc_ext_external
*natptr
)
1246 unsigned int r_type
;
1247 unsigned int r_addend
;
1249 PUT_WORD (abfd
, g
->address
, natptr
->r_address
);
1251 /* Find a type in the output format which matches the input howto -
1252 at the moment we assume input format == output format FIXME!! */
1253 r_type
= (enum reloc_type
) g
->howto
->type
;
1255 r_addend
= g
->addend
; /* Start here, see how it goes */
1257 /* name was clobbered by aout_write_syms to be symbol index*/
1259 if (g
->sym_ptr_ptr
!= NULL
)
1261 if ((*(g
->sym_ptr_ptr
))->section
) {
1262 /* put the section offset into the addend for output */
1263 r_addend
+= (*(g
->sym_ptr_ptr
))->section
->vma
;
1266 r_index
= stoi((*(g
->sym_ptr_ptr
))->KEEPIT
);
1271 if (g
->section
== NULL
) {
1273 r_index
= N_ABS
| N_EXT
;
1275 else if(g
->section
->output_section
== obj_textsec(abfd
)) {
1276 r_index
= N_TEXT
| N_EXT
;
1277 r_addend
+= g
->section
->output_section
->vma
;
1279 else if (g
->section
->output_section
== obj_datasec(abfd
)) {
1280 r_index
= N_DATA
| N_EXT
;
1281 r_addend
+= g
->section
->output_section
->vma
;
1283 else if (g
->section
->output_section
== obj_bsssec(abfd
)) {
1284 r_index
= N_BSS
| N_EXT
;
1285 r_addend
+= g
->section
->output_section
->vma
;
1292 /* now the fun stuff */
1293 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1294 natptr
->r_index
[0] = r_index
>> 16;
1295 natptr
->r_index
[1] = r_index
>> 8;
1296 natptr
->r_index
[2] = r_index
;
1298 (r_extern
? RELOC_EXT_BITS_EXTERN_BIG
: 0)
1299 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_BIG
);
1301 natptr
->r_index
[2] = r_index
>> 16;
1302 natptr
->r_index
[1] = r_index
>> 8;
1303 natptr
->r_index
[0] = r_index
;
1305 (r_extern
? RELOC_EXT_BITS_EXTERN_LITTLE
: 0)
1306 | (r_type
<< RELOC_EXT_BITS_TYPE_SH_LITTLE
);
1309 PUT_WORD (abfd
, r_addend
, natptr
->r_addend
);
1312 #define MOVE_ADDRESS(ad) \
1314 cache_ptr->sym_ptr_ptr = symbols + r_index; \
1315 cache_ptr->section = (asection *)NULL; \
1316 cache_ptr->addend = ad; \
1318 cache_ptr->sym_ptr_ptr = (asymbol **)NULL; \
1319 switch (r_index) { \
1321 case N_TEXT | N_EXT: \
1322 cache_ptr->section = obj_textsec(abfd); \
1323 cache_ptr->addend = ad - su->textsec->vma; \
1326 case N_DATA | N_EXT: \
1327 cache_ptr->section = obj_datasec(abfd); \
1328 cache_ptr->addend = ad - su->datasec->vma; \
1331 case N_BSS | N_EXT: \
1332 cache_ptr->section = obj_bsssec(abfd); \
1333 cache_ptr->addend = ad - su->bsssec->vma; \
1336 case N_ABS | N_EXT: \
1337 cache_ptr->section = NULL; /* No section */ \
1338 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1342 cache_ptr->section = NULL; /* No section */ \
1343 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1350 DEFUN(NAME(aout
,swap_ext_reloc_in
), (abfd
, bytes
, cache_ptr
, symbols
),
1352 struct reloc_ext_external
*bytes AND
1353 arelent
*cache_ptr AND
1358 unsigned int r_type
;
1359 struct aoutdata
*su
= (struct aoutdata
*)(abfd
->tdata
);
1361 cache_ptr
->address
= (GET_SWORD (abfd
, bytes
->r_address
));
1363 /* now the fun stuff */
1364 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1365 r_index
= (bytes
->r_index
[0] << 16)
1366 | (bytes
->r_index
[1] << 8)
1367 | bytes
->r_index
[2];
1368 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_EXT_BITS_EXTERN_BIG
));
1369 r_type
= (bytes
->r_type
[0] & RELOC_EXT_BITS_TYPE_BIG
)
1370 >> RELOC_EXT_BITS_TYPE_SH_BIG
;
1372 r_index
= (bytes
->r_index
[2] << 16)
1373 | (bytes
->r_index
[1] << 8)
1374 | bytes
->r_index
[0];
1375 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_EXT_BITS_EXTERN_LITTLE
));
1376 r_type
= (bytes
->r_type
[0] & RELOC_EXT_BITS_TYPE_LITTLE
)
1377 >> RELOC_EXT_BITS_TYPE_SH_LITTLE
;
1380 cache_ptr
->howto
= howto_table_ext
+ r_type
;
1381 MOVE_ADDRESS(GET_SWORD(abfd
,bytes
->r_addend
));
1385 DEFUN(NAME(aout
,swap_std_reloc_in
), (abfd
, bytes
, cache_ptr
, symbols
),
1387 struct reloc_std_external
*bytes AND
1388 arelent
*cache_ptr AND
1393 unsigned int r_length
;
1395 int r_baserel
, r_jmptable
, r_relative
;
1396 struct aoutdata
*su
= (struct aoutdata
*)(abfd
->tdata
);
1398 cache_ptr
->address
= (int32_type
)(bfd_h_get_32 (abfd
, bytes
->r_address
));
1400 /* now the fun stuff */
1401 if (abfd
->xvec
->header_byteorder_big_p
!= false) {
1402 r_index
= (bytes
->r_index
[0] << 16)
1403 | (bytes
->r_index
[1] << 8)
1404 | bytes
->r_index
[2];
1405 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_EXTERN_BIG
));
1406 r_pcrel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_PCREL_BIG
));
1407 r_baserel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_BASEREL_BIG
));
1408 r_jmptable
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_JMPTABLE_BIG
));
1409 r_relative
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_RELATIVE_BIG
));
1410 r_length
= (bytes
->r_type
[0] & RELOC_STD_BITS_LENGTH_BIG
)
1411 >> RELOC_STD_BITS_LENGTH_SH_BIG
;
1413 r_index
= (bytes
->r_index
[2] << 16)
1414 | (bytes
->r_index
[1] << 8)
1415 | bytes
->r_index
[0];
1416 r_extern
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_EXTERN_LITTLE
));
1417 r_pcrel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_PCREL_LITTLE
));
1418 r_baserel
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_BASEREL_LITTLE
));
1419 r_jmptable
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_JMPTABLE_LITTLE
));
1420 r_relative
= (0 != (bytes
->r_type
[0] & RELOC_STD_BITS_RELATIVE_LITTLE
));
1421 r_length
= (bytes
->r_type
[0] & RELOC_STD_BITS_LENGTH_LITTLE
)
1422 >> RELOC_STD_BITS_LENGTH_SH_LITTLE
;
1425 cache_ptr
->howto
= howto_table_std
+ r_length
+ 4 * r_pcrel
;
1426 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
1434 DEFUN(NAME(aout
,slurp_reloc_table
),(abfd
, asect
, symbols
),
1440 bfd_size_type reloc_size
;
1442 arelent
*reloc_cache
;
1445 if (asect
->relocation
) return true;
1447 if (asect
->flags
& SEC_CONSTRUCTOR
) return true;
1449 if (asect
== obj_datasec (abfd
)) {
1450 reloc_size
= exec_hdr(abfd
)->a_drsize
;
1454 if (asect
== obj_textsec (abfd
)) {
1455 reloc_size
= exec_hdr(abfd
)->a_trsize
;
1459 bfd_error
= invalid_operation
;
1463 bfd_seek (abfd
, asect
->rel_filepos
, SEEK_SET
);
1464 each_size
= obj_reloc_entry_size (abfd
);
1466 count
= reloc_size
/ each_size
;
1469 reloc_cache
= (arelent
*) bfd_zalloc (abfd
, (size_t)(count
* sizeof
1473 bfd_error
= no_memory
;
1477 relocs
= (PTR
) bfd_alloc (abfd
, reloc_size
);
1479 bfd_release (abfd
, reloc_cache
);
1483 if (bfd_read (relocs
, 1, reloc_size
, abfd
) != reloc_size
) {
1484 bfd_release (abfd
, relocs
);
1485 bfd_release (abfd
, reloc_cache
);
1486 bfd_error
= system_call_error
;
1490 if (each_size
== RELOC_EXT_SIZE
) {
1491 register struct reloc_ext_external
*rptr
= (struct reloc_ext_external
*) relocs
;
1492 unsigned int counter
= 0;
1493 arelent
*cache_ptr
= reloc_cache
;
1495 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++) {
1496 NAME(aout
,swap_ext_reloc_in
)(abfd
, rptr
, cache_ptr
, symbols
);
1499 register struct reloc_std_external
*rptr
= (struct reloc_std_external
*) relocs
;
1500 unsigned int counter
= 0;
1501 arelent
*cache_ptr
= reloc_cache
;
1503 for (; counter
< count
; counter
++, rptr
++, cache_ptr
++) {
1504 NAME(aout
,swap_std_reloc_in
)(abfd
, rptr
, cache_ptr
, symbols
);
1509 bfd_release (abfd
,relocs
);
1510 asect
->relocation
= reloc_cache
;
1511 asect
->reloc_count
= count
;
1517 /* Write out a relocation section into an object file. */
1520 DEFUN(NAME(aout
,squirt_out_relocs
),(abfd
, section
),
1525 unsigned char *native
, *natptr
;
1528 unsigned int count
= section
->reloc_count
;
1531 if (count
== 0) return true;
1533 each_size
= obj_reloc_entry_size (abfd
);
1534 natsize
= each_size
* count
;
1535 native
= (unsigned char *) bfd_zalloc (abfd
, natsize
);
1537 bfd_error
= no_memory
;
1541 generic
= section
->orelocation
;
1543 if (each_size
== RELOC_EXT_SIZE
)
1545 for (natptr
= native
;
1547 --count
, natptr
+= each_size
, ++generic
)
1548 NAME(aout
,swap_ext_reloc_out
) (abfd
, *generic
, (struct reloc_ext_external
*)natptr
);
1552 for (natptr
= native
;
1554 --count
, natptr
+= each_size
, ++generic
)
1555 NAME(aout
,swap_std_reloc_out
)(abfd
, *generic
, (struct reloc_std_external
*)natptr
);
1558 if ( bfd_write ((PTR
) native
, 1, natsize
, abfd
) != natsize
) {
1559 bfd_release(abfd
, native
);
1562 bfd_release (abfd
, native
);
1567 /* This is stupid. This function should be a boolean predicate */
1569 DEFUN(NAME(aout
,canonicalize_reloc
),(abfd
, section
, relptr
, symbols
),
1572 arelent
**relptr AND
1575 arelent
*tblptr
= section
->relocation
;
1578 if (!(tblptr
|| NAME(aout
,slurp_reloc_table
)(abfd
, section
, symbols
)))
1581 if (section
->flags
& SEC_CONSTRUCTOR
) {
1582 arelent_chain
*chain
= section
->constructor_chain
;
1583 for (count
= 0; count
< section
->reloc_count
; count
++) {
1584 *relptr
++ = &chain
->relent
;
1585 chain
= chain
->next
;
1589 tblptr
= section
->relocation
;
1590 if (!tblptr
) return 0;
1592 for (count
= 0; count
++ < section
->reloc_count
;)
1594 *relptr
++ = tblptr
++;
1599 return section
->reloc_count
;
1603 DEFUN(NAME(aout
,get_reloc_upper_bound
),(abfd
, asect
),
1607 if (bfd_get_format (abfd
) != bfd_object
) {
1608 bfd_error
= invalid_operation
;
1611 if (asect
->flags
& SEC_CONSTRUCTOR
) {
1612 return (sizeof (arelent
*) * (asect
->reloc_count
+1));
1616 if (asect
== obj_datasec (abfd
))
1617 return (sizeof (arelent
*) *
1618 ((exec_hdr(abfd
)->a_drsize
/ obj_reloc_entry_size (abfd
))
1621 if (asect
== obj_textsec (abfd
))
1622 return (sizeof (arelent
*) *
1623 ((exec_hdr(abfd
)->a_trsize
/ obj_reloc_entry_size (abfd
))
1626 bfd_error
= invalid_operation
;
1632 DEFUN(NAME(aout
,get_symtab_upper_bound
),(abfd
),
1635 if (!NAME(aout
,slurp_symbol_table
)(abfd
)) return 0;
1637 return (bfd_get_symcount (abfd
)+1) * (sizeof (aout_symbol_type
*));
1640 DEFUN(NAME(aout
,get_lineno
),(ignore_abfd
, ignore_symbol
),
1641 bfd
*ignore_abfd AND
1642 asymbol
*ignore_symbol
)
1644 return (alent
*)NULL
;
1649 DEFUN(NAME(aout
,print_symbol
),(ignore_abfd
, afile
, symbol
, how
),
1650 bfd
*ignore_abfd AND
1653 bfd_print_symbol_enum_type how
)
1655 FILE *file
= (FILE *)afile
;
1658 case bfd_print_symbol_name_enum
:
1659 fprintf(file
,"%s", symbol
->name
);
1661 case bfd_print_symbol_type_enum
:
1662 fprintf(file
,"%4x %2x %2x",(unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1663 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1664 (unsigned)(aout_symbol(symbol
)->type
));
1666 case bfd_print_symbol_all_enum
:
1668 CONST
char *section_name
= symbol
->section
== (asection
*)NULL
?
1669 "*abs" : symbol
->section
->name
;
1671 bfd_print_symbol_vandf((PTR
)file
,symbol
);
1673 fprintf(file
," %-5s %04x %02x %02x %s",
1675 (unsigned)(aout_symbol(symbol
)->desc
& 0xffff),
1676 (unsigned)(aout_symbol(symbol
)->other
& 0xff),
1677 (unsigned)(aout_symbol(symbol
)->type
& 0xff),
1685 provided a BFD, a section and an offset into the section, calculate
1686 and return the name of the source file and the line nearest to the
1691 DEFUN(NAME(aout
,find_nearest_line
),(abfd
,
1699 asection
*section AND
1700 asymbol
**symbols AND
1702 CONST
char **filename_ptr AND
1703 CONST
char **functionname_ptr AND
1704 unsigned int *line_ptr
)
1706 /* Run down the file looking for the filename, function and linenumber */
1708 static char buffer
[100];
1709 bfd_vma high_line_vma
= ~0;
1710 bfd_vma low_func_vma
= 0;
1712 *filename_ptr
= abfd
->filename
;
1713 *functionname_ptr
= 0;
1715 if (symbols
!= (asymbol
**)NULL
) {
1716 for (p
= symbols
; *p
; p
++) {
1717 aout_symbol_type
*q
= (aout_symbol_type
*)(*p
);
1720 *filename_ptr
= q
->symbol
.name
;
1721 if (obj_textsec(abfd
) != section
) {
1729 /* We'll keep this if it resolves nearer than the one we have already */
1730 if (q
->symbol
.value
>= offset
&&
1731 q
->symbol
.value
< high_line_vma
) {
1732 *line_ptr
= q
->desc
;
1733 high_line_vma
= q
->symbol
.value
;
1738 /* We'll keep this if it is nearer than the one we have already */
1739 if (q
->symbol
.value
>= low_func_vma
&&
1740 q
->symbol
.value
<= offset
) {
1741 low_func_vma
= q
->symbol
.value
;
1742 func
= (asymbol
*)q
;
1744 if (*line_ptr
&& func
) {
1745 CONST
char *function
= func
->name
;
1747 strncpy(buffer
, function
, sizeof(buffer
)-1);
1748 buffer
[sizeof(buffer
)-1] = 0;
1749 /* Have to remove : stuff */
1750 p
= strchr(buffer
,':');
1751 if (p
!= NULL
) { *p
= NULL
; }
1752 *functionname_ptr
= buffer
;
1767 DEFUN(NAME(aout
,sizeof_headers
),(ignore_abfd
, execable
),
1768 bfd
*ignore_abfd AND
1771 return EXEC_BYTES_SIZE
;