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