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