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