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