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