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