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