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