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