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