Mon Aug 19 13:48:22 1991 Roland H. Pesch (pesch at cygint.cygnus.com)
[deliverable/binutils-gdb.git] / bfd / aoutx.h
1 /* BFD semi-generic back-end for a.out binaries
2 Copyright (C) 1990-1991 Free Software Foundation, Inc.
3 Written by Cygnus Support.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /*doc*
22 @section a.out backends
23
24 BFD supports a number of different flavours of a.out format, though
25 the major differences are only the sizes of the structures on disk,
26 and the shape of the relocation information.
27
28 The support is split into a basic support file @code{aoutx.h} and
29 other files which derive functions from the base. One derivation file
30 is @code{aoutf1.h} (for a.out flavour 1), and adds to the basic a.out
31 functions support for sun3, sun4, 386 and 29k a.out files, to create a
32 target jump vector for a specific target.
33
34 This information is further split out into more specific files for each
35 machine, including @code{sunos.c} - for sun3 and sun4 and
36 @code{demo64} for a demonstration of a 64 bit a.out format.
37
38 The base file @code{aoutx.h} defines general mechanisms for reading
39 and writing records to and from disk, and various other methods which
40 BFD requires. It is included by @code{aout32.c} and @code{aout64.c} to
41 form the names aout_32_swap_exec_header_in,
42 aout_64_swap_exec_header_in, etc.
43
44 As 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
51 Which 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
61 from 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
69 requires all the names from aout32.c, and produces the jump vector
70
71 @example
72 sunos_big_vec
73 @end example
74
75 */
76
77 #define KEEPIT flags
78 #define KEEPITTYPE int
79
80 #include "bfd.h"
81 #include <sysdep.h>
82 #include <ansidecl.h>
83
84 struct external_exec;
85 #include "libaout.h"
86 #include "libbfd.h"
87 #include "aout64.h"
88 #include "stab.gnu.h"
89 #include "ar.h"
90
91 void (*bfd_error_trap)();
92
93 /*doc*
94 @subsection relocations
95 The file @code{aoutx.h} caters for both the @emph{standard} and
96 @emph{extended} forms of a.out relocation records.
97
98 The standard records are characterised by containing only an address,
99 a symbol index and a type field. The extended records (used on 29ks
100 and sparcs) also have a full integer for an addend.
101 */
102 #define CTOR_TABLE_RELOC_IDX 2
103
104 /* start-sanitize-v9 */
105 /* Provided the symbol, returns the value reffed */
106 static bfd_vma
107 DEFUN(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
131 static bfd_reloc_status_enum_type
132 DEFUN(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
146 static bfd_reloc_status_enum_type
147 DEFUN(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
166 static bfd_reloc_status_enum_type
167 DEFUN(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
184 static bfd_reloc_status_enum_type
185 DEFUN(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
202 static r64()
203 {
204 abort();
205 }
206
207 /* end-sanitize-v9 */
208
209 static 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),
234 HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
235
236 /* start-sanitize-v9 */
237
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),
243
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),
247
248
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),
254
255 /* end-sanitize-v9 */
256 };
257
258 /* Convert standard reloc records to "arelent" format (incl byte swap). */
259
260 static reloc_howto_type howto_table_std[] = {
261 /* type rs size bsz pcrel bitpos abs ovrf sf name part_inpl readmask setmask pcdone */
262 HOWTO( 0, 0, 0, 8, false, 0, true, true,0,"8", true, 0x000000ff,0x000000ff, false),
263 HOWTO( 1, 0, 1, 16, false, 0, true, true,0,"16", true, 0x0000ffff,0x0000ffff, false),
264 HOWTO( 2, 0, 2, 32, false, 0, true, true,0,"32", true, 0xffffffff,0xffffffff, false),
265 HOWTO( 3, 0, 3, 64, false, 0, true, true,0,"64", true, 0xdeaddead,0xdeaddead, false),
266 HOWTO( 4, 0, 0, 8, true, 0, false, true,0,"DISP8", true, 0x000000ff,0x000000ff, false),
267 HOWTO( 5, 0, 1, 16, true, 0, false, true,0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
268 HOWTO( 6, 0, 2, 32, true, 0, false, true,0,"DISP32", true, 0xffffffff,0xffffffff, false),
269 HOWTO( 7, 0, 3, 64, true, 0, false, true,0,"DISP64", true, 0xfeedface,0xfeedface, false),
270 };
271
272
273 bfd_error_vector_type bfd_error_vector;
274
275 /*doc*
276 @subsection Internal Entry Points
277 @code{aoutx.h} exports several routines for accessing the contents of
278 an a.out file, which are gathered and exported in turn by various
279 format specific files (eg sunos.c).
280 */
281
282 /*doc*
283 *i aout_<size>_swap_exec_header_in
284 Swaps the information in an executable header taken from a raw byte stream memory image,
285 into the internal exec_header structure.
286 *; PROTO(void, aout_<size>_swap_exec_header_in,
287 (bfd *abfd,
288 struct external_exec *raw_bytes,
289 struct internal_exec *execp));
290 */
291
292 void
293 DEFUN(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
311 /*doc*
312 *i aout_<size>_swap_exec_header_out
313 Swaps the information in an internal exec header structure into the
314 supplied buffer ready for writing to disk.
315 *; PROTO(void, aout_<size>_swap_exec_header_out,
316 (bfd *abfd,
317 struct internal_exec *execp,
318 struct external_exec *raw_bytes));
319 */
320 void
321 DEFUN(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
339 struct container {
340 struct aoutdata a;
341 struct internal_exec e;
342 };
343
344
345 /*doc*
346 *i aout_<size>_some_aout_object_p
347
348 Some A.OUT variant thinks that the file whose format we're checking
349 is an a.out file. Do some more checking, and set up for access if
350 it really is. Call back to the calling environments "finish up"
351 function just before returning, to handle any last-minute setup.
352
353 *; PROTO(bfd_target *, aout_<size>_some_aout_object_p,
354 (bfd *abfd,
355 bfd_target *(*callback_to_real_object_p)()));
356 */
357
358 bfd_target *
359 DEFUN(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
507 /*doc*
508 *i aout_<size>_mkobject
509
510 This routine initializes a BFD for use with a.out files.
511
512 *; PROTO(boolean, aout_<size>_mkobject, (bfd *));
513 */
514
515 boolean
516 DEFUN(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
546
547 /*doc*
548 *i aout_<size>_machine_type
549
550 Keep track of machine architecture and machine type for a.out's.
551 Return the machine_type for a particular arch&machine, or M_UNKNOWN
552 if that exact arch&machine can't be represented in a.out format.
553
554 If the architecture is understood, machine type 0 (default) should
555 always be understood.
556
557 *; PROTO(enum machine_type, aout_<size>_machine_type,
558 (enum bfd_architecture arch,
559 unsigned long machine));
560 */
561
562 enum machine_type
563 DEFUN(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
601 /*doc*
602 *i aout_<size>_set_arch_mach
603
604 Sets the architecture and the machine of the BFD to those values
605 supplied. Verifies that the format can support the architecture
606 required.
607
608 *; PROTO(boolean, aout_<size>_set_arch_mach,
609 (bfd *,
610 enum bfd_architecture,
611 unsigned long machine));
612 */
613
614 boolean
615 DEFUN(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 }
627
628 /*doc*
629 *i aout_<size>new_section_hook
630
631 Called by the BFD in response to a @code{bfd_make_section} request.
632 *; PROTO(boolean, aout_<size>_new_section_hook,
633 (bfd *abfd,
634 asection *newsect));
635 */
636 boolean
637 DEFUN(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
665 boolean
666 DEFUN(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
720 zero in the "value" field. Nonzeroes there are fortrancommon
721 symbols. */
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
726 a 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
731 are 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
747 stabilised these should be inlined into their (single) caller */
748
749 static void
750 DEFUN(translate_from_native_sym_flags,(sym_pointer, cache_ptr, abfd),
751 struct external_nlist *sym_pointer AND
752 aout_symbol_type *cache_ptr AND
753 bfd *abfd)
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 ;
790
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;
810 default:
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 }
821 if ((cache_ptr->type | N_EXT) == (N_INDR | N_EXT)) {
822 /* Two symbols in a row for an INDR message. The first symbol
823 contains the name we will match, the second symbol contains the
824 name the first name is translated into. It is supplied to us
825 undefined. This is good, since we want to pull in any files which
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
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 {
858
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 }
871
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 }
878
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 */
886
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
908 static void
909 DEFUN(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 }
939 if (cache_ptr->flags & (BSF_WARNING)) {
940 (sym_pointer+1)->e_type[0] = 1;
941 }
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
963 function exits. We read the strings into a buffer large enough to
964 hold them all plus all the cached symbol entries. */
965
966 asymbol *
967 DEFUN(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
977 boolean
978 DEFUN(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)));
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);
1008 bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1009 if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1010 bailout:
1011 if (syms) free (syms);
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;
1049 free((PTR)syms);
1050
1051 return true;
1052 }
1053
1054
1055 void
1056 DEFUN(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) {
1119 g->KEEPIT = (KEEPITTYPE) count;
1120 }
1121 }
1122 }
1123
1124
1125
1126 unsigned int
1127 DEFUN(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
1146 void
1147 DEFUN(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
1179 r_index = ((*(g->sym_ptr_ptr))->KEEPIT);
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
1237 void
1238 DEFUN(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
1265 r_index = stoi((*(g->sym_ptr_ptr))->KEEPIT);
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
1348 void
1349 DEFUN(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
1383 void
1384 DEFUN(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
1432 boolean
1433 DEFUN(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) {
1471 nomem:
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
1518 boolean
1519 DEFUN(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 */
1567 unsigned int
1568 DEFUN(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
1601 unsigned int
1602 DEFUN(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
1631 DEFUN(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 *
1639 DEFUN(NAME(aout,get_lineno),(ignore_abfd, ignore_symbol),
1640 bfd *ignore_abfd AND
1641 asymbol *ignore_symbol)
1642 {
1643 return (alent *)NULL;
1644 }
1645
1646
1647 void
1648 DEFUN(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 /*
1684 provided a BFD, a section and an offset into the section, calculate
1685 and return the name of the source file and the line nearest to the
1686 wanted location.
1687 */
1688
1689 boolean
1690 DEFUN(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,':');
1750 if (p != NULL) { *p = NULL; }
1751 *functionname_ptr = buffer;
1752 return true;
1753
1754 }
1755 }
1756 break;
1757 }
1758 }
1759 }
1760
1761 return true;
1762
1763 }
1764
1765 int
1766 DEFUN(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.069416 seconds and 4 git commands to generate.