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