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