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 if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL))
709 bfd_error = invalid_operation;
712 /* if (abfd->flags & D_PAGED) {
713 obj_textsec(abfd)->filepos = 0;
716 obj_textsec(abfd)->filepos = EXEC_BYTES_SIZE;
718 obj_textsec(abfd)->size = align_power(obj_textsec(abfd)->size,
719 obj_textsec(abfd)->alignment_power);
720 obj_datasec(abfd)->filepos = obj_textsec (abfd)->size + EXEC_BYTES_SIZE;
721 obj_datasec(abfd)->size = align_power(obj_datasec(abfd)->size,
722 obj_datasec(abfd)->alignment_power);
726 /* regardless, once we know what we're doing, we might as well get going */
727 if (section != obj_bsssec(abfd))
729 bfd_seek (abfd, section->filepos + offset, SEEK_SET);
732 return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
740 /* Classify stabs symbols */
742 #define sym_in_text_section(sym) \
743 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
745 #define sym_in_data_section(sym) \
746 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
748 #define sym_in_bss_section(sym) \
749 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
751 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
752 zero in the "value" field. Nonzeroes there are fortrancommon
754 #define sym_is_undefined(sym) \
755 ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
757 /* Symbol is a global definition if N_EXT is on and if it has
758 a nonzero type field. */
759 #define sym_is_global_defn(sym) \
760 (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
762 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
764 #define sym_is_debugger_info(sym) \
765 ((sym)->type & ~(N_EXT | N_TYPE))
767 #define sym_is_fortrancommon(sym) \
768 (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
770 /* Symbol is absolute if it has N_ABS set */
771 #define sym_is_absolute(sym) \
772 (((sym)->type & N_TYPE)== N_ABS)
775 #define sym_is_indirect(sym) \
776 (((sym)->type & N_ABS)== N_ABS)
778 /* Only in their own functions for ease of debugging; when sym flags have
779 stabilised these should be inlined into their (single) caller */
782 DEFUN(translate_from_native_sym_flags,(sym_pointer, cache_ptr, abfd),
783 struct external_nlist *sym_pointer AND
784 aout_symbol_type *cache_ptr AND
787 switch (cache_ptr->type & N_TYPE) {
793 char *copy = bfd_alloc(abfd, strlen(cache_ptr->symbol.name)+1);
795 arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain));
796 strcpy(copy, cache_ptr->symbol.name);
797 section = bfd_make_section(abfd,copy);
798 switch ( (cache_ptr->type & N_TYPE) ) {
800 section->flags = SEC_CONSTRUCTOR;
801 reloc->relent.section = (asection *)NULL;
802 cache_ptr->symbol.section = (asection *)NULL;
805 section->flags = SEC_CONSTRUCTOR_TEXT;
806 reloc->relent.section = (asection *)obj_textsec(abfd);
807 cache_ptr->symbol.value -= reloc->relent.section->vma;
810 section->flags = SEC_CONSTRUCTOR_DATA;
811 reloc->relent.section = (asection *)obj_datasec(abfd);
812 cache_ptr->symbol.value -= reloc->relent.section->vma;
815 section->flags = SEC_CONSTRUCTOR_BSS;
816 reloc->relent.section = (asection *)obj_bsssec(abfd);
817 cache_ptr->symbol.value -= reloc->relent.section->vma;
820 cache_ptr->symbol.section = reloc->relent.section;
821 reloc->relent.addend = cache_ptr->symbol.value ;
823 /* We modify the symbol to belong to a section depending upon the
824 name of the symbol - probably __CTOR__ or __DTOR__ but we don't
825 really care, and add to the size of the section to contain a
826 pointer to the symbol. Build a reloc entry to relocate to this
827 symbol attached to this section. */
830 section->reloc_count++;
831 section->alignment_power = 2;
832 reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
833 reloc->next = section->constructor_chain;
834 section->constructor_chain = reloc;
835 reloc->relent.address = section->size;
836 section->size += sizeof(int *);
838 reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
839 cache_ptr->symbol.flags |= BSF_DEBUGGING | BSF_CONSTRUCTOR;
843 if (cache_ptr->type == N_WARNING)
845 /* This symbol is the text of a warning message, the next symbol
846 is the symbol to associate the warning with */
847 cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
848 cache_ptr->symbol.value = (bfd_vma)((cache_ptr+1));
849 /* We furgle with the next symbol in place. We don't want it to be undefined, we'll trample the type */
850 (sym_pointer+1)->e_type[0] = 0xff;
853 if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT)) {
854 /* Two symbols in a row for an INDR message. The first symbol
855 contains the name we will match, the second symbol contains the
856 name the first name is translated into. It is supplied to us
857 undefined. This is good, since we want to pull in any files which
859 cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT;
860 cache_ptr->symbol.value = (bfd_vma)((cache_ptr+1));
865 if (sym_is_debugger_info (cache_ptr)) {
866 cache_ptr->symbol.flags = BSF_DEBUGGING ;
867 /* Work out the section correct for this symbol */
868 switch (cache_ptr->type & N_TYPE)
872 cache_ptr->symbol.section = obj_textsec (abfd);
873 cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
876 cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
877 cache_ptr->symbol.section = obj_datasec (abfd);
880 cache_ptr->symbol.section = obj_bsssec (abfd);
881 cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
885 cache_ptr->symbol.section = 0;
891 if (sym_is_fortrancommon (cache_ptr))
893 cache_ptr->symbol.flags = BSF_FORT_COMM;
894 cache_ptr->symbol.section = (asection *)NULL;
897 if (sym_is_undefined (cache_ptr)) {
898 cache_ptr->symbol.flags = BSF_UNDEFINED;
900 else if (sym_is_global_defn (cache_ptr)) {
901 cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
904 else if (sym_is_absolute (cache_ptr)) {
905 cache_ptr->symbol.flags = BSF_ABSOLUTE;
908 cache_ptr->symbol.flags = BSF_LOCAL;
911 /* In a.out, the value of a symbol is always relative to the
912 * start of the file, if this is a data symbol we'll subtract
913 * the size of the text section to get the section relative
914 * value. If this is a bss symbol (which would be strange)
915 * we'll subtract the size of the previous two sections
916 * to find the section relative address.
919 if (sym_in_text_section (cache_ptr)) {
920 cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
921 cache_ptr->symbol.section = obj_textsec (abfd);
923 else if (sym_in_data_section (cache_ptr)){
924 cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
925 cache_ptr->symbol.section = obj_datasec (abfd);
927 else if (sym_in_bss_section(cache_ptr)) {
928 cache_ptr->symbol.section = obj_bsssec (abfd);
929 cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
932 cache_ptr->symbol.section = (asection *)NULL;
933 cache_ptr->symbol.flags |= BSF_ABSOLUTE;
941 DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
942 struct external_nlist *sym_pointer AND
943 asymbol *cache_ptr AND
946 bfd_vma value = cache_ptr->value;
948 if (bfd_get_section(cache_ptr)) {
949 if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
950 sym_pointer->e_type[0] |= N_BSS;
952 else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
953 sym_pointer->e_type[0] |= N_DATA;
955 else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
956 sym_pointer->e_type[0] |= N_TEXT;
959 bfd_error_vector.nonrepresentable_section(abfd,
960 bfd_get_output_section(cache_ptr)->name);
962 /* Turn the symbol from section relative to absolute again */
965 cache_ptr->section->output_section->vma
966 + cache_ptr->section->output_offset ;
969 sym_pointer->e_type[0] |= N_ABS;
971 if (cache_ptr->flags & (BSF_WARNING)) {
972 (sym_pointer+1)->e_type[0] = 1;
974 if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
975 sym_pointer->e_type[0] = (N_UNDF | N_EXT);
978 if (cache_ptr->flags & BSF_ABSOLUTE) {
979 sym_pointer->e_type[0] |= N_ABS;
982 if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
983 sym_pointer->e_type[0] |= N_EXT;
985 if (cache_ptr->flags & BSF_DEBUGGING) {
986 sym_pointer->e_type [0]= ((aout_symbol_type *)cache_ptr)->type;
989 PUT_WORD(abfd, value, sym_pointer->e_value);
992 /* Native-level interface to symbols. */
994 /* We read the symbols into a buffer, which is discarded when this
995 function exits. We read the strings into a buffer large enough to
996 hold them all plus all the cached symbol entries. */
999 DEFUN(NAME(aout,make_empty_symbol),(abfd),
1002 aout_symbol_type *new =
1003 (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
1004 new->symbol.the_bfd = abfd;
1006 return &new->symbol;
1010 DEFUN(NAME(aout,slurp_symbol_table),(abfd),
1013 bfd_size_type symbol_size;
1014 bfd_size_type string_size;
1015 unsigned char string_chars[BYTES_IN_WORD];
1016 struct external_nlist *syms;
1018 aout_symbol_type *cached;
1020 /* If there's no work to be done, don't do any */
1021 if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
1022 symbol_size = exec_hdr(abfd)->a_syms;
1023 if (symbol_size == 0) {
1024 bfd_error = no_symbols;
1028 bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1029 if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
1031 string_size = GET_WORD (abfd, string_chars);
1033 strings =(char *) bfd_alloc(abfd, string_size + 1);
1034 cached = (aout_symbol_type *)
1035 bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type)));
1037 /* malloc this, so we can free it if simply. The symbol caching
1038 might want to allocate onto the bfd's obstack */
1039 syms = (struct external_nlist *) malloc(symbol_size);
1040 bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1041 if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1043 if (syms) free (syms);
1044 if (cached) bfd_release (abfd, cached);
1045 if (strings)bfd_release (abfd, strings);
1049 bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1050 if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) {
1054 /* OK, now walk the new symtable, cacheing symbol properties */
1056 register struct external_nlist *sym_pointer;
1057 register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd);
1058 register aout_symbol_type *cache_ptr = cached;
1060 /* Run through table and copy values */
1061 for (sym_pointer = syms, cache_ptr = cached;
1062 sym_pointer < sym_end; sym_pointer++, cache_ptr++)
1064 bfd_vma x = GET_WORD(abfd, sym_pointer->e_strx);
1065 cache_ptr->symbol.the_bfd = abfd;
1067 cache_ptr->symbol.name = x + strings;
1069 cache_ptr->symbol.name = (char *)NULL;
1071 cache_ptr->symbol.value = GET_SWORD(abfd, sym_pointer->e_value);
1072 cache_ptr->desc = bfd_get_16(abfd, sym_pointer->e_desc);
1073 cache_ptr->other =bfd_get_8(abfd, sym_pointer->e_other);
1074 cache_ptr->type = bfd_get_8(abfd, sym_pointer->e_type);
1075 cache_ptr->symbol.udata = 0;
1076 translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
1080 obj_aout_symbols (abfd) = cached;
1088 DEFUN(NAME(aout,write_syms),(abfd),
1091 unsigned int count ;
1092 asymbol **generic = bfd_get_outsymbols (abfd);
1094 bfd_size_type stindex = BYTES_IN_WORD; /* initial string length */
1096 for (count = 0; count < bfd_get_symcount (abfd); count++) {
1097 asymbol *g = generic[count];
1098 struct external_nlist nsp;
1102 unsigned int length = strlen(g->name) +1;
1103 PUT_WORD (abfd, stindex, (unsigned char *)nsp.e_strx);
1107 PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx);
1110 if (g->the_bfd->xvec->flavour == abfd->xvec->flavour)
1112 bfd_h_put_16(abfd, aout_symbol(g)->desc, nsp.e_desc);
1113 bfd_h_put_8(abfd, aout_symbol(g)->other, nsp.e_other);
1114 bfd_h_put_8(abfd, aout_symbol(g)->type, nsp.e_type);
1118 bfd_h_put_16(abfd,0, nsp.e_desc);
1119 bfd_h_put_8(abfd, 0, nsp.e_other);
1120 bfd_h_put_8(abfd, 0, nsp.e_type);
1125 translate_to_native_sym_flags (&nsp, g, abfd);
1127 bfd_write((PTR)&nsp,1,EXTERNAL_LIST_SIZE, abfd);
1131 /* Now output the strings. Be sure to put string length into correct
1132 * byte ordering before writing it.
1135 char buffer[BYTES_IN_WORD];
1136 PUT_WORD (abfd, stindex, (unsigned char *)buffer);
1138 bfd_write((PTR)buffer, 1, BYTES_IN_WORD, abfd);
1140 generic = bfd_get_outsymbols(abfd);
1141 for (count = 0; count < bfd_get_symcount(abfd); count++)
1143 asymbol *g = *(generic++);
1147 size_t length = strlen(g->name)+1;
1148 bfd_write((PTR)g->name, 1, length, abfd);
1150 if ((g->flags & BSF_FAKE)==0) {
1151 g->KEEPIT = (KEEPITTYPE) count;
1159 DEFUN(NAME(aout,get_symtab),(abfd, location),
1163 unsigned int counter = 0;
1164 aout_symbol_type *symbase;
1166 if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
1168 for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
1169 *(location++) = (asymbol *)( symbase++);
1171 return bfd_get_symcount(abfd);
1175 /* Standard reloc stuff */
1176 /* Output standard relocation information to a file in target byte order. */
1179 DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr),
1182 struct reloc_std_external *natptr)
1186 unsigned int r_length;
1188 int r_baserel, r_jmptable, r_relative;
1189 unsigned int r_addend;
1191 PUT_WORD(abfd, g->address, natptr->r_address);
1193 r_length = g->howto->size ; /* Size as a power of two */
1194 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
1195 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
1200 r_addend = g->addend; /* Start here, see how it goes */
1202 /* name was clobbered by aout_write_syms to be symbol index */
1204 if (g->sym_ptr_ptr != NULL)
1206 if ((*(g->sym_ptr_ptr))->section) {
1207 /* put the section offset into the addend for output */
1208 r_addend += (*(g->sym_ptr_ptr))->section->vma;
1211 r_index = ((*(g->sym_ptr_ptr))->KEEPIT);
1216 if (g->section == NULL) {
1217 /* It is possible to have a reloc with nothing, we generate an
1220 r_index = N_ABS | N_EXT;
1222 else if(g->section->output_section == obj_textsec(abfd)) {
1223 r_index = N_TEXT | N_EXT;
1224 r_addend += g->section->output_section->vma;
1226 else if (g->section->output_section == obj_datasec(abfd)) {
1227 r_index = N_DATA | N_EXT;
1228 r_addend += g->section->output_section->vma;
1230 else if (g->section->output_section == obj_bsssec(abfd)) {
1231 r_index = N_BSS | N_EXT ;
1232 r_addend += g->section->output_section->vma;
1239 /* now the fun stuff */
1240 if (abfd->xvec->header_byteorder_big_p != false) {
1241 natptr->r_index[0] = r_index >> 16;
1242 natptr->r_index[1] = r_index >> 8;
1243 natptr->r_index[2] = r_index;
1245 (r_extern? RELOC_STD_BITS_EXTERN_BIG: 0)
1246 | (r_pcrel? RELOC_STD_BITS_PCREL_BIG: 0)
1247 | (r_baserel? RELOC_STD_BITS_BASEREL_BIG: 0)
1248 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_BIG: 0)
1249 | (r_relative? RELOC_STD_BITS_RELATIVE_BIG: 0)
1250 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
1252 natptr->r_index[2] = r_index >> 16;
1253 natptr->r_index[1] = r_index >> 8;
1254 natptr->r_index[0] = r_index;
1256 (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
1257 | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
1258 | (r_baserel? RELOC_STD_BITS_BASEREL_LITTLE: 0)
1259 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1260 | (r_relative? RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1261 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
1266 /* Extended stuff */
1267 /* Output extended relocation information to a file in target byte order. */
1270 DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr),
1273 register struct reloc_ext_external *natptr)
1277 unsigned int r_type;
1278 unsigned int r_addend;
1280 PUT_WORD (abfd, g->address, natptr->r_address);
1282 /* Find a type in the output format which matches the input howto -
1283 at the moment we assume input format == output format FIXME!! */
1284 r_type = (enum reloc_type) g->howto->type;
1286 r_addend = g->addend; /* Start here, see how it goes */
1288 /* name was clobbered by aout_write_syms to be symbol index*/
1290 if (g->sym_ptr_ptr != NULL)
1292 if ((*(g->sym_ptr_ptr))->section) {
1293 /* put the section offset into the addend for output */
1294 r_addend += (*(g->sym_ptr_ptr))->section->vma;
1297 r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
1302 if (g->section == NULL) {
1304 r_index = N_ABS | N_EXT;
1306 else if(g->section->output_section == obj_textsec(abfd)) {
1307 r_index = N_TEXT | N_EXT;
1308 r_addend += g->section->output_section->vma;
1310 else if (g->section->output_section == obj_datasec(abfd)) {
1311 r_index = N_DATA | N_EXT;
1312 r_addend += g->section->output_section->vma;
1314 else if (g->section->output_section == obj_bsssec(abfd)) {
1315 r_index = N_BSS | N_EXT ;
1316 r_addend += g->section->output_section->vma;
1323 /* now the fun stuff */
1324 if (abfd->xvec->header_byteorder_big_p != false) {
1325 natptr->r_index[0] = r_index >> 16;
1326 natptr->r_index[1] = r_index >> 8;
1327 natptr->r_index[2] = r_index;
1329 (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1330 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1332 natptr->r_index[2] = r_index >> 16;
1333 natptr->r_index[1] = r_index >> 8;
1334 natptr->r_index[0] = r_index;
1336 (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1337 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1340 PUT_WORD (abfd, r_addend, natptr->r_addend);
1343 #define MOVE_ADDRESS(ad) \
1345 cache_ptr->sym_ptr_ptr = symbols + r_index; \
1346 cache_ptr->section = (asection *)NULL; \
1347 cache_ptr->addend = ad; \
1349 cache_ptr->sym_ptr_ptr = (asymbol **)NULL; \
1350 switch (r_index) { \
1352 case N_TEXT | N_EXT: \
1353 cache_ptr->section = obj_textsec(abfd); \
1354 cache_ptr->addend = ad - su->textsec->vma; \
1357 case N_DATA | N_EXT: \
1358 cache_ptr->section = obj_datasec(abfd); \
1359 cache_ptr->addend = ad - su->datasec->vma; \
1362 case N_BSS | N_EXT: \
1363 cache_ptr->section = obj_bsssec(abfd); \
1364 cache_ptr->addend = ad - su->bsssec->vma; \
1367 case N_ABS | N_EXT: \
1368 cache_ptr->section = NULL; /* No section */ \
1369 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1373 cache_ptr->section = NULL; /* No section */ \
1374 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1381 DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
1383 struct reloc_ext_external *bytes AND
1384 arelent *cache_ptr AND
1389 unsigned int r_type;
1390 struct aoutdata *su = (struct aoutdata *)(abfd->tdata);
1392 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
1394 /* now the fun stuff */
1395 if (abfd->xvec->header_byteorder_big_p != false) {
1396 r_index = (bytes->r_index[0] << 16)
1397 | (bytes->r_index[1] << 8)
1398 | bytes->r_index[2];
1399 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
1400 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
1401 >> RELOC_EXT_BITS_TYPE_SH_BIG;
1403 r_index = (bytes->r_index[2] << 16)
1404 | (bytes->r_index[1] << 8)
1405 | bytes->r_index[0];
1406 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1407 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1408 >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1411 cache_ptr->howto = howto_table_ext + r_type;
1412 MOVE_ADDRESS(GET_SWORD(abfd,bytes->r_addend));
1416 DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
1418 struct reloc_std_external *bytes AND
1419 arelent *cache_ptr AND
1424 unsigned int r_length;
1426 int r_baserel, r_jmptable, r_relative;
1427 struct aoutdata *su = (struct aoutdata *)(abfd->tdata);
1429 cache_ptr->address = (int32_type)(bfd_h_get_32 (abfd, bytes->r_address));
1431 /* now the fun stuff */
1432 if (abfd->xvec->header_byteorder_big_p != false) {
1433 r_index = (bytes->r_index[0] << 16)
1434 | (bytes->r_index[1] << 8)
1435 | bytes->r_index[2];
1436 r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
1437 r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
1438 r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
1439 r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1440 r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
1441 r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
1442 >> RELOC_STD_BITS_LENGTH_SH_BIG;
1444 r_index = (bytes->r_index[2] << 16)
1445 | (bytes->r_index[1] << 8)
1446 | bytes->r_index[0];
1447 r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1448 r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
1449 r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1450 r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1451 r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1452 r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
1453 >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1456 cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
1457 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
1465 DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols),
1471 bfd_size_type reloc_size;
1473 arelent *reloc_cache;
1476 if (asect->relocation) return true;
1478 if (asect->flags & SEC_CONSTRUCTOR) return true;
1480 if (asect == obj_datasec (abfd)) {
1481 reloc_size = exec_hdr(abfd)->a_drsize;
1485 if (asect == obj_textsec (abfd)) {
1486 reloc_size = exec_hdr(abfd)->a_trsize;
1490 bfd_error = invalid_operation;
1494 bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1495 each_size = obj_reloc_entry_size (abfd);
1497 count = reloc_size / each_size;
1500 reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
1504 bfd_error = no_memory;
1508 relocs = (PTR) bfd_alloc (abfd, reloc_size);
1510 bfd_release (abfd, reloc_cache);
1514 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
1515 bfd_release (abfd, relocs);
1516 bfd_release (abfd, reloc_cache);
1517 bfd_error = system_call_error;
1521 if (each_size == RELOC_EXT_SIZE) {
1522 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
1523 unsigned int counter = 0;
1524 arelent *cache_ptr = reloc_cache;
1526 for (; counter < count; counter++, rptr++, cache_ptr++) {
1527 NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols);
1530 register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs;
1531 unsigned int counter = 0;
1532 arelent *cache_ptr = reloc_cache;
1534 for (; counter < count; counter++, rptr++, cache_ptr++) {
1535 NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols);
1540 bfd_release (abfd,relocs);
1541 asect->relocation = reloc_cache;
1542 asect->reloc_count = count;
1548 /* Write out a relocation section into an object file. */
1551 DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
1556 unsigned char *native, *natptr;
1559 unsigned int count = section->reloc_count;
1562 if (count == 0) return true;
1564 each_size = obj_reloc_entry_size (abfd);
1565 natsize = each_size * count;
1566 native = (unsigned char *) bfd_zalloc (abfd, natsize);
1568 bfd_error = no_memory;
1572 generic = section->orelocation;
1574 if (each_size == RELOC_EXT_SIZE)
1576 for (natptr = native;
1578 --count, natptr += each_size, ++generic)
1579 NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
1583 for (natptr = native;
1585 --count, natptr += each_size, ++generic)
1586 NAME(aout,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr);
1589 if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1590 bfd_release(abfd, native);
1593 bfd_release (abfd, native);
1598 /* This is stupid. This function should be a boolean predicate */
1600 DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
1603 arelent **relptr AND
1606 arelent *tblptr = section->relocation;
1609 if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
1612 if (section->flags & SEC_CONSTRUCTOR) {
1613 arelent_chain *chain = section->constructor_chain;
1614 for (count = 0; count < section->reloc_count; count ++) {
1615 *relptr ++ = &chain->relent;
1616 chain = chain->next;
1620 tblptr = section->relocation;
1621 if (!tblptr) return 0;
1623 for (count = 0; count++ < section->reloc_count;)
1625 *relptr++ = tblptr++;
1630 return section->reloc_count;
1634 DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect),
1638 if (bfd_get_format (abfd) != bfd_object) {
1639 bfd_error = invalid_operation;
1642 if (asect->flags & SEC_CONSTRUCTOR) {
1643 return (sizeof (arelent *) * (asect->reloc_count+1));
1647 if (asect == obj_datasec (abfd))
1648 return (sizeof (arelent *) *
1649 ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
1652 if (asect == obj_textsec (abfd))
1653 return (sizeof (arelent *) *
1654 ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
1657 bfd_error = invalid_operation;
1663 DEFUN(NAME(aout,get_symtab_upper_bound),(abfd),
1666 if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
1668 return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
1671 DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol),
1672 bfd *ignore_abfd AND
1673 asymbol *ignore_symbol)
1675 return (alent *)NULL;
1680 DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how),
1681 bfd *ignore_abfd AND
1684 bfd_print_symbol_enum_type how)
1686 FILE *file = (FILE *)afile;
1689 case bfd_print_symbol_name_enum:
1690 fprintf(file,"%s", symbol->name);
1692 case bfd_print_symbol_type_enum:
1693 fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1694 (unsigned)(aout_symbol(symbol)->other & 0xff),
1695 (unsigned)(aout_symbol(symbol)->type));
1697 case bfd_print_symbol_all_enum:
1699 CONST char *section_name = symbol->section == (asection *)NULL ?
1700 "*abs" : symbol->section->name;
1702 bfd_print_symbol_vandf((PTR)file,symbol);
1704 fprintf(file," %-5s %04x %02x %02x %s",
1706 (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1707 (unsigned)(aout_symbol(symbol)->other & 0xff),
1708 (unsigned)(aout_symbol(symbol)->type & 0xff),
1716 provided a BFD, a section and an offset into the section, calculate
1717 and return the name of the source file and the line nearest to the
1722 DEFUN(NAME(aout,find_nearest_line),(abfd,
1730 asection *section AND
1731 asymbol **symbols AND
1733 CONST char **filename_ptr AND
1734 CONST char **functionname_ptr AND
1735 unsigned int *line_ptr)
1737 /* Run down the file looking for the filename, function and linenumber */
1739 static char buffer[100];
1740 bfd_vma high_line_vma = ~0;
1741 bfd_vma low_func_vma = 0;
1743 *filename_ptr = abfd->filename;
1744 *functionname_ptr = 0;
1746 if (symbols != (asymbol **)NULL) {
1747 for (p = symbols; *p; p++) {
1748 aout_symbol_type *q = (aout_symbol_type *)(*p);
1751 *filename_ptr = q->symbol.name;
1752 if (obj_textsec(abfd) != section) {
1760 /* We'll keep this if it resolves nearer than the one we have already */
1761 if (q->symbol.value >= offset &&
1762 q->symbol.value < high_line_vma) {
1763 *line_ptr = q->desc;
1764 high_line_vma = q->symbol.value;
1769 /* We'll keep this if it is nearer than the one we have already */
1770 if (q->symbol.value >= low_func_vma &&
1771 q->symbol.value <= offset) {
1772 low_func_vma = q->symbol.value;
1773 func = (asymbol *)q;
1775 if (*line_ptr && func) {
1776 CONST char *function = func->name;
1778 strncpy(buffer, function, sizeof(buffer)-1);
1779 buffer[sizeof(buffer)-1] = 0;
1780 /* Have to remove : stuff */
1781 p = strchr(buffer,':');
1782 if (p != NULL) { *p = NULL; }
1783 *functionname_ptr = buffer;
1798 DEFUN(NAME(aout,sizeof_headers),(ignore_abfd, execable),
1799 bfd *ignore_abfd AND
1802 return EXEC_BYTES_SIZE;