]> Git Repo - binutils.git/blame - bfd/aoutx.h
Initial revision
[binutils.git] / bfd / aoutx.h
CommitLineData
88dfcd68
SC
1/* BFD semi-generic back-end for a.out binaries
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Written by Cygnus Support.
7ed4093a 4
88dfcd68 5This file is part of BFD, the Binary File Descriptor library.
7ed4093a 6
88dfcd68 7This program is free software; you can redistribute it and/or modify
7ed4093a 8it under the terms of the GNU General Public License as published by
88dfcd68
SC
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
7ed4093a 11
88dfcd68 12This program is distributed in the hope that it will be useful,
7ed4093a
SC
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
88dfcd68
SC
18along with this program; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
7ed4093a 20
6f715d66
SC
21/*doc*
22@section a.out backends
23
24BFD supports a number of different flavours of a.out format, though
25the major differences are only the sizes of the structures on disk,
26and the shape of the relocation information.
27
28The support is split into a basic support file @code{aoutx.h} and
29other files which derive functions from the base. One derivation file
30is @code{aoutf1.h} (for a.out flavour 1), and adds to the basic a.out
31functions support for sun3, sun4, 386 and 29k a.out files, to create a
32target jump vector for a specific target.
33
34This information is further split out into more specific files for each
35machine, including @code{sunos.c} - for sun3 and sun4 and
36@code{demo64} for a demonstration of a 64 bit a.out format.
37
38The base file @code{aoutx.h} defines general mechanisms for reading
39and writing records to and from disk, and various other methods which
40bfd requires. It is included by @code{aout32.c} and @code{aout64.c} to
41form the names aout_32_swap_exec_header_in,
42aout_64_swap_exec_header_in, etc.
43
44As an example, this is what goes on to make the back end for a sun4, from aout32.c
45
46@example
47 #define ARCH_SIZE 32
48 #include "aoutx.h"
49@end example
50
51Which exports names:
52@example
53 ...
54 aout_32_canonicalize_reloc
55 aout_32_find_nearest_line
56 aout_32_get_lineno
57 aout_32_get_reloc_upper_bound
58 ...
59@end example
60
61from sunos.c
62
63@example
64 #define ARCH 32
65 #define TARGET_NAME "a.out-sunos-big"
66 #define VECNAME sunos_big_vec
67 #include "aoutf1.h"
68@end example
69requires all the names from aout32.c, and produces the jump vector
70
71@example
72 sunos_big_vec
73@end example
74
75*/
76
67c060c3
SC
77
78#include "bfd.h"
7ed4093a
SC
79#include <sysdep.h>
80#include <ansidecl.h>
81
7ed4093a 82struct external_exec;
6f715d66 83#include "libaout.h"
7ed4093a
SC
84#include "libbfd.h"
85#include "aout64.h"
86#include "stab.gnu.h"
87#include "ar.h"
88
89void (*bfd_error_trap)();
90
6f715d66
SC
91/*doc*
92@subsection relocations
93The file @code{aoutx.h} caters for both the @emph{standard} and
94@emph{extended} forms of a.out relocation records.
7ed4093a 95
6f715d66
SC
96The standard records are characterised by containing only an address,
97a symbol index and a type field. The extended records (used on 29ks
98and sparcs) also have a full integer for an addend.
99*/
7ed4093a 100#define CTOR_TABLE_RELOC_IDX 2
67c060c3
SC
101
102/* start-sanitize-v9 */
103/* Provided the symbol, returns the value reffed */
104static bfd_vma
105DEFUN(get_symbol_value,(symbol, input_section),
106 asymbol *symbol AND
107 asection *input_section)
108{
109 bfd_vma relocation = 0;
110
111 if (symbol != (asymbol *)NULL) {
112 if (symbol->flags & BSF_FORT_COMM) {
113 relocation = 0;
114 } else {
115 relocation = symbol->value;
116 }
117 if (symbol->section != (asection *)NULL) {
118 relocation += symbol->section->output_section->vma +
119 symbol->section->output_offset;
120 }
121 }
122 else {
123 /* No symbol, so use the input section value */
124 relocation = input_section->output_section->vma + input_section->output_offset;
125 }
126 return relocation;
127}
128
129static bfd_reloc_status_enum_type
130DEFUN(reloc64,(abfd, reloc_entry, symbol_in, data, input_section),
131 bfd *abfd AND
132 arelent *reloc_entry AND
133 asymbol *symbol_in AND
134 unsigned char *data AND
135 asection *input_section)
136{
137 bfd_vma sym_value = get_symbol_value(symbol_in, input_section);
138 bfd_vma value = bfd_get_64(abfd, (bfd_byte *)data + reloc_entry->address);
139 value += sym_value + reloc_entry->addend;
140 bfd_put_64(abfd, value, (bfd_byte *)data+reloc_entry->address);
141 return bfd_reloc_ok;
142}
143
144static bfd_reloc_status_enum_type
145DEFUN(disp64,(abfd, reloc_entry, symbol_in, data, input_section),
146 bfd *abfd AND
147 arelent *reloc_entry AND
148 asymbol *symbol_in AND
149 unsigned char *data AND
150 asection *input_section)
151{
152 bfd_vma sym_value = get_symbol_value(symbol_in, input_section);
153
154/* bfd_get_64(abfd, (bfd_byte *)data + reloc_entry->address);*/
155 bfd_vma value = 0;
156 value += sym_value + reloc_entry->addend;
157
158 /* Subtract from the calculated value the pc */
159 value -= reloc_entry->address + input_section->output_section->vma;
160 bfd_put_64(abfd, value, (bfd_byte *)data+reloc_entry->address);
161 return bfd_reloc_ok;
162}
163
164static bfd_reloc_status_enum_type
165DEFUN(hhi22,(abfd, reloc_entry, symbol_in, data, input_section),
166 bfd *abfd AND
167 arelent *reloc_entry AND
168 asymbol *symbol_in AND
169 unsigned char *data AND
170 asection *input_section)
171{
172 bfd_vma sym_value = get_symbol_value(symbol_in, input_section);
173
174 bfd_vma value = bfd_get_32(abfd, (bfd_byte *)data + reloc_entry->address);
175
176 value = (value & ~0x3fffff) | ( ((sym_value + reloc_entry->addend) >> 32+10) & 0x3fffff);
177
178 bfd_put_32(abfd, value, (bfd_byte *)data+reloc_entry->address);
179 return bfd_reloc_ok;
180}
181
182static bfd_reloc_status_enum_type
183DEFUN(hlo10,(abfd, reloc_entry, symbol_in, data, input_section),
184 bfd *abfd AND
185 arelent *reloc_entry AND
186 asymbol *symbol_in AND
187 unsigned char *data AND
188 asection *input_section)
189{
190 bfd_vma sym_value = get_symbol_value(symbol_in, input_section);
191
192 bfd_vma value = bfd_get_32(abfd, (bfd_byte *)data + reloc_entry->address);
193
194 value = (value & ~0x3ff) | (((sym_value + reloc_entry->addend) >> 32) & 0x3ff);
195
196 bfd_put_32(abfd, value, (bfd_byte *)data+reloc_entry->address);
197 return bfd_reloc_ok;
198}
199
200static r64()
201{
202 abort();
203}
204
205/* end-sanitize-v9 */
206
7ed4093a
SC
207static reloc_howto_type howto_table_ext[] =
208{
209 HOWTO(RELOC_8, 0, 0, 8, false, 0, true, true,0,"8", false, 0,0x000000ff, false),
210 HOWTO(RELOC_16, 0, 1, 16, false, 0, true, true,0,"16", false, 0,0x0000ffff, false),
211 HOWTO(RELOC_32, 0, 2, 32, false, 0, true, true,0,"32", false, 0,0xffffffff, false),
212 HOWTO(RELOC_DISP8, 0, 0, 8, true, 0, false, true,0,"DISP8", false, 0,0x000000ff, false),
213 HOWTO(RELOC_DISP16, 0, 1, 16, true, 0, false, true,0,"DISP16", false, 0,0x0000ffff, false),
214 HOWTO(RELOC_DISP32, 0, 2, 32, true, 0, false, true,0,"DISP32", false, 0,0xffffffff, false),
215 HOWTO(RELOC_WDISP30,2, 2, 30, true, 0, false, true,0,"WDISP30", false, 0,0x3fffffff, false),
216 HOWTO(RELOC_WDISP22,2, 2, 22, true, 0, false, true,0,"WDISP22", false, 0,0x003fffff, false),
217 HOWTO(RELOC_HI22, 10, 2, 22, false, 0, false, true,0,"HI22", false, 0,0x003fffff, false),
218 HOWTO(RELOC_22, 0, 2, 22, false, 0, false, true,0,"22", false, 0,0x003fffff, false),
219 HOWTO(RELOC_13, 0, 2, 13, false, 0, false, true,0,"13", false, 0,0x00001fff, false),
220 HOWTO(RELOC_LO10, 0, 2, 10, false, 0, false, true,0,"LO10", false, 0,0x000003ff, false),
221 HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, false, true,0,"SFA_BASE", false, 0,0xffffffff, false),
222 HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, false, true,0,"SFA_OFF13",false, 0,0xffffffff, false),
223 HOWTO(RELOC_BASE10, 0, 2, 16, false, 0, false, true,0,"BASE10", false, 0,0x0000ffff, false),
224 HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, false, true,0,"BASE13", false, 0,0x00001fff, false),
225 HOWTO(RELOC_BASE22, 0, 2, 0, false, 0, false, true,0,"BASE22", false, 0,0x00000000, false),
226 HOWTO(RELOC_PC10, 0, 2, 10, false, 0, false, true,0,"PC10", false, 0,0x000003ff, false),
227 HOWTO(RELOC_PC22, 0, 2, 22, false, 0, false, true,0,"PC22", false, 0,0x003fffff, false),
228 HOWTO(RELOC_JMP_TBL,0, 2, 32, false, 0, false, true,0,"JMP_TBL", false, 0,0xffffffff, false),
229 HOWTO(RELOC_SEGOFF16,0, 2, 0, false, 0, false, true,0,"SEGOFF16", false, 0,0x00000000, false),
230 HOWTO(RELOC_GLOB_DAT,0, 2, 0, false, 0, false, true,0,"GLOB_DAT", false, 0,0x00000000, false),
231 HOWTO(RELOC_JMP_SLOT,0, 2, 0, false, 0, false, true,0,"JMP_SLOT", false, 0,0x00000000, false),
67c060c3
SC
232 HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
233
234/* start-sanitize-v9 */
235#ifdef HOST_64_BIT
236 HOWTO(RELOC_11, 0, 2, 21, true, 0, false, true,r64,"11", false, 0,/*0x00000000001fffff*/0, false),
237 HOWTO(RELOC_WDISP2_14, 0, 2, 21, true, 0, false, true,r64,"DISP2_14",false, 0,/*0x00000000001fffff*/0, false),
238 HOWTO(RELOC_WDISP19, 0, 3, 64, true, 0, false, true,r64,"DISP19", false, 0,/*0xffffffffffffffff*/0, false),
239 HOWTO(RELOC_HHI22, 42, 3, 22, false, 0, false, true,hhi22,"HHI22",false, 0,/*0x003fffff00000000*/0, false),
240 HOWTO(RELOC_HLO10, 32, 3, 10, false, 0, false, true,hlo10,"HLO10", false, 0,/*0x000003ff00000000*/0, false),
241#endif
7ed4093a
SC
242 HOWTO(RELOC_JUMPTARG,2, 13, 16, true, 0, false, true,0,"JUMPTARG", false, 0,0x0000ffff, false),
243 HOWTO(RELOC_CONST, 0, 13, 16, false, 0, false, true,0,"CONST", false, 0,0x0000ffff, false),
244 HOWTO(RELOC_CONSTH, 16, 13, 16, false, 0, false, true,0,"CONSTH", false, 0,0x0000ffff, false),
67c060c3
SC
245
246#ifdef HOST_64_BIT
247 HOWTO(RELOC_64, 0, 3, 64, false, 0, true, true,reloc64,"64", false, 0,/*0xffffffffffffffff*/0, false),
248 HOWTO(RELOC_DISP64, 0, 3, 64, true, 0, false, true,disp64,"DISP64", false, 0,/*0xffffffffffffffff*/0, false),
249 HOWTO(RELOC_WDISP21,2, 2, 21, true, 0, false, true,r64,"WDISP21",false, 0,/*0x00000000001fffff*/0, false),
250 HOWTO(RELOC_DISP21, 0, 2, 21, true, 0, false, true,r64,"DISP21", false, 0,/*0x00000000001fffff*/0, false),
251 HOWTO(RELOC_DISP14, 0, 2, 14, true, 0, false, true,r64,"DISP21", false, 0,/*0x0000000000003fff*/0, false),
252#endif
253/* end-sanitize-v9 */
7ed4093a
SC
254};
255
256/* Convert standard reloc records to "arelent" format (incl byte swap). */
257
258static reloc_howto_type howto_table_std[] = {
259 /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */
260HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
261HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
262HOWTO( 2, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
263HOWTO( 3, 0, 3, 64, false, 0, true, true,0,"64", true, 0xdeaddead,0xdeaddead, false),
264HOWTO( 4, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
265HOWTO( 5, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
266HOWTO( 6, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
267HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedface,0xfeedface, false),
268};
269
270
271bfd_error_vector_type bfd_error_vector;
6f715d66
SC
272
273/*doc*
274@subsection Internal Entry Points
275@code{aoutx.h} exports several routines for accessing the contents of
276an a.out file, which are gathered and exported in turn by various
277format specific files (eg sunos.c).
278*/
279
280/*doc*
281*i aout_<size>_swap_exec_header_in
282Swaps the information in an executable header taken from a raw byte stream memory image,
283into the internal exec_header structure.
284*; PROTO(void, aout_<size>_swap_exec_header_in,
285 (bfd *abfd,
286 struct external_exec *raw_bytes,
287 struct internal_exec *execp));
288*/
289
7ed4093a
SC
290void
291DEFUN(NAME(aout,swap_exec_header_in),(abfd, raw_bytes, execp),
292 bfd *abfd AND
293 struct external_exec *raw_bytes AND
294 struct internal_exec *execp)
295{
296 struct external_exec *bytes = (struct external_exec *)raw_bytes;
297
298 /* Now fill in fields in the execp, from the bytes in the raw data. */
299 execp->a_info = bfd_h_get_32 (abfd, bytes->e_info);
300 execp->a_text = GET_WORD (abfd, bytes->e_text);
301 execp->a_data = GET_WORD (abfd, bytes->e_data);
302 execp->a_bss = GET_WORD (abfd, bytes->e_bss);
303 execp->a_syms = GET_WORD (abfd, bytes->e_syms);
304 execp->a_entry = GET_WORD (abfd, bytes->e_entry);
305 execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
306 execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
307}
308
6f715d66
SC
309/*doc*
310*i aout_<size>_swap_exec_header_out
311Swaps the information in an internal exec header structure into the
312supplied buffer ready for writing to disk.
313*; PROTO(void, aout_<size>_swap_exec_header_out,
314 (bfd *abfd,
315 struct internal_exec *execp,
316 struct external_exec *raw_bytes));
317*/
7ed4093a
SC
318void
319DEFUN(NAME(aout,swap_exec_header_out),(abfd, execp, raw_bytes),
320 bfd *abfd AND
321 struct internal_exec *execp AND
322 struct external_exec *raw_bytes)
323{
324 struct external_exec *bytes = (struct external_exec *)raw_bytes;
325
326 /* Now fill in fields in the raw data, from the fields in the exec struct. */
327 bfd_h_put_32 (abfd, execp->a_info , bytes->e_info);
328 PUT_WORD (abfd, execp->a_text , bytes->e_text);
329 PUT_WORD (abfd, execp->a_data , bytes->e_data);
330 PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
331 PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
332 PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
333 PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
334 PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
335}
336
337struct container {
338 struct aoutdata a;
339 struct internal_exec e;
340};
341
6f715d66
SC
342
343/*doc*
344*i aout_<size>_some_aout_object_p
345
346Some A.OUT variant thinks that the file whose format we're checking
347is an a.out file. Do some more checking, and set up for access if
348it really is. Call back to the calling environments "finish up"
349function just before returning, to handle any last-minute setup.
350
351*; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
352 (bfd *abfd,
353 bfd_target *(*callback_to_real_object_p)()));
354*/
7ed4093a
SC
355
356bfd_target *
357DEFUN(NAME(aout,some_aout_object_p),(abfd, callback_to_real_object_p),
358 bfd *abfd AND
359 bfd_target *(*callback_to_real_object_p) ())
360{
361 struct external_exec exec_bytes;
362 struct internal_exec *execp;
363 struct container *rawptr;
364
365 if (bfd_seek (abfd, 0L, false) < 0) {
366 bfd_error = system_call_error;
367 return 0;
368 }
369
370 if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
371 != EXEC_BYTES_SIZE) {
372 bfd_error = wrong_format;
373 return 0;
374 }
375
376 /* Use an intermediate variable for clarity */
377 rawptr = (struct container *) bfd_zalloc (abfd, sizeof (struct container));
378
379 if (rawptr == NULL) {
380 bfd_error = no_memory;
381 return 0;
382 }
383
384 set_tdata (abfd, rawptr);
385 exec_hdr (abfd) = execp = &(rawptr->e);
386 NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, execp);
387
388 /* Set the file flags */
389 abfd->flags = NO_FLAGS;
390 if (execp->a_drsize || execp->a_trsize)
391 abfd->flags |= HAS_RELOC;
392 if (execp->a_entry)
393 abfd->flags |= EXEC_P;
394 if (execp->a_syms)
395 abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
396
397 if (N_MAGIC (*execp) == ZMAGIC) abfd->flags |= D_PAGED;
398 if (N_MAGIC (*execp) == NMAGIC) abfd->flags |= WP_TEXT;
399
400 bfd_get_start_address (abfd) = execp->a_entry;
401
402 obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
403 bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
404
405 /* Set the default architecture and machine type. These can be
406 overridden in the callback routine. */
407 abfd->obj_arch = bfd_arch_unknown;
408 abfd->obj_machine = 0;
409
410 /* The default relocation entry size is that of traditional V7 Unix. */
411 obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
412
413 /* create the sections. This is raunchy, but bfd_close wants to reclaim
414 them */
415 obj_textsec (abfd) = (asection *)NULL;
416 obj_datasec (abfd) = (asection *)NULL;
417 obj_bsssec (abfd) = (asection *)NULL;
418 (void)bfd_make_section(abfd, ".text");
419 (void)bfd_make_section(abfd, ".data");
420 (void)bfd_make_section(abfd, ".bss");
421
422 abfd->sections = obj_textsec (abfd);
423 obj_textsec (abfd)->next = obj_datasec (abfd);
424 obj_datasec (abfd)->next = obj_bsssec (abfd);
425
426 obj_datasec (abfd)->size = execp->a_data;
427 obj_bsssec (abfd)->size = execp->a_bss;
428 obj_textsec (abfd)->size = execp->a_text;
429
430 if (abfd->flags & D_PAGED) {
431 obj_textsec (abfd)->size -= EXEC_BYTES_SIZE;
432 }
433
434
435 obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
436 (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
437 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
438 obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
439 (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
440 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
441 obj_bsssec (abfd)->flags = SEC_ALLOC;
442
443#ifdef THIS_IS_ONLY_DOCUMENTATION
444 /* Call back to the format-dependent code to fill in the rest of the
445 fields and do any further cleanup. Things that should be filled
446 in by the callback: */
447
448 struct exec *execp = exec_hdr (abfd);
449
450 /* The virtual memory addresses of the sections */
451 obj_datasec (abfd)->vma = N_DATADDR(*execp);
452 obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
453 obj_textsec (abfd)->vma = N_TXTADDR(*execp);
454
455 /* The file offsets of the sections */
456 obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
457 obj_datasec (abfd)->filepos = N_DATOFF(*execp);
458
459 /* The file offsets of the relocation info */
460 obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
461 obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
462
463 /* The file offsets of the string table and symbol table. */
464 obj_str_filepos (abfd) = N_STROFF (*execp);
465 obj_sym_filepos (abfd) = N_SYMOFF (*execp);
466
467 /* This common code can't fill in those things because they depend
468 on either the start address of the text segment, the rounding
469 up of virtual addersses between segments, or the starting file
470 position of the text segment -- all of which varies among different
471 versions of a.out. */
472
473 /* Determine the architecture and machine type of the object file. */
474 switch (N_MACHTYPE (*exec_hdr (abfd))) {
475 default:
476 abfd->obj_arch = bfd_arch_obscure;
477 break;
478 }
479
480 /* Determine the size of a relocation entry */
481 switch (abfd->obj_arch) {
482 case bfd_arch_sparc:
483 case bfd_arch_a29k:
484 obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
485 default:
486 obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
487 }
488
489 return abfd->xvec;
490
491 /* The architecture is encoded in various ways in various a.out variants,
492 or is not encoded at all in some of them. The relocation size depends
493 on the architecture and the a.out variant. Finally, the return value
494 is the bfd_target vector in use. If an error occurs, return zero and
495 set bfd_error to the appropriate error code.
496
497 Formats such as b.out, which have additional fields in the a.out
498 header, should cope with them in this callback as well. */
499#endif /* DOCUMENTATION */
500
501
502 return (*callback_to_real_object_p)(abfd);
503}
504
6f715d66
SC
505/*doc*
506*i aout_<size>_mkobject
507
508This routine initializes a bfd for use with a.out files.
509
510*; PROTO(boolean, aout_<size>_mkobject, (bfd *));
511*/
7ed4093a
SC
512
513boolean
514DEFUN(NAME(aout,mkobject),(abfd),
515 bfd *abfd)
516{
517 struct container *rawptr;
518
519 bfd_error = system_call_error;
520
521 /* Use an intermediate variable for clarity */
522 rawptr = (struct container *)bfd_zalloc (abfd, sizeof (struct container));
523
524 if (rawptr == NULL) {
525 bfd_error = no_memory;
526 return false;
527 }
528
529 set_tdata (abfd, rawptr);
530 exec_hdr (abfd) = &(rawptr->e);
531
532 /* For simplicity's sake we just make all the sections right here. */
533
534 obj_textsec (abfd) = (asection *)NULL;
535 obj_datasec (abfd) = (asection *)NULL;
536 obj_bsssec (abfd) = (asection *)NULL;
537 bfd_make_section (abfd, ".text");
538 bfd_make_section (abfd, ".data");
539 bfd_make_section (abfd, ".bss");
540
541 return true;
542}
543
6f715d66
SC
544
545/*doc*
546*i aout_<size>_machine_type
547
548Keep track of machine architecture and machine type for a.out's.
7ed4093a
SC
549Return the machine_type for a particular arch&machine, or M_UNKNOWN
550if that exact arch&machine can't be represented in a.out format.
551
552If the architecture is understood, machine type 0 (default) should
6f715d66
SC
553always be understood.
554
555*; PROTO(enum machine_type, aout_<size>_machine_type,
556 (enum bfd_architecture arch,
557 unsigned long machine));
558*/
7ed4093a
SC
559
560enum machine_type
561DEFUN(NAME(aout,machine_type),(arch, machine),
562 enum bfd_architecture arch AND
563 unsigned long machine)
564{
565 enum machine_type arch_flags;
566
567 arch_flags = M_UNKNOWN;
568
569 switch (arch) {
570 case bfd_arch_sparc:
571 if (machine == 0) arch_flags = M_SPARC;
572 break;
573
574 case bfd_arch_m68k:
575 switch (machine) {
576 case 0: arch_flags = M_68010; break;
577 case 68000: arch_flags = M_UNKNOWN; break;
578 case 68010: arch_flags = M_68010; break;
579 case 68020: arch_flags = M_68020; break;
580 default: arch_flags = M_UNKNOWN; break;
581 }
582 break;
583
584 case bfd_arch_i386:
585 if (machine == 0) arch_flags = M_386;
586 break;
587
588 case bfd_arch_a29k:
589 if (machine == 0) arch_flags = M_29K;
590 break;
591
592 default:
593 arch_flags = M_UNKNOWN;
594 break;
595 }
596 return arch_flags;
597}
598
6f715d66
SC
599/*doc*
600*i aout_<size>_set_arch_mach
601
602Sets the architecture and the machine of the bfd to those values
603supplied. Verifies that the format can support the architecture
604required.
605
606*; PROTO(boolean, aout_<size>_set_arch_mach,
607 (bfd *,
608 enum bfd_architecture,
609 unsigned long machine));
610*/
611
7ed4093a
SC
612boolean
613DEFUN(NAME(aout,set_arch_mach),(abfd, arch, machine),
614 bfd *abfd AND
615 enum bfd_architecture arch AND
616 unsigned long machine)
617{
618 abfd->obj_arch = arch;
619 abfd->obj_machine = machine;
620 if (arch != bfd_arch_unknown &&
621 NAME(aout,machine_type) (arch, machine) == M_UNKNOWN)
622 return false; /* We can't represent this type */
623 return true; /* We're easy ... */
624}
7ed4093a 625
6f715d66
SC
626/*doc*
627*i aout_<size>new_section_hook
628
629Called by the bfd in response to a @code{bfd_make_section} request.
630*; PROTO(boolean, aout_<size>_new_section_hook,
631 (bfd *abfd,
632 asection *newsect));
633*/
7ed4093a
SC
634boolean
635DEFUN(NAME(aout,new_section_hook),(abfd, newsect),
636 bfd *abfd AND
637 asection *newsect)
638{
639 /* align to double at least */
640 newsect->alignment_power = 3;
641
642 if (bfd_get_format (abfd) == bfd_object) {
643 if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
644 obj_textsec(abfd)= newsect;
645 return true;
646 }
647
648 if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
649 obj_datasec(abfd) = newsect;
650 return true;
651 }
652
653 if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
654 obj_bsssec(abfd) = newsect;
655 return true;
656 }
657 }
658
659 /* We allow more than three sections internally */
660 return true;
661}
662
663boolean
664DEFUN(NAME(aout,set_section_contents),(abfd, section, location, offset, count),
665 bfd *abfd AND
666 sec_ptr section AND
667 PTR location AND
668 file_ptr offset AND
669 bfd_size_type count)
670{
671 if (abfd->output_has_begun == false)
672 { /* set by bfd.c handler */
673 if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL))
674 {
675 bfd_error = invalid_operation;
676 return false;
677 }
678/* if (abfd->flags & D_PAGED) {
679 obj_textsec(abfd)->filepos = 0;
680 }
681 else*/ {
682 obj_textsec(abfd)->filepos = EXEC_BYTES_SIZE;
683 }
684 obj_textsec(abfd)->size = align_power(obj_textsec(abfd)->size,
685 obj_textsec(abfd)->alignment_power);
686 obj_datasec(abfd)->filepos = obj_textsec (abfd)->size + EXEC_BYTES_SIZE;
687 obj_datasec(abfd)->size = align_power(obj_datasec(abfd)->size,
688 obj_datasec(abfd)->alignment_power);
689
690
691 }
692 /* regardless, once we know what we're doing, we might as well get going */
693 if (section != obj_bsssec(abfd))
694 {
695 bfd_seek (abfd, section->filepos + offset, SEEK_SET);
696
697 if (count) {
698 return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
699 true : false;
700 }
701 return false;
702 }
703 return true;
704}
705\f
706/* Classify stabs symbols */
707
708#define sym_in_text_section(sym) \
709(((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
710
711#define sym_in_data_section(sym) \
712(((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
713
714#define sym_in_bss_section(sym) \
715(((sym)->type & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
716
717/* Symbol is undefined if type is N_UNDF|N_EXT and if it has
718zero in the "value" field. Nonzeroes there are fortrancommon
719symbols. */
720#define sym_is_undefined(sym) \
721((sym)->type == (N_UNDF | N_EXT) && (sym)->symbol.value == 0)
722
723/* Symbol is a global definition if N_EXT is on and if it has
724a nonzero type field. */
725#define sym_is_global_defn(sym) \
726(((sym)->type & N_EXT) && (sym)->type & N_TYPE)
727
728/* Symbol is debugger info if any bits outside N_TYPE or N_EXT
729are on. */
730#define sym_is_debugger_info(sym) \
731((sym)->type & ~(N_EXT | N_TYPE))
732
733#define sym_is_fortrancommon(sym) \
734(((sym)->type == (N_EXT)) && (sym)->symbol.value != 0)
735
736/* Symbol is absolute if it has N_ABS set */
737#define sym_is_absolute(sym) \
738(((sym)->type & N_TYPE)== N_ABS)
739
740
741#define sym_is_indirect(sym) \
742(((sym)->type & N_ABS)== N_ABS)
743
744/* Only in their own functions for ease of debugging; when sym flags have
745stabilised these should be inlined into their (single) caller */
746
747static void
748DEFUN(translate_from_native_sym_flags,(sym_pointer, cache_ptr, abfd),
749 struct external_nlist *sym_pointer AND
750 aout_symbol_type *cache_ptr AND
751 bfd *abfd)
752{
753 switch (cache_ptr->type & N_TYPE) {
754 case N_SETA:
755 case N_SETT:
756 case N_SETD:
757 case N_SETB:
758 {
67c060c3
SC
759 char *copy = bfd_alloc(abfd, strlen(cache_ptr->symbol.name)+1);
760 asection *section ;
7ed4093a 761 arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain));
67c060c3 762 strcpy(copy, cache_ptr->symbol.name);
88dfcd68 763 section = bfd_make_section(abfd,copy);
7ed4093a
SC
764 switch ( (cache_ptr->type & N_TYPE) ) {
765 case N_SETA:
88dfcd68 766 section->flags = SEC_CONSTRUCTOR;
7ed4093a
SC
767 reloc->relent.section = (asection *)NULL;
768 cache_ptr->symbol.section = (asection *)NULL;
769 break;
770 case N_SETT:
88dfcd68 771 section->flags = SEC_CONSTRUCTOR_TEXT;
7ed4093a
SC
772 reloc->relent.section = (asection *)obj_textsec(abfd);
773 cache_ptr->symbol.value -= reloc->relent.section->vma;
774 break;
775 case N_SETD:
88dfcd68 776 section->flags = SEC_CONSTRUCTOR_DATA;
7ed4093a
SC
777 reloc->relent.section = (asection *)obj_datasec(abfd);
778 cache_ptr->symbol.value -= reloc->relent.section->vma;
779 break;
780 case N_SETB:
88dfcd68 781 section->flags = SEC_CONSTRUCTOR_BSS;
7ed4093a
SC
782 reloc->relent.section = (asection *)obj_bsssec(abfd);
783 cache_ptr->symbol.value -= reloc->relent.section->vma;
784 break;
785 }
786 cache_ptr->symbol.section = reloc->relent.section;
787 reloc->relent.addend = cache_ptr->symbol.value ;
788
789 /* We modify the symbol to belong to a section depending upon the
790 name of the symbol - probably __CTOR__ or __DTOR__ but we don't
791 really care, and add to the size of the section to contain a
792 pointer to the symbol. Build a reloc entry to relocate to this
793 symbol attached to this section. */
88dfcd68
SC
794
795
7ed4093a
SC
796 section->reloc_count++;
797 section->alignment_power = 2;
798 reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
799 reloc->next = section->constructor_chain;
800 section->constructor_chain = reloc;
801 reloc->relent.address = section->size;
802 section->size += sizeof(int *);
88dfcd68 803
7ed4093a 804 reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
88dfcd68 805 cache_ptr->symbol.flags |= BSF_DEBUGGING | BSF_CONSTRUCTOR;
7ed4093a
SC
806 }
807 break;
808 default:
88dfcd68
SC
809 if (cache_ptr->type == N_WARNING)
810 {
811 /* This symbol is the text of a warning message, the next symbol
812 is the symbol to associate the warning with */
813 cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
814 cache_ptr->symbol.value = (bfd_vma)((cache_ptr+1));
815 /* We furgle with the next symbol in place. We don't want it to be undefined, we'll trample the type */
816 (sym_pointer+1)->e_type[0] = 0xff;
817 break;
818 }
819 if (cache_ptr->type == N_INDR) {
820 /* Two symbols in a row for an INDR message. The first symbol
821 contains the name we will match, the second symbol contains the
822 name the first name is translated into. It is supplied to us
823 undefined. This is good, since we want to pull in any files which
824 define it */
825 cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT;
826 cache_ptr->symbol.value = (bfd_vma)((cache_ptr+1));
827 break;
828 }
829
830
7ed4093a
SC
831 if (sym_is_debugger_info (cache_ptr)) {
832 cache_ptr->symbol.flags = BSF_DEBUGGING ;
833 /* Work out the section correct for this symbol */
834 switch (cache_ptr->type & N_TYPE)
835 {
836 case N_TEXT:
837 case N_FN:
838 cache_ptr->symbol.section = obj_textsec (abfd);
839 cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
840 break;
841 case N_DATA:
842 cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
843 cache_ptr->symbol.section = obj_datasec (abfd);
844 break;
845 case N_BSS :
846 cache_ptr->symbol.section = obj_bsssec (abfd);
847 cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
848 break;
849 case N_ABS:
850 default:
851 cache_ptr->symbol.section = 0;
852 break;
853 }
854 }
855 else {
88dfcd68 856
7ed4093a
SC
857 if (sym_is_fortrancommon (cache_ptr))
858 {
859 cache_ptr->symbol.flags = BSF_FORT_COMM;
860 cache_ptr->symbol.section = (asection *)NULL;
861 }
862 else {
863 if (sym_is_undefined (cache_ptr)) {
864 cache_ptr->symbol.flags = BSF_UNDEFINED;
865 }
866 else if (sym_is_global_defn (cache_ptr)) {
867 cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
868 }
88dfcd68 869
7ed4093a
SC
870 else if (sym_is_absolute (cache_ptr)) {
871 cache_ptr->symbol.flags = BSF_ABSOLUTE;
872 }
873 else {
874 cache_ptr->symbol.flags = BSF_LOCAL;
875 }
88dfcd68 876
7ed4093a
SC
877 /* In a.out, the value of a symbol is always relative to the
878 * start of the file, if this is a data symbol we'll subtract
879 * the size of the text section to get the section relative
880 * value. If this is a bss symbol (which would be strange)
881 * we'll subtract the size of the previous two sections
882 * to find the section relative address.
883 */
88dfcd68 884
7ed4093a
SC
885 if (sym_in_text_section (cache_ptr)) {
886 cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
887 cache_ptr->symbol.section = obj_textsec (abfd);
888 }
889 else if (sym_in_data_section (cache_ptr)){
890 cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
891 cache_ptr->symbol.section = obj_datasec (abfd);
892 }
893 else if (sym_in_bss_section(cache_ptr)) {
894 cache_ptr->symbol.section = obj_bsssec (abfd);
895 cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
896 }
897 else {
898 cache_ptr->symbol.section = (asection *)NULL;
899 cache_ptr->symbol.flags |= BSF_ABSOLUTE;
900 }
901 }
902 }
903 }
904}
905
906static void
907DEFUN(translate_to_native_sym_flags,(sym_pointer, cache_ptr, abfd),
908 struct external_nlist *sym_pointer AND
909 asymbol *cache_ptr AND
910 bfd *abfd)
911{
912 bfd_vma value = cache_ptr->value;
913
914 if (bfd_get_section(cache_ptr)) {
915 if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
916 sym_pointer->e_type[0] |= N_BSS;
917 }
918 else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
919 sym_pointer->e_type[0] |= N_DATA;
920 }
921 else if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
922 sym_pointer->e_type[0] |= N_TEXT;
923 }
924 else {
925 bfd_error_vector.nonrepresentable_section(abfd,
926 bfd_get_output_section(cache_ptr)->name);
927 }
928 /* Turn the symbol from section relative to absolute again */
929
930 value +=
931 cache_ptr->section->output_section->vma
932 + cache_ptr->section->output_offset ;
933 }
934 else {
935 sym_pointer->e_type[0] |= N_ABS;
936 }
88dfcd68
SC
937 if (cache_ptr->flags & (BSF_WARNING)) {
938 (sym_pointer+1)->e_type[0] = 1;
939 }
7ed4093a
SC
940 if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
941 sym_pointer->e_type[0] = (N_UNDF | N_EXT);
942 }
943 else {
944 if (cache_ptr->flags & BSF_ABSOLUTE) {
945 sym_pointer->e_type[0] |= N_ABS;
946 }
947
948 if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
949 sym_pointer->e_type[0] |= N_EXT;
950 }
951 if (cache_ptr->flags & BSF_DEBUGGING) {
952 sym_pointer->e_type [0]= ((aout_symbol_type *)cache_ptr)->type;
953 }
954 }
955 PUT_WORD(abfd, value, sym_pointer->e_value);
956}
957\f
958/* Native-level interface to symbols. */
959
960/* We read the symbols into a buffer, which is discarded when this
961function exits. We read the strings into a buffer large enough to
962hold them all plus all the cached symbol entries. */
963
964asymbol *
965DEFUN(NAME(aout,make_empty_symbol),(abfd),
966 bfd *abfd)
967 {
968 aout_symbol_type *new =
969 (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
970 new->symbol.the_bfd = abfd;
971
972 return &new->symbol;
973 }
974
975boolean
976DEFUN(NAME(aout,slurp_symbol_table),(abfd),
977 bfd *abfd)
978 {
979 bfd_size_type symbol_size;
980 bfd_size_type string_size;
981 unsigned char string_chars[BYTES_IN_WORD];
982 struct external_nlist *syms;
983 char *strings;
984 aout_symbol_type *cached;
985
986 /* If there's no work to be done, don't do any */
987 if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
988 symbol_size = exec_hdr(abfd)->a_syms;
989 if (symbol_size == 0) {
990 bfd_error = no_symbols;
991 return false;
992 }
993
994 bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
995 if (bfd_read ((PTR)string_chars, BYTES_IN_WORD, 1, abfd) != BYTES_IN_WORD)
996 return false;
997 string_size = GET_WORD (abfd, string_chars);
998
999 strings =(char *) bfd_alloc(abfd, string_size + 1);
1000 cached = (aout_symbol_type *)
1001 bfd_zalloc(abfd, (bfd_size_type)(bfd_get_symcount (abfd) * sizeof(aout_symbol_type)));
67c060c3
SC
1002
1003 /* malloc this, so we can free it if simply. The symbol caching
1004 might want to allocate onto the bfd's obstack */
1005 syms = (struct external_nlist *) malloc(symbol_size);
7ed4093a
SC
1006 bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1007 if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1008 bailout:
67c060c3 1009 if (syms) free (syms);
7ed4093a
SC
1010 if (cached) bfd_release (abfd, cached);
1011 if (strings)bfd_release (abfd, strings);
1012 return false;
1013 }
1014
1015 bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1016 if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) {
1017 goto bailout;
1018 }
1019
1020 /* OK, now walk the new symtable, cacheing symbol properties */
1021 {
1022 register struct external_nlist *sym_pointer;
1023 register struct external_nlist *sym_end = syms + bfd_get_symcount (abfd);
1024 register aout_symbol_type *cache_ptr = cached;
1025
1026 /* Run through table and copy values */
1027 for (sym_pointer = syms, cache_ptr = cached;
1028 sym_pointer < sym_end; sym_pointer++, cache_ptr++)
1029 {
1030 bfd_vma x = GET_WORD(abfd, sym_pointer->e_strx);
1031 cache_ptr->symbol.the_bfd = abfd;
1032 if (x)
1033 cache_ptr->symbol.name = x + strings;
1034 else
1035 cache_ptr->symbol.name = (char *)NULL;
1036
1037 cache_ptr->symbol.value = GET_SWORD(abfd, sym_pointer->e_value);
1038 cache_ptr->desc = bfd_get_16(abfd, sym_pointer->e_desc);
1039 cache_ptr->other =bfd_get_8(abfd, sym_pointer->e_other);
1040 cache_ptr->type = bfd_get_8(abfd, sym_pointer->e_type);
1041 cache_ptr->symbol.udata = 0;
1042 translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
1043 }
1044 }
1045
1046 obj_aout_symbols (abfd) = cached;
67c060c3 1047 free((PTR)syms);
7ed4093a
SC
1048
1049 return true;
1050 }
1051
1052
1053void
1054DEFUN(NAME(aout,write_syms),(abfd),
1055 bfd *abfd)
1056 {
1057 unsigned int count ;
1058 asymbol **generic = bfd_get_outsymbols (abfd);
1059
1060 bfd_size_type stindex = BYTES_IN_WORD; /* initial string length */
1061
1062 for (count = 0; count < bfd_get_symcount (abfd); count++) {
1063 asymbol *g = generic[count];
1064 struct external_nlist nsp;
1065
1066
1067 if (g->name) {
1068 unsigned int length = strlen(g->name) +1;
1069 PUT_WORD (abfd, stindex, (unsigned char *)nsp.e_strx);
1070 stindex += length;
1071 }
1072 else {
1073 PUT_WORD (abfd, 0, (unsigned char *)nsp.e_strx);
1074 }
1075
1076 if (g->the_bfd->xvec->flavour == abfd->xvec->flavour)
1077 {
1078 bfd_h_put_16(abfd, aout_symbol(g)->desc, nsp.e_desc);
1079 bfd_h_put_8(abfd, aout_symbol(g)->other, nsp.e_other);
1080 bfd_h_put_8(abfd, aout_symbol(g)->type, nsp.e_type);
1081 }
1082 else
1083 {
1084 bfd_h_put_16(abfd,0, nsp.e_desc);
1085 bfd_h_put_8(abfd, 0, nsp.e_other);
1086 bfd_h_put_8(abfd, 0, nsp.e_type);
1087 }
1088
1089
1090
1091 translate_to_native_sym_flags (&nsp, (PTR)g, abfd);
1092
1093 bfd_write((PTR)&nsp,1,EXTERNAL_LIST_SIZE, abfd);
1094 }
1095
1096
1097 /* Now output the strings. Be sure to put string length into correct
1098 * byte ordering before writing it.
1099 */
1100 {
1101 char buffer[BYTES_IN_WORD];
1102 PUT_WORD (abfd, stindex, (unsigned char *)buffer);
1103
1104 bfd_write((PTR)buffer, 1, BYTES_IN_WORD, abfd);
1105 }
1106 generic = bfd_get_outsymbols(abfd);
1107 for (count = 0; count < bfd_get_symcount(abfd); count++)
1108 {
1109 asymbol *g = *(generic++);
1110
1111 if (g->name)
1112 {
1113 size_t length = strlen(g->name)+1;
1114 bfd_write((PTR)g->name, 1, length, abfd);
1115 }
1116 if ((g->flags & BSF_FAKE)==0) {
1117 g->name = itos(count); /* smash the generic symbol */
1118 }
1119 }
1120 }
1121
1122
1123
1124unsigned int
1125DEFUN(NAME(aout,get_symtab),(abfd, location),
1126 bfd *abfd AND
1127 asymbol **location)
1128 {
1129 unsigned int counter = 0;
1130 aout_symbol_type *symbase;
1131
1132 if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
1133
1134 for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
1135 *(location++) = (asymbol *)( symbase++);
1136 *location++ =0;
1137 return bfd_get_symcount(abfd);
1138 }
1139
1140\f
1141/* Standard reloc stuff */
1142/* Output standard relocation information to a file in target byte order. */
1143
1144void
1145DEFUN(NAME(aout,swap_std_reloc_out),(abfd, g, natptr),
1146 bfd *abfd AND
1147 arelent *g AND
1148 struct reloc_std_external *natptr)
1149 {
1150 int r_index;
1151 int r_extern;
1152 unsigned int r_length;
1153 int r_pcrel;
1154 int r_baserel, r_jmptable, r_relative;
1155 unsigned int r_addend;
1156
1157 PUT_WORD(abfd, g->address, natptr->r_address);
1158
1159 r_length = g->howto->size ; /* Size as a power of two */
1160 r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
1161 /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
1162 r_baserel = 0;
1163 r_jmptable = 0;
1164 r_relative = 0;
1165
1166 r_addend = g->addend; /* Start here, see how it goes */
1167
1168 /* name was clobbered by aout_write_syms to be symbol index */
1169
1170 if (g->sym_ptr_ptr != NULL)
1171 {
1172 if ((*(g->sym_ptr_ptr))->section) {
1173 /* put the section offset into the addend for output */
1174 r_addend += (*(g->sym_ptr_ptr))->section->vma;
1175 }
1176
1177 r_index = stoi((*(g->sym_ptr_ptr))->name);
1178 r_extern = 1;
1179 }
1180 else {
1181 r_extern = 0;
1182 if (g->section == NULL) {
1183 /* It is possible to have a reloc with nothing, we generate an
1184 abs + 0 */
1185 r_addend = 0;
1186 r_index = N_ABS | N_EXT;
1187 }
1188 else if(g->section->output_section == obj_textsec(abfd)) {
1189 r_index = N_TEXT | N_EXT;
1190 r_addend += g->section->output_section->vma;
1191 }
1192 else if (g->section->output_section == obj_datasec(abfd)) {
1193 r_index = N_DATA | N_EXT;
1194 r_addend += g->section->output_section->vma;
1195 }
1196 else if (g->section->output_section == obj_bsssec(abfd)) {
1197 r_index = N_BSS | N_EXT ;
1198 r_addend += g->section->output_section->vma;
1199 }
1200 else {
1201 BFD_ASSERT(0);
1202 }
1203 }
1204
1205 /* now the fun stuff */
1206 if (abfd->xvec->header_byteorder_big_p != false) {
1207 natptr->r_index[0] = r_index >> 16;
1208 natptr->r_index[1] = r_index >> 8;
1209 natptr->r_index[2] = r_index;
1210 natptr->r_type[0] =
1211 (r_extern? RELOC_STD_BITS_EXTERN_BIG: 0)
1212 | (r_pcrel? RELOC_STD_BITS_PCREL_BIG: 0)
1213 | (r_baserel? RELOC_STD_BITS_BASEREL_BIG: 0)
1214 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_BIG: 0)
1215 | (r_relative? RELOC_STD_BITS_RELATIVE_BIG: 0)
1216 | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
1217 } else {
1218 natptr->r_index[2] = r_index >> 16;
1219 natptr->r_index[1] = r_index >> 8;
1220 natptr->r_index[0] = r_index;
1221 natptr->r_type[0] =
1222 (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
1223 | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
1224 | (r_baserel? RELOC_STD_BITS_BASEREL_LITTLE: 0)
1225 | (r_jmptable? RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1226 | (r_relative? RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1227 | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
1228 }
1229 }
1230
1231
1232/* Extended stuff */
1233/* Output extended relocation information to a file in target byte order. */
1234
1235void
1236DEFUN(NAME(aout,swap_ext_reloc_out),(abfd, g, natptr),
1237 bfd *abfd AND
1238 arelent *g AND
1239 register struct reloc_ext_external *natptr)
1240 {
1241 int r_index;
1242 int r_extern;
1243 unsigned int r_type;
1244 unsigned int r_addend;
1245
1246 PUT_WORD (abfd, g->address, natptr->r_address);
1247
1248 /* Find a type in the output format which matches the input howto -
1249 at the moment we assume input format == output format FIXME!! */
1250 r_type = (enum reloc_type) g->howto->type;
1251
1252 r_addend = g->addend; /* Start here, see how it goes */
1253
1254 /* name was clobbered by aout_write_syms to be symbol index*/
1255
1256 if (g->sym_ptr_ptr != NULL)
1257 {
1258 if ((*(g->sym_ptr_ptr))->section) {
1259 /* put the section offset into the addend for output */
1260 r_addend += (*(g->sym_ptr_ptr))->section->vma;
1261 }
1262
1263 r_index = stoi((*(g->sym_ptr_ptr))->name);
1264 r_extern = 1;
1265 }
1266 else {
1267 r_extern = 0;
1268 if (g->section == NULL) {
1269 BFD_ASSERT(0);
1270 r_index = N_ABS | N_EXT;
1271 }
1272 else if(g->section->output_section == obj_textsec(abfd)) {
1273 r_index = N_TEXT | N_EXT;
1274 r_addend += g->section->output_section->vma;
1275 }
1276 else if (g->section->output_section == obj_datasec(abfd)) {
1277 r_index = N_DATA | N_EXT;
1278 r_addend += g->section->output_section->vma;
1279 }
1280 else if (g->section->output_section == obj_bsssec(abfd)) {
1281 r_index = N_BSS | N_EXT ;
1282 r_addend += g->section->output_section->vma;
1283 }
1284 else {
1285 BFD_ASSERT(0);
1286 }
1287 }
1288
1289 /* now the fun stuff */
1290 if (abfd->xvec->header_byteorder_big_p != false) {
1291 natptr->r_index[0] = r_index >> 16;
1292 natptr->r_index[1] = r_index >> 8;
1293 natptr->r_index[2] = r_index;
1294 natptr->r_type[0] =
1295 (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1296 | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1297 } else {
1298 natptr->r_index[2] = r_index >> 16;
1299 natptr->r_index[1] = r_index >> 8;
1300 natptr->r_index[0] = r_index;
1301 natptr->r_type[0] =
1302 (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1303 | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1304 }
1305
1306 PUT_WORD (abfd, r_addend, natptr->r_addend);
1307}
1308
1309#define MOVE_ADDRESS(ad) \
1310 if (r_extern) { \
1311 cache_ptr->sym_ptr_ptr = symbols + r_index; \
1312 cache_ptr->section = (asection *)NULL; \
1313 cache_ptr->addend = ad; \
1314 } else { \
1315 cache_ptr->sym_ptr_ptr = (asymbol **)NULL; \
1316 switch (r_index) { \
1317 case N_TEXT: \
1318 case N_TEXT | N_EXT: \
1319 cache_ptr->section = obj_textsec(abfd); \
1320 cache_ptr->addend = ad - su->textsec->vma; \
1321 break; \
1322 case N_DATA: \
1323 case N_DATA | N_EXT: \
1324 cache_ptr->section = obj_datasec(abfd); \
1325 cache_ptr->addend = ad - su->datasec->vma; \
1326 break; \
1327 case N_BSS: \
1328 case N_BSS | N_EXT: \
1329 cache_ptr->section = obj_bsssec(abfd); \
1330 cache_ptr->addend = ad - su->bsssec->vma; \
1331 break; \
1332 case N_ABS: \
1333 case N_ABS | N_EXT: \
1334 cache_ptr->section = NULL; /* No section */ \
1335 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1336 BFD_ASSERT(1); \
1337 break; \
1338 default: \
1339 cache_ptr->section = NULL; /* No section */ \
1340 cache_ptr->addend = ad; /* FIXME, is this right? */ \
1341 BFD_ASSERT(1); \
1342 break; \
1343 } \
1344 } \
1345
1346void
1347DEFUN(NAME(aout,swap_ext_reloc_in), (abfd, bytes, cache_ptr, symbols),
1348 bfd *abfd AND
1349 struct reloc_ext_external *bytes AND
1350 arelent *cache_ptr AND
1351 asymbol **symbols)
1352{
1353 int r_index;
1354 int r_extern;
1355 unsigned int r_type;
1356 struct aoutdata *su = (struct aoutdata *)(abfd->tdata);
1357
1358 cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
1359
1360 /* now the fun stuff */
1361 if (abfd->xvec->header_byteorder_big_p != false) {
1362 r_index = (bytes->r_index[0] << 16)
1363 | (bytes->r_index[1] << 8)
1364 | bytes->r_index[2];
1365 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
1366 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
1367 >> RELOC_EXT_BITS_TYPE_SH_BIG;
1368 } else {
1369 r_index = (bytes->r_index[2] << 16)
1370 | (bytes->r_index[1] << 8)
1371 | bytes->r_index[0];
1372 r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1373 r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1374 >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1375 }
1376
1377 cache_ptr->howto = howto_table_ext + r_type;
1378 MOVE_ADDRESS(GET_SWORD(abfd,bytes->r_addend));
1379}
1380
1381void
1382DEFUN(NAME(aout,swap_std_reloc_in), (abfd, bytes, cache_ptr, symbols),
1383 bfd *abfd AND
1384 struct reloc_std_external *bytes AND
1385 arelent *cache_ptr AND
1386 asymbol **symbols)
1387{
1388 int r_index;
1389 int r_extern;
1390 unsigned int r_length;
1391 int r_pcrel;
1392 int r_baserel, r_jmptable, r_relative;
1393 struct aoutdata *su = (struct aoutdata *)(abfd->tdata);
1394
1395 cache_ptr->address = (int32_type)(bfd_h_get_32 (abfd, bytes->r_address));
1396
1397 /* now the fun stuff */
1398 if (abfd->xvec->header_byteorder_big_p != false) {
1399 r_index = (bytes->r_index[0] << 16)
1400 | (bytes->r_index[1] << 8)
1401 | bytes->r_index[2];
1402 r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
1403 r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
1404 r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
1405 r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1406 r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
1407 r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
1408 >> RELOC_STD_BITS_LENGTH_SH_BIG;
1409 } else {
1410 r_index = (bytes->r_index[2] << 16)
1411 | (bytes->r_index[1] << 8)
1412 | bytes->r_index[0];
1413 r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1414 r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
1415 r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1416 r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1417 r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1418 r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
1419 >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1420 }
1421
1422 cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
1423 /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
1424
1425 MOVE_ADDRESS(0);
1426}
1427
1428/* Reloc hackery */
1429
1430boolean
1431DEFUN(NAME(aout,slurp_reloc_table),(abfd, asect, symbols),
1432 bfd *abfd AND
1433 sec_ptr asect AND
1434 asymbol **symbols)
1435{
1436 unsigned int count;
1437 bfd_size_type reloc_size;
1438 PTR relocs;
1439 arelent *reloc_cache;
1440 size_t each_size;
1441
1442 if (asect->relocation) return true;
1443
1444 if (asect->flags & SEC_CONSTRUCTOR) return true;
1445
1446 if (asect == obj_datasec (abfd)) {
1447 reloc_size = exec_hdr(abfd)->a_drsize;
1448 goto doit;
1449 }
1450
1451 if (asect == obj_textsec (abfd)) {
1452 reloc_size = exec_hdr(abfd)->a_trsize;
1453 goto doit;
1454 }
1455
1456 bfd_error = invalid_operation;
1457 return false;
1458
1459 doit:
1460 bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1461 each_size = obj_reloc_entry_size (abfd);
1462
1463 count = reloc_size / each_size;
1464
1465
1466 reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
1467 (arelent)));
1468 if (!reloc_cache) {
1469nomem:
1470 bfd_error = no_memory;
1471 return false;
1472 }
1473
1474 relocs = (PTR) bfd_alloc (abfd, reloc_size);
1475 if (!relocs) {
1476 bfd_release (abfd, reloc_cache);
1477 goto nomem;
1478 }
1479
1480 if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
1481 bfd_release (abfd, relocs);
1482 bfd_release (abfd, reloc_cache);
1483 bfd_error = system_call_error;
1484 return false;
1485 }
1486
1487 if (each_size == RELOC_EXT_SIZE) {
1488 register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
1489 unsigned int counter = 0;
1490 arelent *cache_ptr = reloc_cache;
1491
1492 for (; counter < count; counter++, rptr++, cache_ptr++) {
1493 NAME(aout,swap_ext_reloc_in)(abfd, rptr, cache_ptr, symbols);
1494 }
1495 } else {
1496 register struct reloc_std_external *rptr = (struct reloc_std_external*) relocs;
1497 unsigned int counter = 0;
1498 arelent *cache_ptr = reloc_cache;
1499
1500 for (; counter < count; counter++, rptr++, cache_ptr++) {
1501 NAME(aout,swap_std_reloc_in)(abfd, rptr, cache_ptr, symbols);
1502 }
1503
1504 }
1505
1506 bfd_release (abfd,relocs);
1507 asect->relocation = reloc_cache;
1508 asect->reloc_count = count;
1509 return true;
1510}
1511
1512
1513
1514/* Write out a relocation section into an object file. */
1515
1516boolean
1517DEFUN(NAME(aout,squirt_out_relocs),(abfd, section),
1518 bfd *abfd AND
1519 asection *section)
1520{
1521 arelent **generic;
1522 unsigned char *native, *natptr;
1523 size_t each_size;
1524
1525 unsigned int count = section->reloc_count;
1526 size_t natsize;
1527
1528 if (count == 0) return true;
1529
1530 each_size = obj_reloc_entry_size (abfd);
1531 natsize = each_size * count;
1532 native = (unsigned char *) bfd_zalloc (abfd, natsize);
1533 if (!native) {
1534 bfd_error = no_memory;
1535 return false;
1536 }
1537
1538 generic = section->orelocation;
1539
1540 if (each_size == RELOC_EXT_SIZE)
1541 {
1542 for (natptr = native;
1543 count != 0;
1544 --count, natptr += each_size, ++generic)
1545 NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
1546 }
1547 else
1548 {
1549 for (natptr = native;
1550 count != 0;
1551 --count, natptr += each_size, ++generic)
1552 NAME(aout,swap_std_reloc_out)(abfd, *generic, (struct reloc_std_external *)natptr);
1553 }
1554
1555 if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1556 bfd_release(abfd, native);
1557 return false;
1558 }
1559 bfd_release (abfd, native);
1560
1561 return true;
1562}
1563
1564/* This is stupid. This function should be a boolean predicate */
1565unsigned int
1566DEFUN(NAME(aout,canonicalize_reloc),(abfd, section, relptr, symbols),
1567 bfd *abfd AND
1568 sec_ptr section AND
1569 arelent **relptr AND
1570 asymbol **symbols)
1571{
1572 arelent *tblptr = section->relocation;
1573 unsigned int count;
1574
1575 if (!(tblptr || NAME(aout,slurp_reloc_table)(abfd, section, symbols)))
1576 return 0;
1577
1578 if (section->flags & SEC_CONSTRUCTOR) {
1579 arelent_chain *chain = section->constructor_chain;
1580 for (count = 0; count < section->reloc_count; count ++) {
1581 *relptr ++ = &chain->relent;
1582 chain = chain->next;
1583 }
1584 }
1585 else {
1586 tblptr = section->relocation;
1587 if (!tblptr) return 0;
1588
1589 for (count = 0; count++ < section->reloc_count;)
1590 {
1591 *relptr++ = tblptr++;
1592 }
1593 }
1594 *relptr = 0;
1595
1596 return section->reloc_count;
1597}
1598
1599unsigned int
1600DEFUN(NAME(aout,get_reloc_upper_bound),(abfd, asect),
1601 bfd *abfd AND
1602 sec_ptr asect)
1603{
1604 if (bfd_get_format (abfd) != bfd_object) {
1605 bfd_error = invalid_operation;
1606 return 0;
1607 }
1608 if (asect->flags & SEC_CONSTRUCTOR) {
1609 return (sizeof (arelent *) * (asect->reloc_count+1));
1610 }
1611
1612
1613 if (asect == obj_datasec (abfd))
1614 return (sizeof (arelent *) *
1615 ((exec_hdr(abfd)->a_drsize / obj_reloc_entry_size (abfd))
1616 +1));
1617
1618 if (asect == obj_textsec (abfd))
1619 return (sizeof (arelent *) *
1620 ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
1621 +1));
1622
1623 bfd_error = invalid_operation;
1624 return 0;
1625}
1626
1627\f
1628 unsigned int
1629DEFUN(NAME(aout,get_symtab_upper_bound),(abfd),
1630 bfd *abfd)
1631{
1632 if (!NAME(aout,slurp_symbol_table)(abfd)) return 0;
1633
1634 return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
1635}
1636 alent *
1637DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol),
1638 bfd *ignore_abfd AND
1639 asymbol *ignore_symbol)
1640{
1641return (alent *)NULL;
1642}
1643
1644
1645void
1646DEFUN(NAME(aout,print_symbol),(ignore_abfd, afile, symbol, how),
1647 bfd *ignore_abfd AND
1648 PTR afile AND
1649 asymbol *symbol AND
1650 bfd_print_symbol_enum_type how)
1651{
1652 FILE *file = (FILE *)afile;
1653
1654 switch (how) {
1655 case bfd_print_symbol_name_enum:
1656 fprintf(file,"%s", symbol->name);
1657 break;
1658 case bfd_print_symbol_type_enum:
1659 fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1660 (unsigned)(aout_symbol(symbol)->other & 0xff),
1661 (unsigned)(aout_symbol(symbol)->type));
1662 break;
1663 case bfd_print_symbol_all_enum:
1664 {
1665 CONST char *section_name = symbol->section == (asection *)NULL ?
1666 "*abs" : symbol->section->name;
1667
1668 bfd_print_symbol_vandf((PTR)file,symbol);
1669
1670 fprintf(file," %-5s %04x %02x %02x %s",
1671 section_name,
1672 (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1673 (unsigned)(aout_symbol(symbol)->other & 0xff),
1674 (unsigned)(aout_symbol(symbol)->type & 0xff),
1675 symbol->name);
1676 }
1677 break;
1678 }
1679}
1680
1681/*
1682 provided a bfd, a section and an offset into the section, calculate
1683 and return the name of the source file and the line nearest to the
1684 wanted location.
1685*/
1686
1687boolean
1688DEFUN(NAME(aout,find_nearest_line),(abfd,
1689 section,
1690 symbols,
1691 offset,
1692 filename_ptr,
1693 functionname_ptr,
1694 line_ptr),
1695 bfd *abfd AND
1696 asection *section AND
1697 asymbol **symbols AND
1698 bfd_vma offset AND
1699 CONST char **filename_ptr AND
1700 CONST char **functionname_ptr AND
1701 unsigned int *line_ptr)
1702{
1703 /* Run down the file looking for the filename, function and linenumber */
1704 asymbol **p;
1705 static char buffer[100];
1706 bfd_vma high_line_vma = ~0;
1707 bfd_vma low_func_vma = 0;
1708 asymbol *func = 0;
1709 *filename_ptr = abfd->filename;
1710 *functionname_ptr = 0;
1711 *line_ptr = 0;
1712 if (symbols != (asymbol **)NULL) {
1713 for (p = symbols; *p; p++) {
1714 aout_symbol_type *q = (aout_symbol_type *)(*p);
1715 switch (q->type){
1716 case N_SO:
1717 *filename_ptr = q->symbol.name;
1718 if (obj_textsec(abfd) != section) {
1719 return true;
1720 }
1721 break;
1722 case N_SLINE:
1723
1724 case N_DSLINE:
1725 case N_BSLINE:
1726 /* We'll keep this if it resolves nearer than the one we have already */
1727 if (q->symbol.value >= offset &&
1728 q->symbol.value < high_line_vma) {
1729 *line_ptr = q->desc;
1730 high_line_vma = q->symbol.value;
1731 }
1732 break;
1733 case N_FUN:
1734 {
1735 /* We'll keep this if it is nearer than the one we have already */
1736 if (q->symbol.value >= low_func_vma &&
1737 q->symbol.value <= offset) {
1738 low_func_vma = q->symbol.value;
1739 func = (asymbol *)q;
1740 }
1741 if (*line_ptr && func) {
1742 CONST char *function = func->name;
1743 char *p;
1744 strncpy(buffer, function, sizeof(buffer)-1);
1745 buffer[sizeof(buffer)-1] = 0;
1746 /* Have to remove : stuff */
1747 p = strchr(buffer,':');
6f715d66 1748 if (p != NULL) { *p = NULL; }
7ed4093a
SC
1749 *functionname_ptr = buffer;
1750 return true;
1751
1752 }
1753 }
1754 break;
1755 }
1756 }
1757 }
1758
1759 return true;
1760
1761}
1762
1763int
1764DEFUN(NAME(aout,sizeof_headers),(ignore_abfd, execable),
1765 bfd *ignore_abfd AND
1766 boolean execable)
1767{
1768 return EXEC_BYTES_SIZE;
1769}
This page took 0.219986 seconds and 4 git commands to generate.