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