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);
207 /* end-sanitize-v9 */
209 static reloc_howto_type howto_table_ext[] =
211 HOWTO(RELOC_8, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false),
212 HOWTO(RELOC_16, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false),
213 HOWTO(RELOC_32, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false),
214 HOWTO(RELOC_DISP8, 0, 0, 8, true, 0, false, true,0,"DISP8", false, 0,0x000000ff, false),
215 HOWTO(RELOC_DISP16, 0, 1, 16, true, 0, false, true,0,"DISP16", false, 0,0x0000ffff, false),
216 HOWTO(RELOC_DISP32, 0, 2, 32, true, 0, false, true,0,"DISP32", false, 0,0xffffffff, false),
217 HOWTO(RELOC_WDISP30,2, 2, 30, true, 0, false, true,0,"WDISP30", false, 0,0x3fffffff, false),
218 HOWTO(RELOC_WDISP22,2, 2, 22, true, 0, false, true,0,"WDISP22", false, 0,0x003fffff, false),
219 HOWTO(RELOC_HI22, 10, 2, 22, false, 0, false, true,0,"HI22", false, 0,0x003fffff, false),
220 HOWTO(RELOC_22, 0, 2, 22, false, 0, false, true,0,"22", false, 0,0x003fffff, false),
221 HOWTO(RELOC_13, 0, 2, 13, false, 0, false, true,0,"13", false, 0,0x00001fff, false),
222 HOWTO(RELOC_LO10, 0, 2, 10, false, 0, false, true,0,"LO10", false, 0,0x000003ff, false),
223 HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, false, true,0,"SFA_BASE", false, 0,0xffffffff, false),
224 HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, false, true,0,"SFA_OFF13",false, 0,0xffffffff, false),
225 HOWTO(RELOC_BASE10, 0, 2, 16, false, 0, false, true,0,"BASE10", false, 0,0x0000ffff, false),
226 HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, false, true,0,"BASE13", false, 0,0x00001fff, false),
227 HOWTO(RELOC_BASE22, 0, 2, 0, false, 0, false, true,0,"BASE22", false, 0,0x00000000, false),
228 HOWTO(RELOC_PC10, 0, 2, 10, false, 0, false, true,0,"PC10", false, 0,0x000003ff, false),
229 HOWTO(RELOC_PC22, 0, 2, 22, false, 0, false, true,0,"PC22", false, 0,0x003fffff, false),
230 HOWTO(RELOC_JMP_TBL,0, 2, 32, false, 0, false, true,0,"JMP_TBL", false, 0,0xffffffff, false),
231 HOWTO(RELOC_SEGOFF16,0, 2, 0, false, 0, false, true,0,"SEGOFF16", false, 0,0x00000000, false),
232 HOWTO(RELOC_GLOB_DAT,0, 2, 0, false, 0, false, true,0,"GLOB_DAT", false, 0,0x00000000, false),
233 HOWTO(RELOC_JMP_SLOT,0, 2, 0, false, 0, false, true,0,"JMP_SLOT", false, 0,0x00000000, false),
234 HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
236 /* start-sanitize-v9 */
238 HOWTO(RELOC_11, 0, 2, 21, true, 0, false, true,r64,"11", false, 0,/*0x00000000001fffff*/0, false),
239 HOWTO(RELOC_WDISP2_14, 0, 2, 21, true, 0, false, true,r64,"DISP2_14",false, 0,/*0x00000000001fffff*/0, false),
240 HOWTO(RELOC_WDISP19, 0, 3, 64, true, 0, false, true,r64,"DISP19", false, 0,/*0xffffffffffffffff*/0, false),
241 HOWTO(RELOC_HHI22, 42, 3, 22, false, 0, false, true,hhi22,"HHI22",false, 0,/*0x003fffff00000000*/0, false),
242 HOWTO(RELOC_HLO10, 32, 3, 10, false, 0, false, true,hlo10,"HLO10", false, 0,/*0x000003ff00000000*/0, false),
244 HOWTO(RELOC_JUMPTARG,2, 13, 16, true, 0, false, true,0,"JUMPTARG", false, 0,0x0000ffff, false),
245 HOWTO(RELOC_CONST, 0, 13, 16, false, 0, false, true,0,"CONST", false, 0,0x0000ffff, false),
246 HOWTO(RELOC_CONSTH, 16, 13, 16, false, 0, false, true,0,"CONSTH", false, 0,0x0000ffff, false),
249 HOWTO(RELOC_64, 0, 3, 64, false, 0, true, true,reloc64,"64", false, 0,/*0xffffffffffffffff*/0, false),
250 HOWTO(RELOC_DISP64, 0, 3, 64, true, 0, false, true,disp64,"DISP64", false, 0,/*0xffffffffffffffff*/0, false),
251 HOWTO(RELOC_WDISP21,2, 2, 21, true, 0, false, true,r64,"WDISP21",false, 0,/*0x00000000001fffff*/0, false),
252 HOWTO(RELOC_DISP21, 0, 2, 21, true, 0, false, true,r64,"DISP21", false, 0,/*0x00000000001fffff*/0, false),
253 HOWTO(RELOC_DISP14, 0, 2, 14, true, 0, false, true,r64,"DISP21", false, 0,/*0x0000000000003fff*/0, false),
255 /* end-sanitize-v9 */
258 /* Convert standard reloc records to "arelent" format (incl byte swap). */
260 static reloc_howto_type howto_table_std[] = {
261 /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */
262 HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
263 HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
264 HOWTO( 2, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
265 HOWTO( 3, 0, 3, 64, false, 0, true, true,0,"64", true, 0xdeaddead,0xdeaddead, false),
266 HOWTO( 4, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
267 HOWTO( 5, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
268 HOWTO( 6, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
269 HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedface,0xfeedface, false),
273 bfd_error_vector_type bfd_error_vector;
276 @subsection Internal Entry Points
277 @code{aoutx.h} exports several routines for accessing the contents of
278 an a.out file, which are gathered and exported in turn by various
279 format specific files (eg sunos.c).
283 *i aout_<size>_swap_exec_header_in
284 Swaps the information in an executable header taken from a raw byte stream memory image,
285 into the internal exec_header structure.
286 *; PROTO(void, aout_<size>_swap_exec_header_in,
288 struct external_exec *raw_bytes,
289 struct internal_exec *execp));
293 DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
295 struct external_exec *raw_bytes AND
296 struct internal_exec *execp)
298 struct external_exec *bytes = (struct external_exec *)raw_bytes;
300 /* Now fill in fields in the execp, from the bytes in the raw data. */
301 execp->a_info = bfd_h_get_32 (abfd, bytes->e_info);
302 execp->a_text = GET_WORD (abfd, bytes->e_text);
303 execp->a_data = GET_WORD (abfd, bytes->e_data);
304 execp->a_bss = GET_WORD (abfd, bytes->e_bss);
305 execp->a_syms = GET_WORD (abfd, bytes->e_syms);
306 execp->a_entry = GET_WORD (abfd, bytes->e_entry);
307 execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
308 execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
312 *i aout_<size>_swap_exec_header_out
313 Swaps the information in an internal exec header structure into the
314 supplied buffer ready for writing to disk.
315 *; PROTO(void, aout_<size>_swap_exec_header_out,
317 struct internal_exec *execp,
318 struct external_exec *raw_bytes));
321 DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes),
323 struct internal_exec *execp AND
324 struct external_exec *raw_bytes)
326 struct external_exec *bytes = (struct external_exec *)raw_bytes;
328 /* Now fill in fields in the raw data, from the fields in the exec struct. */
329 bfd_h_put_32 (abfd, execp->a_info , bytes->e_info);
330 PUT_WORD (abfd, execp->a_text , bytes->e_text);
331 PUT_WORD (abfd, execp->a_data , bytes->e_data);
332 PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
333 PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
334 PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
335 PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
336 PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
341 struct internal_exec e;
346 *i aout_<size>_some_aout_object_p
348 Some A.OUT variant thinks that the file whose format we're checking
349 is an a.out file. Do some more checking, and set up for access if
350 it really is. Call back to the calling environments "finish up"
351 function just before returning, to handle any last-minute setup.
353 *; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
355 bfd_target *(*callback_to_real_object_p)()));
359 DEFUN(NAME(aout,some_aout_object_p),(abfd, callback_to_real_object_p),
361 bfd_target *(*callback_to_real_object_p) ())
363 struct external_exec exec_bytes;
364 struct internal_exec *execp;
365 struct container *rawptr;
367 if (bfd_seek (abfd, 0L, false) < 0) {
368 bfd_error = system_call_error;
372 if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
373 != EXEC_BYTES_SIZE) {
374 bfd_error = wrong_format;
378 /* Use an intermediate variable for clarity */
379 rawptr = (struct container *) bfd_zalloc (abfd, sizeof (struct container));
381 if (rawptr == NULL) {
382 bfd_error = no_memory;
386 set_tdata (abfd, rawptr);
387 exec_hdr (abfd) = execp = &(rawptr->e);
388 NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, execp);
390 /* Set the file flags */
391 abfd->flags = NO_FLAGS;
392 if (execp->a_drsize || execp->a_trsize)
393 abfd->flags |= HAS_RELOC;
395 abfd->flags |= EXEC_P;
397 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
399 if (N_MAGIC (*execp) == ZMAGIC) abfd->flags |= D_PAGED;
400 if (N_MAGIC (*execp) == NMAGIC) abfd->flags |= WP_TEXT;
402 bfd_get_start_address (abfd) = execp->a_entry;
404 obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
405 bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
407 /* Set the default architecture and machine type. These can be
408 overridden in the callback routine. */
409 abfd->obj_arch = bfd_arch_unknown;
410 abfd->obj_machine = 0;
412 /* The default relocation entry size is that of traditional V7 Unix. */
413 obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
415 /* create the sections. This is raunchy, but bfd_close wants to reclaim
417 obj_textsec (abfd) = (asection *)NULL;
418 obj_datasec (abfd) = (asection *)NULL;
419 obj_bsssec (abfd) = (asection *)NULL;
420 (void)bfd_make_section(abfd, ".text");
421 (void)bfd_make_section(abfd, ".data");
422 (void)bfd_make_section(abfd, ".bss");
424 abfd->sections = obj_textsec (abfd);
425 obj_textsec (abfd)->next = obj_datasec (abfd);
426 obj_datasec (abfd)->next = obj_bsssec (abfd);
428 obj_datasec (abfd)->size = execp->a_data;
429 obj_bsssec (abfd)->size = execp->a_bss;
430 obj_textsec (abfd)->size = execp->a_text;
432 if (abfd->flags & D_PAGED) {
433 obj_textsec (abfd)->size -= EXEC_BYTES_SIZE;
437 obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
438 (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
439 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
440 obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
441 (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
442 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
443 obj_bsssec (abfd)->flags = SEC_ALLOC;
445 #ifdef THIS_IS_ONLY_DOCUMENTATION
446 /* Call back to the format-dependent code to fill in the rest of the
447 fields and do any further cleanup. Things that should be filled
448 in by the callback: */
450 struct exec *execp = exec_hdr (abfd);
452 /* The virtual memory addresses of the sections */
453 obj_datasec (abfd)->vma = N_DATADDR(*execp);
454 obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
455 obj_textsec (abfd)->vma = N_TXTADDR(*execp);
457 /* The file offsets of the sections */
458 obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
459 obj_datasec (abfd)->filepos = N_DATOFF(*execp);
461 /* The file offsets of the relocation info */
462 obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
463 obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
465 /* The file offsets of the string table and symbol table. */
466 obj_str_filepos (abfd) = N_STROFF (*execp);
467 obj_sym_filepos (abfd) = N_SYMOFF (*execp);
469 /* This common code can't fill in those things because they depend
470 on either the start address of the text segment, the rounding
471 up of virtual addersses between segments, or the starting file
472 position of the text segment -- all of which varies among different
473 versions of a.out. */
475 /* Determine the architecture and machine type of the object file. */
476 switch (N_MACHTYPE (*exec_hdr (abfd))) {
478 abfd->obj_arch = bfd_arch_obscure;
482 /* Determine the size of a relocation entry */
483 switch (abfd->obj_arch) {
486 obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
488 obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
493 /* The architecture is encoded in various ways in various a.out variants,
494 or is not encoded at all in some of them. The relocation size depends
495 on the architecture and the a.out variant. Finally, the return value
496 is the bfd_target vector in use. If an error occurs, return zero and
497 set bfd_error to the appropriate error code.
499 Formats such as b.out, which have additional fields in the a.out
500 header, should cope with them in this callback as well. */
501 #endif /* DOCUMENTATION */
504 return (*callback_to_real_object_p)(abfd);
508 *i aout_<size>_mkobject
510 This routine initializes a bfd for use with a.out files.
512 *; PROTO(boolean, aout_<size>_mkobject, (bfd *));
516 DEFUN(NAME(aout,mkobject),(abfd),
519 struct container *rawptr;
521 bfd_error = system_call_error;
523 /* Use an intermediate variable for clarity */
524 rawptr = (struct container *)bfd_zalloc (abfd, sizeof (struct container));
526 if (rawptr == NULL) {
527 bfd_error = no_memory;
531 set_tdata (abfd, rawptr);
532 exec_hdr (abfd) = &(rawptr->e);
534 /* For simplicity's sake we just make all the sections right here. */
536 obj_textsec (abfd) = (asection *)NULL;
537 obj_datasec (abfd) = (asection *)NULL;
538 obj_bsssec (abfd) = (asection *)NULL;
539 bfd_make_section (abfd, ".text");
540 bfd_make_section (abfd, ".data");
541 bfd_make_section (abfd, ".bss");
548 *i aout_<size>_machine_type
550 Keep track of machine architecture and machine type for a.out's.
551 Return the machine_type for a particular arch&machine, or M_UNKNOWN
552 if that exact arch&machine can't be represented in a.out format.
554 If the architecture is understood, machine type 0 (default) should
555 always be understood.
557 *; PROTO(enum machine_type, aout_<size>_machine_type,
558 (enum bfd_architecture arch,
559 unsigned long machine));
563 DEFUN(NAME(aout,machine_type),(arch, machine),
564 enum bfd_architecture arch AND
565 unsigned long machine)
567 enum machine_type arch_flags;
569 arch_flags = M_UNKNOWN;
573 if (machine == 0) arch_flags = M_SPARC;
578 case 0: arch_flags = M_68010; break;
579 case 68000: arch_flags = M_UNKNOWN; break;
580 case 68010: arch_flags = M_68010; break;
581 case 68020: arch_flags = M_68020; break;
582 default: arch_flags = M_UNKNOWN; break;
587 if (machine == 0) arch_flags = M_386;
591 if (machine == 0) arch_flags = M_29K;
595 arch_flags = M_UNKNOWN;
602 *i aout_<size>_set_arch_mach
604 Sets the architecture and the machine of the bfd to those values
605 supplied. Verifies that the format can support the architecture
608 *; PROTO(boolean, aout_<size>_set_arch_mach,
610 enum bfd_architecture,
611 unsigned long machine));
615 DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine),
617 enum bfd_architecture arch AND
618 unsigned long machine)
620 abfd->obj_arch = arch;
621 abfd->obj_machine = machine;
622 if (arch != bfd_arch_unknown &&
623 NAME(aout,machine_type) (arch, machine) == M_UNKNOWN)
624 return false; /* We can't represent this type */
625 return true; /* We're easy ... */
629 *i aout_<size>new_section_hook
631 Called by the bfd in response to a @code{bfd_make_section} request.
632 *; PROTO(boolean, aout_<size>_new_section_hook,
637 DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
641 /* align to double at least */
642 newsect->alignment_power = 3;
644 if (bfd_get_format (abfd) == bfd_object) {
645 if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
646 obj_textsec(abfd)= newsect;
650 if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
651 obj_datasec(abfd) = newsect;
655 if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
656 obj_bsssec(abfd) = newsect;
661 /* We allow more than three sections internally */
666 DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count),
673 if (abfd->output_has_begun == false)
674 { /* set by bfd.c handler */
675 if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL))
677 bfd_error = invalid_operation;
680 /* if (abfd->flags & D_PAGED) {
681 obj_textsec(abfd)->filepos = 0;
684 obj_textsec(abfd)->filepos = EXEC_BYTES_SIZE;
686 obj_textsec(abfd)->size = align_power(obj_textsec(abfd)->size,
687 obj_textsec(abfd)->alignment_power);
688 obj_datasec(abfd)->filepos = obj_textsec (abfd)->size + EXEC_BYTES_SIZE;
689 obj_datasec(abfd)->size = align_power(obj_datasec(abfd)->size,
690 obj_datasec(abfd)->alignment_power);
694 /* regardless, once we know what we're doing, we might as well get going */
695 if (section != obj_bsssec(abfd))
697 bfd_seek (abfd, section->filepos + offset, SEEK_SET);
700 return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
708 /* Classify stabs symbols */
710 #define sym_in_text_section(sym) \
711 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
713 #define sym_in_data_section(sym) \
714 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
716 #define sym_in_bss_section(sym) \
717 (((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
719 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
720 zero in the "value" field. Nonzeroes there are fortrancommon
722 #define sym_is_undefined(sym) \
723 ((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
725 /* Symbol is a global definition if N_EXT is on and if it has
726 a nonzero type field. */
727 #define sym_is_global_defn(sym) \
728 (((sym)->type & N_EXT) && (sym)->type & N_TYPE)
730 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
732 #define sym_is_debugger_info(sym) \
733 ((sym)->type & ~(N_EXT | N_TYPE))
735 #define sym_is_fortrancommon(sym) \
736 (((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
738 /* Symbol is absolute if it has N_ABS set */
739 #define sym_is_absolute(sym) \
740 (((sym)->type & N_TYPE)== N_ABS)
743 #define sym_is_indirect(sym) \
744 (((sym)->type & N_ABS)== N_ABS)
746 /* Only in their own functions for ease of debugging; when sym flags have
747 stabilised these should be inlined into their (single) caller */
750 DEFUN(translate_from_native_sym_flags,(sym_pointer, cache_ptr, abfd),
751 struct external_nlist *sym_pointer AND
752 aout_symbol_type *cache_ptr AND
755 switch (cache_ptr->type & N_TYPE) {
761 char *copy = bfd_alloc(abfd, strlen(cache_ptr->symbol.name)+1);
763 arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain));
764 strcpy(copy, cache_ptr->symbol.name);
765 section = bfd_make_section(abfd,copy);
766 switch ( (cache_ptr->type & N_TYPE) ) {
768 section->flags = SEC_CONSTRUCTOR;
769 reloc->relent.section = (asection *)NULL;
770 cache_ptr->symbol.section = (asection *)NULL;
773 section->flags = SEC_CONSTRUCTOR_TEXT;
774 reloc->relent.section = (asection *)obj_textsec(abfd);
775 cache_ptr->symbol.value -= reloc->relent.section->vma;
778 section->flags = SEC_CONSTRUCTOR_DATA;
779 reloc->relent.section = (asection *)obj_datasec(abfd);
780 cache_ptr->symbol.value -= reloc->relent.section->vma;
783 section->flags = SEC_CONSTRUCTOR_BSS;
784 reloc->relent.section = (asection *)obj_bsssec(abfd);
785 cache_ptr->symbol.value -= reloc->relent.section->vma;
788 cache_ptr->symbol.section = reloc->relent.section;
789 reloc->relent.addend = cache_ptr->symbol.value ;
791 /* We modify the symbol to belong to a section depending upon the
792 name of the symbol - probably __CTOR__ or __DTOR__ but we don't
793 really care, and add to the size of the section to contain a
794 pointer to the symbol. Build a reloc entry to relocate to this
795 symbol attached to this section. */
798 section->reloc_count++;
799 section->alignment_power = 2;
800 reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
801 reloc->next = section->constructor_chain;
802 section->constructor_chain = reloc;
803 reloc->relent.address = section->size;
804 section->size += sizeof(int *);
806 reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
807 cache_ptr->symbol.flags |= BSF_DEBUGGING | BSF_CONSTRUCTOR;
811 if (cache_ptr->type == N_WARNING)
813 /* This symbol is the text of a warning message, the next symbol
814 is the symbol to associate the warning with */
815 cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
816 cache_ptr->symbol.value = (bfd_vma)((cache_ptr+1));
817 /* We furgle with the next symbol in place. We don't want it to be undefined, we'll trample the type */
818 (sym_pointer+1)->e_type[0] = 0xff;
821 if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT)) {
822 /* Two symbols in a row for an INDR message. The first symbol
823 contains the name we will match, the second symbol contains the
824 name the first name is translated into. It is supplied to us
825 undefined. This is good, since we want to pull in any files which
827 cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT;
828 cache_ptr->symbol.value = (bfd_vma)((cache_ptr+1));
833 if (sym_is_debugger_info (cache_ptr)) {
834 cache_ptr->symbol.flags = BSF_DEBUGGING ;
835 /* Work out the section correct for this symbol */
836 switch (cache_ptr->type & N_TYPE)
840 cache_ptr->symbol.section = obj_textsec (abfd);
841 cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
844 cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
845 cache_ptr->symbol.section = obj_datasec (abfd);
848 cache_ptr->symbol.section = obj_bsssec (abfd);
849 cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
853 cache_ptr->symbol.section = 0;
859 if (sym_is_fortrancommon (cache_ptr))
861 cache_ptr->symbol.flags = BSF_FORT_COMM;
862 cache_ptr->symbol.section = (asection *)NULL;
865 if (sym_is_undefined (cache_ptr)) {
866 cache_ptr->symbol.flags = BSF_UNDEFINED;
868 else if (sym_is_global_defn (cache_ptr)) {
869 cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
872 else if (sym_is_absolute (cache_ptr)) {
873 cache_ptr->symbol.flags = BSF_ABSOLUTE;
876 cache_ptr->symbol.flags = BSF_LOCAL;
879 /* In a.out, the value of a symbol is always relative to the
880 * start of the file, if this is a data symbol we'll subtract
881 * the size of the text section to get the section relative
882 * value. If this is a bss symbol (which would be strange)
883 * we'll subtract the size of the previous two sections
884 * to find the section relative address.
887 if (sym_in_text_section (cache_ptr)) {
888 cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
889 cache_ptr->symbol.section = obj_textsec (abfd);
891 else if (sym_in_data_section (cache_ptr)){
892 cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
893 cache_ptr->symbol.section = obj_datasec (abfd);
895 else if (sym_in_bss_section(cache_ptr)) {
896 cache_ptr->symbol.section = obj_bsssec (abfd);
897 cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
900 cache_ptr->symbol.section = (asection *)NULL;
901 cache_ptr->symbol.flags |= BSF_ABSOLUTE;
909 DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
910 struct external_nlist *sym_pointer AND
911 asymbol *cache_ptr AND
914 bfd_vma value = cache_ptr->value;
916 if (bfd_get_section(cache_ptr)) {
917 if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
918 sym_pointer->e_type[0] |= N_BSS;
920 else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
921 sym_pointer->e_type[0] |= N_DATA;
923 else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
924 sym_pointer->e_type[0] |= N_TEXT;
927 bfd_error_vector.nonrepresentable_section(abfd,
928 bfd_get_output_section(cache_ptr)->name);
930 /* Turn the symbol from section relative to absolute again */
933 cache_ptr->section->output_section->vma
934 + cache_ptr->section->output_offset ;
937 sym_pointer->e_type[0] |= N_ABS;
939 if (cache_ptr->flags & (BSF_WARNING)) {
940 (sym_pointer+1)->e_type[0] = 1;
942 if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
943 sym_pointer->e_type[0] = (N_UNDF | N_EXT);
946 if (cache_ptr->flags & BSF_ABSOLUTE) {
947 sym_pointer->e_type[0] |= N_ABS;
950 if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
951 sym_pointer->e_type[0] |= N_EXT;
953 if (cache_ptr->flags & BSF_DEBUGGING) {
954 sym_pointer->e_type [0]= ((aout_symbol_type *)cache_ptr)->type;
957 PUT_WORD(abfd, value, sym_pointer->e_value);
960 /* Native-level interface to symbols. */
962 /* We read the symbols into a buffer, which is discarded when this
963 function exits. We read the strings into a buffer large enough to
964 hold them all plus all the cached symbol entries. */
967 DEFUN(NAME(aout,make_empty_symbol),(abfd),
970 aout_symbol_type *new =
971 (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
972 new->symbol.the_bfd = abfd;
978 DEFUN(NAME(aout,slurp_symbol_table),(abfd),
981 bfd_size_type symbol_size;
982 bfd_size_type string_size;
983 unsigned char string_chars[BYTES_IN_WORD];
984 struct external_nlist *syms;
986 aout_symbol_type *cached;
988 /* If there's no work to be done, don't do any */
989 if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
990 symbol_size = exec_hdr(abfd)->a_syms;
991 if (symbol_size == 0) {
992 bfd_error = no_symbols;
996 bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
997 if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
999 string_size = GET_WORD (abfd, string_chars);
1001 strings =(char *) bfd_alloc(abfd, string_size + 1);
1002 cached = (aout_symbol_type *)
1003 bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type)));
1005 /* malloc this, so we can free it if simply. The symbol caching
1006 might want to allocate onto the bfd's obstack */
1007 syms = (struct external_nlist *) malloc(symbol_size);
1008 bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1009 if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1011 if (syms) free (syms);
1012 if (cached) bfd_release (abfd, cached);
1013 if (strings)bfd_release (abfd, strings);
1017 bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1018 if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) {
1022 /* OK, now walk the new symtable, cacheing symbol properties */
1024 register struct external_nlist *sym_pointer;
1025 register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd);
1026 register aout_symbol_type *cache_ptr = cached;
1028 /* Run through table and copy values */
1029 for (sym_pointer = syms, cache_ptr = cached;
1030 sym_pointer < sym_end; sym_pointer++, cache_ptr++)
1032 bfd_vma x = GET_WORD(abfd, sym_pointer->e_strx);
1033 cache_ptr->symbol.the_bfd = abfd;
1035 cache_ptr->symbol.name = x + strings;
1037 cache_ptr->symbol.name = (char *)NULL;
1039 cache_ptr->symbol.value = GET_SWORD(abfd, sym_pointer->e_value);
1040 cache_ptr->desc = bfd_get_16(abfd, sym_pointer->e_desc);
1041 cache_ptr->other =bfd_get_8(abfd, sym_pointer->e_other);
1042 cache_ptr->type = bfd_get_8(abfd, sym_pointer->e_type);
1043 cache_ptr->symbol.udata = 0;
1044 translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
1048 obj_aout_symbols (abfd) = cached;
1056 DEFUN(NAME(aout,write_syms),(abfd),
1059 unsigned int count ;
1060 asymbol **generic = bfd_get_outsymbols (abfd);
1062 bfd_size_type stindex = BYTES_IN_WORD; /* initial string length */
1064 for (count = 0; count < bfd_get_symcount (abfd); count++) {
1065 asymbol *g = generic[count];
1066 struct external_nlist nsp;
1070 unsigned int length = strlen(g->name) +1;
1071 PUT_WORD (abfd, stindex, (unsigned char *)nsp.e_strx);
1075 PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx);
1078 if (g->the_bfd->xvec->flavour == abfd->xvec->flavour)
1080 bfd_h_put_16(abfd, aout_symbol(g)->desc, nsp.e_desc);
1081 bfd_h_put_8(abfd, aout_symbol(g)->other, nsp.e_other);
1082 bfd_h_put_8(abfd, aout_symbol(g)->type, nsp.e_type);
1086 bfd_h_put_16(abfd,0, nsp.e_desc);
1087 bfd_h_put_8(abfd, 0, nsp.e_other);
1088 bfd_h_put_8(abfd, 0, nsp.e_type);
1093 translate_to_native_sym_flags (&nsp, (PTR)g, abfd);
1095 bfd_write((PTR)&nsp,1,EXTERNAL_LIST_SIZE, abfd);
1099 /* Now output the strings. Be sure to put string length into correct
1100 * byte ordering before writing it.
1103 char buffer[BYTES_IN_WORD];
1104 PUT_WORD (abfd, stindex, (unsigned char *)buffer);
1106 bfd_write((PTR)buffer, 1, BYTES_IN_WORD, abfd);
1108 generic = bfd_get_outsymbols(abfd);
1109 for (count = 0; count < bfd_get_symcount(abfd); count++)
1111 asymbol *g = *(generic++);
1115 size_t length = strlen(g->name)+1;
1116 bfd_write((PTR)g->name, 1, length, abfd);
1118 if ((g->flags & BSF_FAKE)==0) {
1119 g->KEEPIT = (KEEPITTYPE) count;
1127 DEFUN(NAME(aout,get_symtab),(abfd, location),
1131 unsigned int counter = 0;
1132 aout_symbol_type *symbase;
1134 if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
1136 for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
1137 *(location++) = (asymbol *)( symbase++);
1139 return bfd_get_symcount(abfd);
1143 /* Standard reloc stuff */
1144 /* Output standard relocation information to a file in target byte order. */
1147 DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr),
1150 struct reloc_std_external *natptr)
1154 unsigned int r_length;
1156 int r_baserel, r_jmptable, r_relative;
1157 unsigned int r_addend;
1159 PUT_WORD(abfd, g->address, natptr->r_address);
1161 r_length = g->howto->size ; /* Size as a power of two */
1162 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
1163 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
1168 r_addend = g->addend; /* Start here, see how it goes */
1170 /* name was clobbered by aout_write_syms to be symbol index */
1172 if (g->sym_ptr_ptr != NULL)
1174 if ((*(g->sym_ptr_ptr))->section) {
1175 /* put the section offset into the addend for output */
1176 r_addend += (*(g->sym_ptr_ptr))->section->vma;
1179 r_index = ((*(g->sym_ptr_ptr))->KEEPIT);
1184 if (g->section == NULL) {
1185 /* It is possible to have a reloc with nothing, we generate an
1188 r_index = N_ABS | N_EXT;
1190 else if(g->section->output_section == obj_textsec(abfd)) {
1191 r_index = N_TEXT | N_EXT;
1192 r_addend += g->section->output_section->vma;
1194 else if (g->section->output_section == obj_datasec(abfd)) {
1195 r_index = N_DATA | N_EXT;
1196 r_addend += g->section->output_section->vma;
1198 else if (g->section->output_section == obj_bsssec(abfd)) {
1199 r_index = N_BSS | N_EXT ;
1200 r_addend += g->section->output_section->vma;
1207 /* now the fun stuff */
1208 if (abfd->xvec->header_byteorder_big_p != false) {
1209 natptr->r_index[0] = r_index >> 16;
1210 natptr->r_index[1] = r_index >> 8;
1211 natptr->r_index[2] = r_index;
1213 (r_extern? RELOC_STD_BITS_EXTERN_BIG: 0)
1214 | (r_pcrel? RELOC_STD_BITS_PCREL_BIG: 0)
1215 | (r_baserel? RELOC_STD_BITS_BASEREL_BIG: 0)
1216 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_BIG: 0)
1217 | (r_relative? RELOC_STD_BITS_RELATIVE_BIG: 0)
1218 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
1220 natptr->r_index[2] = r_index >> 16;
1221 natptr->r_index[1] = r_index >> 8;
1222 natptr->r_index[0] = r_index;
1224 (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
1225 | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
1226 | (r_baserel? RELOC_STD_BITS_BASEREL_LITTLE: 0)
1227 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1228 | (r_relative? RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1229 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
1234 /* Extended stuff */
1235 /* Output extended relocation information to a file in target byte order. */
1238 DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr),
1241 register struct reloc_ext_external *natptr)
1245 unsigned int r_type;
1246 unsigned int r_addend;
1248 PUT_WORD (abfd, g->address, natptr->r_address);
1250 /* Find a type in the output format which matches the input howto -
1251 at the moment we assume input format == output format FIXME!! */
1252 r_type = (enum reloc_type) g->howto->type;
1254 r_addend = g->addend; /* Start here, see how it goes */
1256 /* name was clobbered by aout_write_syms to be symbol index*/
1258 if (g->sym_ptr_ptr != NULL)
1260 if ((*(g->sym_ptr_ptr))->section) {
1261 /* put the section offset into the addend for output */
1262 r_addend += (*(g->sym_ptr_ptr))->section->vma;
1265 r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
1270 if (g->section == NULL) {
1272 r_index = N_ABS | N_EXT;
1274 else if(g->section->output_section == obj_textsec(abfd)) {
1275 r_index = N_TEXT | N_EXT;
1276 r_addend += g->section->output_section->vma;
1278 else if (g->section->output_section == obj_datasec(abfd)) {
1279 r_index = N_DATA | N_EXT;
1280 r_addend += g->section->output_section->vma;
1282 else if (g->section->output_section == obj_bsssec(abfd)) {
1283 r_index = N_BSS | N_EXT ;
1284 r_addend += g->section->output_section->vma;
1291 /* now the fun stuff */
1292 if (abfd->xvec->header_byteorder_big_p != false) {
1293 natptr->r_index[0] = r_index >> 16;
1294 natptr->r_index[1] = r_index >> 8;
1295 natptr->r_index[2] = r_index;
1297 (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1298 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1300 natptr->r_index[2] = r_index >> 16;
1301 natptr->r_index[1] = r_index >> 8;
1302 natptr->r_index[0] = r_index;
1304 (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1305 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1308 PUT_WORD (abfd, r_addend, natptr->r_addend);
1311 #define MOVE_ADDRESS(ad) \
1313 cache_ptr->sym_ptr_ptr = symbols + r_index; \
1314 cache_ptr->section = (asection *)NULL; \
1315 cache_ptr->addend = ad; \
1317 cache_ptr->sym_ptr_ptr = (asymbol **)NULL; \
1318 switch (r_index) { \
1320 case N_TEXT | N_EXT: \
1321 cache_ptr->section = obj_textsec(abfd); \
1322 cache_ptr->addend = ad - su->textsec->vma; \
1325 case N_DATA | N_EXT: \
1326 cache_ptr->section = obj_datasec(abfd); \
1327 cache_ptr->addend = ad - su->datasec->vma; \
1330 case N_BSS | N_EXT: \
1331 cache_ptr->section = obj_bsssec(abfd); \
1332 cache_ptr->addend = ad - su->bsssec->vma; \
1335 case N_ABS | N_EXT: \
1336 cache_ptr->section = NULL; /* No section */ \
1337 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1341 cache_ptr->section = NULL; /* No section */ \
1342 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1349 DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
1351 struct reloc_ext_external *bytes AND
1352 arelent *cache_ptr AND
1357 unsigned int r_type;
1358 struct aoutdata *su = (struct aoutdata *)(abfd->tdata);
1360 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
1362 /* now the fun stuff */
1363 if (abfd->xvec->header_byteorder_big_p != false) {
1364 r_index = (bytes->r_index[0] << 16)
1365 | (bytes->r_index[1] << 8)
1366 | bytes->r_index[2];
1367 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
1368 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
1369 >> RELOC_EXT_BITS_TYPE_SH_BIG;
1371 r_index = (bytes->r_index[2] << 16)
1372 | (bytes->r_index[1] << 8)
1373 | bytes->r_index[0];
1374 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1375 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1376 >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1379 cache_ptr->howto = howto_table_ext + r_type;
1380 MOVE_ADDRESS(GET_SWORD(abfd,bytes->r_addend));
1384 DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
1386 struct reloc_std_external *bytes AND
1387 arelent *cache_ptr AND
1392 unsigned int r_length;
1394 int r_baserel, r_jmptable, r_relative;
1395 struct aoutdata *su = (struct aoutdata *)(abfd->tdata);
1397 cache_ptr->address = (int32_type)(bfd_h_get_32 (abfd, bytes->r_address));
1399 /* now the fun stuff */
1400 if (abfd->xvec->header_byteorder_big_p != false) {
1401 r_index = (bytes->r_index[0] << 16)
1402 | (bytes->r_index[1] << 8)
1403 | bytes->r_index[2];
1404 r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
1405 r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
1406 r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
1407 r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1408 r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
1409 r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
1410 >> RELOC_STD_BITS_LENGTH_SH_BIG;
1412 r_index = (bytes->r_index[2] << 16)
1413 | (bytes->r_index[1] << 8)
1414 | bytes->r_index[0];
1415 r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1416 r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
1417 r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1418 r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1419 r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1420 r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
1421 >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1424 cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
1425 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
1433 DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols),
1439 bfd_size_type reloc_size;
1441 arelent *reloc_cache;
1444 if (asect->relocation) return true;
1446 if (asect->flags & SEC_CONSTRUCTOR) return true;
1448 if (asect == obj_datasec (abfd)) {
1449 reloc_size = exec_hdr(abfd)->a_drsize;
1453 if (asect == obj_textsec (abfd)) {
1454 reloc_size = exec_hdr(abfd)->a_trsize;
1458 bfd_error = invalid_operation;
1462 bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1463 each_size = obj_reloc_entry_size (abfd);
1465 count = reloc_size / each_size;
1468 reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
1472 bfd_error = no_memory;
1476 relocs = (PTR) bfd_alloc (abfd, reloc_size);
1478 bfd_release (abfd, reloc_cache);
1482 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
1483 bfd_release (abfd, relocs);
1484 bfd_release (abfd, reloc_cache);
1485 bfd_error = system_call_error;
1489 if (each_size == RELOC_EXT_SIZE) {
1490 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
1491 unsigned int counter = 0;
1492 arelent *cache_ptr = reloc_cache;
1494 for (; counter < count; counter++, rptr++, cache_ptr++) {
1495 NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols);
1498 register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs;
1499 unsigned int counter = 0;
1500 arelent *cache_ptr = reloc_cache;
1502 for (; counter < count; counter++, rptr++, cache_ptr++) {
1503 NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols);
1508 bfd_release (abfd,relocs);
1509 asect->relocation = reloc_cache;
1510 asect->reloc_count = count;
1516 /* Write out a relocation section into an object file. */
1519 DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
1524 unsigned char *native, *natptr;
1527 unsigned int count = section->reloc_count;
1530 if (count == 0) return true;
1532 each_size = obj_reloc_entry_size (abfd);
1533 natsize = each_size * count;
1534 native = (unsigned char *) bfd_zalloc (abfd, natsize);
1536 bfd_error = no_memory;
1540 generic = section->orelocation;
1542 if (each_size == RELOC_EXT_SIZE)
1544 for (natptr = native;
1546 --count, natptr += each_size, ++generic)
1547 NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
1551 for (natptr = native;
1553 --count, natptr += each_size, ++generic)
1554 NAME(aout,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr);
1557 if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1558 bfd_release(abfd, native);
1561 bfd_release (abfd, native);
1566 /* This is stupid. This function should be a boolean predicate */
1568 DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
1571 arelent **relptr AND
1574 arelent *tblptr = section->relocation;
1577 if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
1580 if (section->flags & SEC_CONSTRUCTOR) {
1581 arelent_chain *chain = section->constructor_chain;
1582 for (count = 0; count < section->reloc_count; count ++) {
1583 *relptr ++ = &chain->relent;
1584 chain = chain->next;
1588 tblptr = section->relocation;
1589 if (!tblptr) return 0;
1591 for (count = 0; count++ < section->reloc_count;)
1593 *relptr++ = tblptr++;
1598 return section->reloc_count;
1602 DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect),
1606 if (bfd_get_format (abfd) != bfd_object) {
1607 bfd_error = invalid_operation;
1610 if (asect->flags & SEC_CONSTRUCTOR) {
1611 return (sizeof (arelent *) * (asect->reloc_count+1));
1615 if (asect == obj_datasec (abfd))
1616 return (sizeof (arelent *) *
1617 ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
1620 if (asect == obj_textsec (abfd))
1621 return (sizeof (arelent *) *
1622 ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
1625 bfd_error = invalid_operation;
1631 DEFUN(NAME(aout,get_symtab_upper_bound),(abfd),
1634 if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
1636 return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
1639 DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol),
1640 bfd *ignore_abfd AND
1641 asymbol *ignore_symbol)
1643 return (alent *)NULL;
1648 DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how),
1649 bfd *ignore_abfd AND
1652 bfd_print_symbol_enum_type how)
1654 FILE *file = (FILE *)afile;
1657 case bfd_print_symbol_name_enum:
1658 fprintf(file,"%s", symbol->name);
1660 case bfd_print_symbol_type_enum:
1661 fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1662 (unsigned)(aout_symbol(symbol)->other & 0xff),
1663 (unsigned)(aout_symbol(symbol)->type));
1665 case bfd_print_symbol_all_enum:
1667 CONST char *section_name = symbol->section == (asection *)NULL ?
1668 "*abs" : symbol->section->name;
1670 bfd_print_symbol_vandf((PTR)file,symbol);
1672 fprintf(file," %-5s %04x %02x %02x %s",
1674 (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1675 (unsigned)(aout_symbol(symbol)->other & 0xff),
1676 (unsigned)(aout_symbol(symbol)->type & 0xff),
1684 provided a bfd, a section and an offset into the section, calculate
1685 and return the name of the source file and the line nearest to the
1690 DEFUN(NAME(aout,find_nearest_line),(abfd,
1698 asection *section AND
1699 asymbol **symbols AND
1701 CONST char **filename_ptr AND
1702 CONST char **functionname_ptr AND
1703 unsigned int *line_ptr)
1705 /* Run down the file looking for the filename, function and linenumber */
1707 static char buffer[100];
1708 bfd_vma high_line_vma = ~0;
1709 bfd_vma low_func_vma = 0;
1711 *filename_ptr = abfd->filename;
1712 *functionname_ptr = 0;
1714 if (symbols != (asymbol **)NULL) {
1715 for (p = symbols; *p; p++) {
1716 aout_symbol_type *q = (aout_symbol_type *)(*p);
1719 *filename_ptr = q->symbol.name;
1720 if (obj_textsec(abfd) != section) {
1728 /* We'll keep this if it resolves nearer than the one we have already */
1729 if (q->symbol.value >= offset &&
1730 q->symbol.value < high_line_vma) {
1731 *line_ptr = q->desc;
1732 high_line_vma = q->symbol.value;
1737 /* We'll keep this if it is nearer than the one we have already */
1738 if (q->symbol.value >= low_func_vma &&
1739 q->symbol.value <= offset) {
1740 low_func_vma = q->symbol.value;
1741 func = (asymbol *)q;
1743 if (*line_ptr && func) {
1744 CONST char *function = func->name;
1746 strncpy(buffer, function, sizeof(buffer)-1);
1747 buffer[sizeof(buffer)-1] = 0;
1748 /* Have to remove : stuff */
1749 p = strchr(buffer,':');
1750 if (p != NULL) { *p = NULL; }
1751 *functionname_ptr = buffer;
1766 DEFUN(NAME(aout,sizeof_headers),(ignore_abfd, execable),
1767 bfd *ignore_abfd AND
1770 return EXEC_BYTES_SIZE;