Various portability lints.
[external/binutils.git] / bfd / sunos.c
1 /*** bfd backend for sunos binaries */
2 /** a.out files */
3
4 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
5
6 This file is part of BFD, the Binary File Diddler.
7
8 BFD is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
11 any later version.
12
13 BFD is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with BFD; see the file COPYING.  If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22 /* $Id$ */
23
24 #include <ansidecl.h>
25 #include "sysdep.h"
26 #include "bfd.h"
27 #include "libbfd.h"
28
29 #include "a.out.sun4.h"
30 #include "a.out.gnu.h"
31 #include "stab.gnu.h"
32 #include "ar.h"
33 #include "liba.out.h"           /* BFD a.out internal data structures */
34
35 void (*bfd_error_trap)();
36
37 /*SUPPRESS558*/
38 /*SUPPRESS529*/
39
40 #define CTOR_TABLE_RELOC_IDX 2
41 static  reloc_howto_type howto_table_ext[] = 
42 {
43   HOWTO(RELOC_8,      0,  0,    8,  false, 0, true,  true,0,"8",      false, 0,0x000000ff, false),
44   HOWTO(RELOC_16,     0,  1,    16, false, 0, true,  true,0,"16",      false, 0,0x0000ffff, false),
45   HOWTO(RELOC_32,     0,  2,    32, false, 0, true,  true,0,"32",      false, 0,0xffffffff, false),
46   HOWTO(RELOC_DISP8,  0,  0,    8,  true,  0, false, true,0,"DISP8",    false, 0,0x000000ff, false),
47   HOWTO(RELOC_DISP16, 0,  1,    16, true,  0, false, true,0,"DISP16",   false, 0,0x0000ffff, false),
48   HOWTO(RELOC_DISP32, 0,  2,    32, true,  0, false, true,0,"DISP32",   false, 0,0xffffffff, false),
49   HOWTO(RELOC_WDISP30,2,  2,    30, true,  0, false, true,0,"WDISP30",  false, 0,0x3fffffff, false),
50   HOWTO(RELOC_WDISP22,2,  2,    22, true,  0, false, true,0,"WDISP22",  false, 0,0x003fffff, false),
51   HOWTO(RELOC_HI22,   10, 2,    22, false, 0, false, true,0,"HI22",     false, 0,0x003fffff, false),
52   HOWTO(RELOC_22,      0, 2,    22, false, 0, false, true,0,"22",       false, 0,0x003fffff, false),
53   HOWTO(RELOC_13,       0, 2,   13, false, 0, false, true,0,"13",       false, 0,0x00001fff, false),
54   HOWTO(RELOC_LO10,     0, 2,   10, false, 0, false, true,0,"LO10",     false, 0,0x000003ff, false),
55   HOWTO(RELOC_SFA_BASE,0, 2,    32, false, 0, false, true,0,"SFA_BASE", false, 0,0xffffffff, false),
56   HOWTO(RELOC_SFA_OFF13,0,2,    32, false, 0, false, true,0,"SFA_OFF13",false, 0,0xffffffff, false),
57   HOWTO(RELOC_BASE10, 0,  2,    16, false, 0, false, true,0,"BASE10",   false, 0,0x0000ffff, false),
58   HOWTO(RELOC_BASE13, 0,  2,    13, false, 0, false, true,0,"BASE13",   false, 0,0x00001fff, false),
59   HOWTO(RELOC_BASE22, 0,  2,    0,  false, 0, false, true,0,"BASE22",   false, 0,0x00000000, false),
60   HOWTO(RELOC_PC10,   0,  2,    10, false, 0, false, true,0,"PC10",     false, 0,0x000003ff, false),
61   HOWTO(RELOC_PC22,   0,  2,    22, false, 0, false, true,0,"PC22",     false, 0,0x003fffff, false),
62   HOWTO(RELOC_JMP_TBL,0,  2,    32, false, 0, false, true,0,"JMP_TBL",  false, 0,0xffffffff, false),
63   HOWTO(RELOC_SEGOFF16,0, 2,    0,  false, 0, false, true,0,"SEGOFF16", false, 0,0x00000000, false),
64   HOWTO(RELOC_GLOB_DAT,0, 2,    0,  false, 0, false, true,0,"GLOB_DAT", false, 0,0x00000000, false),
65   HOWTO(RELOC_JMP_SLOT,0, 2,    0,  false, 0, false, true,0,"JMP_SLOT", false, 0,0x00000000, false),
66   HOWTO(RELOC_RELATIVE,0, 2,    0,  false, 0, false, true,0,"RELATIVE", false, 0,0x00000000, false),
67   HOWTO(RELOC_JUMPTARG,2, 13,   16, true,  0, false, true,0,"JUMPTARG", false, 0,0x0000ffff, false),
68   HOWTO(RELOC_CONST,    0, 13,  16, false, 0, false, true,0,"CONST",    false, 0,0x0000ffff, false),
69   HOWTO(RELOC_CONSTH, 16, 13,   16, false, 0, false, true,0,"CONSTH",   false, 0,0x0000ffff, false),
70 };
71
72 /* Convert standard reloc records to "arelent" format (incl byte swap).  */
73
74 static  reloc_howto_type howto_table_std[] = {
75   /* type           rs   size bsz  pcrel bitpos  abs ovrf sf name    part_inpl   readmask  setmask  pcdone */
76 HOWTO( 0,              0,  0,   8,  false, 0, true,  true,0,"8",        true, 0x000000ff,0x000000ff, false),
77 HOWTO( 1,              0,  1,   16, false, 0, true,  true,0,"16",       true, 0x0000ffff,0x0000ffff, false),
78 HOWTO( 2,              0,  2,   32, false, 0, true,  true,0,"32",       true, 0xffffffff,0xffffffff, false),
79 HOWTO( 3,              0,  3,   64, false, 0, true,  true,0,"64",       true, 0xdeaddead,0xdeaddead, false),
80 HOWTO( 4,              0,  0,   8,  true,  0, false, true,0,"DISP8",    true, 0x000000ff,0x000000ff, false),
81 HOWTO( 5,              0,  1,   16, true,  0, false, true,0,"DISP16",   true, 0x0000ffff,0x0000ffff, false),
82 HOWTO( 6,              0,  2,   32, true,  0, false, true,0,"DISP32",   true, 0xffffffff,0xffffffff, false),
83 HOWTO( 7,              0,  3,   64, true,  0, false, true,0,"DISP64",   true, 0xfeedface,0xfeedface, false),
84 };
85
86
87 bfd_error_vector_type bfd_error_vector;
88
89 PROTO (void , sunos4_write_syms, ());
90 PROTO (static boolean,sunos4_squirt_out_relocs,(bfd *abfd, asection *section));
91
92
93 static size_t
94 reloc_size_func(abfd)
95 bfd *abfd;
96 {
97   switch (bfd_get_architecture (abfd)) {
98   case bfd_arch_sparc:
99   case bfd_arch_a29k:
100     return  RELOC_EXT_SIZE;
101   default:
102     return  RELOC_STD_SIZE;
103   }
104 }
105
106 static void
107 DEFUN(bfd_aout_swap_exec_header_in,(abfd, raw_bytes, execp),
108       bfd *abfd AND
109       unsigned char *raw_bytes AND
110       struct exec *execp)
111 {
112   struct exec_bytes *bytes = (struct exec_bytes *)raw_bytes;
113
114   /* Now fill in fields in the execp, from the bytes in the raw data.  */
115   execp->a_info   = bfd_h_getlong (abfd, bytes->a_info);
116   execp->a_text   = bfd_h_getlong (abfd, bytes->a_text);
117   execp->a_data   = bfd_h_getlong (abfd, bytes->a_data);
118   execp->a_bss    = bfd_h_getlong (abfd, bytes->a_bss);
119   execp->a_syms   = bfd_h_getlong (abfd, bytes->a_syms);
120   execp->a_entry  = bfd_h_getlong (abfd, bytes->a_entry);
121   execp->a_trsize = bfd_h_getlong (abfd, bytes->a_trsize);
122   execp->a_drsize = bfd_h_getlong (abfd, bytes->a_drsize);
123 }
124
125 static void
126 DEFUN(bfd_aout_swap_exec_header_out,(abfd, execp, raw_bytes),
127      bfd *abfd AND
128      struct exec *execp AND 
129      unsigned char *raw_bytes)
130 {
131   struct exec_bytes *bytes = (struct exec_bytes *)raw_bytes;
132
133   /* Now fill in fields in the raw data, from the fields in the exec struct. */
134   bfd_h_putlong (abfd, execp->a_info  , bytes->a_info);
135   bfd_h_putlong (abfd, execp->a_text  , bytes->a_text);
136   bfd_h_putlong (abfd, execp->a_data  , bytes->a_data);
137   bfd_h_putlong (abfd, execp->a_bss   , bytes->a_bss);
138   bfd_h_putlong (abfd, execp->a_syms  , bytes->a_syms);
139   bfd_h_putlong (abfd, execp->a_entry , bytes->a_entry);
140   bfd_h_putlong (abfd, execp->a_trsize, bytes->a_trsize);
141   bfd_h_putlong (abfd, execp->a_drsize, bytes->a_drsize);
142 }
143
144 bfd_target *
145 sunos4_object_p (abfd)
146      bfd *abfd;
147 {
148   unsigned char magicbuf[4];    /* Raw bytes of magic number from file */
149   unsigned long magic;          /* Swapped magic number */
150   unsigned char exec_bytes[EXEC_BYTES_SIZE];    /* Raw bytes of exec hdr */
151   struct exec *execp;
152   PTR rawptr;
153
154   bfd_error = system_call_error;
155
156   if (bfd_read ((PTR)magicbuf, 1, sizeof (magicbuf), abfd) !=
157       sizeof (magicbuf))
158     return 0;
159   magic = bfd_h_getlong (abfd, magicbuf);
160
161   if (N_BADMAG (*((struct exec *) &magic))) return 0;
162
163   if (bfd_seek (abfd, 0L, false) < 0) return 0;
164
165   if (bfd_read ((PTR) exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
166       != EXEC_BYTES_SIZE) {
167     bfd_error = wrong_format;
168     return 0;
169   }
170
171   /* Use an intermediate variable for clarity */
172   rawptr = (PTR) bfd_zalloc (abfd, sizeof (struct sunexdata) + sizeof (struct exec));
173
174   if (rawptr == NULL) {
175     bfd_error = no_memory;
176     return 0;
177   }
178
179   set_tdata (abfd, ((struct sunexdata *) rawptr));
180   exec_hdr (abfd) = execp =
181     (struct exec *) ((char *)rawptr + sizeof (struct sunexdata));
182
183   bfd_aout_swap_exec_header_in (abfd, exec_bytes, execp);
184
185   /* Set the file flags */
186   abfd->flags = NO_FLAGS;
187   if (execp->a_drsize || execp->a_trsize)
188     abfd->flags |= HAS_RELOC;
189   if (execp->a_entry) 
190     abfd->flags |= EXEC_P;
191   if (execp->a_syms) 
192     abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
193
194
195   if (N_MAGIC (*execp) == ZMAGIC) abfd->flags |= D_PAGED;
196   if (N_MAGIC (*execp) == NMAGIC) abfd->flags |= WP_TEXT;
197
198   /* Determine the architecture and machine type of the object file.  */
199   abfd->obj_arch = bfd_arch_unknown;    /* Default values */
200   abfd->obj_machine = 0;
201   switch (N_MACHTYPE (*execp)) {
202
203   case M_UNKNOWN:
204         break;
205
206   case M_68010:
207         abfd->obj_arch = bfd_arch_m68k;
208         abfd->obj_machine = 68010;
209         break;
210
211   case M_68020:
212         abfd->obj_arch = bfd_arch_m68k;
213         abfd->obj_machine = 68020;
214         break;
215
216   case M_SPARC:
217         abfd->obj_arch = bfd_arch_sparc;
218         break;
219
220   case M_386:
221         abfd->obj_arch = bfd_arch_i386;
222         break;
223
224   case M_29K:
225         abfd->obj_arch = bfd_arch_a29k;
226         break;
227
228   default:
229         abfd->obj_arch = bfd_arch_obscure;
230         break;
231   }
232
233   bfd_get_start_address (abfd) = execp->a_entry;
234
235   bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct nlist);
236
237   /* Remember the positions of the string table and symbol table.  */
238   obj_str_filepos (abfd) = N_STROFF (*execp);
239   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
240
241   /* create the sections.  This is raunchy, but bfd_close wants to reclaim
242      them */
243   obj_textsec (abfd) = (asection *)NULL;
244   obj_datasec (abfd) = (asection *)NULL;
245   obj_bsssec (abfd) = (asection *)NULL;
246   obj_aout_symbols(abfd) = (aout_symbol_type *)NULL;
247   (void)bfd_make_section(abfd, ".text");
248   (void)bfd_make_section(abfd, ".data");
249   (void)bfd_make_section(abfd, ".bss");
250
251   obj_datasec (abfd)->size = execp->a_data;
252   obj_bsssec (abfd)->size = execp->a_bss;
253   obj_textsec (abfd)->size = execp->a_text;
254   obj_datasec (abfd)->vma = N_DATADDR(*execp);
255   obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
256   obj_textsec (abfd)->vma = N_TXTADDR(*execp);
257
258   obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
259   obj_datasec (abfd)->filepos = N_DATOFF(*execp);
260
261   obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
262   obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
263
264   obj_textsec (abfd)->flags = (execp->a_trsize != 0 ?
265                                (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
266                                (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
267   obj_datasec (abfd)->flags = (execp->a_drsize != 0 ?
268                                (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_HAS_CONTENTS) :
269                                (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS));
270   obj_bsssec (abfd)->flags = SEC_ALLOC;
271
272   abfd->sections = obj_textsec (abfd);
273   obj_textsec (abfd)->next = obj_datasec (abfd);
274   obj_datasec (abfd)->next = obj_bsssec (abfd);
275   return abfd->xvec;
276 }
277
278
279 boolean
280 sunos4_mkobject (abfd)
281      bfd *abfd;
282 {
283   char *rawptr;
284
285   bfd_error = system_call_error;
286
287   /* Use an intermediate variable for clarity */
288   rawptr = bfd_zalloc (abfd, sizeof (struct sunexdata) + sizeof (struct exec));
289
290   if (rawptr == NULL) {
291     bfd_error = no_memory;
292     return false;
293   }
294
295   set_tdata (abfd, (struct sunexdata *) rawptr);
296   exec_hdr (abfd) = (struct exec *) (rawptr + sizeof (struct sunexdata));
297
298   /* For simplicity's sake we just make all the sections right here. */
299
300   obj_textsec (abfd) = (asection *)NULL;
301   obj_datasec (abfd) = (asection *)NULL;
302   obj_bsssec (abfd) = (asection *)NULL;
303   bfd_make_section (abfd, ".text");
304   bfd_make_section (abfd, ".data");
305   bfd_make_section (abfd, ".bss");
306
307   return true;
308 }
309
310 /* Keep track of machine architecture and machine type for a.out's.
311    Return the machine_type for a particular arch&machine, or M_UNKNOWN
312    if that exact arch&machine can't be represented in a.out format.
313
314    If the architecture is understood, machine type 0 (default) should
315    always be understood.  */
316
317 static enum machine_type
318 aout_machine_type (arch, machine)
319      enum bfd_architecture arch;
320      unsigned long machine;
321 {
322   enum machine_type arch_flags;
323
324   arch_flags = M_UNKNOWN;
325
326   switch (arch) {
327   case bfd_arch_sparc:
328     if (machine == 0)   arch_flags = M_SPARC;
329     break;
330
331   case bfd_arch_m68k:
332     switch (machine) {
333     case 0:             arch_flags = M_68010; break;
334     case 68000:         arch_flags = M_UNKNOWN; break;
335     case 68010:         arch_flags = M_68010; break;
336     case 68020:         arch_flags = M_68020; break;
337     default:            arch_flags = M_UNKNOWN; break;
338     }
339     break;
340
341   case bfd_arch_i386:
342     if (machine == 0)   arch_flags = M_386;
343     break;
344
345   case bfd_arch_a29k:
346     if (machine == 0)   arch_flags = M_29K;
347     break;
348
349   default:
350     arch_flags = M_UNKNOWN;
351     break;
352   }
353   return arch_flags;
354 }
355
356 boolean
357 sunos4_set_arch_mach (abfd, arch, machine)
358      bfd *abfd;
359      enum bfd_architecture arch;
360      unsigned long machine;
361 {
362   abfd->obj_arch = arch;
363   abfd->obj_machine = machine;
364   if (arch != bfd_arch_unknown &&
365       aout_machine_type (arch, machine) == M_UNKNOWN)
366     return false;               /* We can't represent this type */
367   return true;                  /* We're easy ... */
368 }
369
370 boolean
371 sunos4_write_object_contents (abfd)
372      bfd *abfd;
373 {
374   size_t data_pad = 0;
375   unsigned char exec_bytes[EXEC_BYTES_SIZE];
376   struct exec *execp = exec_hdr (abfd);
377
378   execp->a_text = obj_textsec (abfd)->size;
379
380   /* Magic number, maestro, please!  */
381   switch (bfd_get_architecture(abfd)) {
382   case bfd_arch_m68k:
383     switch (bfd_get_machine(abfd)) {
384     case 68010:
385       N_SET_MACHTYPE(*execp, M_68010);
386       break;
387     default:
388     case 68020:
389       N_SET_MACHTYPE(*execp, M_68020);
390       break;
391     }
392     break;
393   case bfd_arch_sparc:
394     N_SET_MACHTYPE(*execp, M_SPARC);
395     break;
396   case bfd_arch_i386:
397     N_SET_MACHTYPE(*execp, M_386);
398     break;
399   case bfd_arch_a29k:
400     N_SET_MACHTYPE(*execp, M_29K);
401     break;
402   default:
403     N_SET_MACHTYPE(*execp, M_UNKNOWN);
404   }
405
406   N_SET_MAGIC (*execp, OMAGIC);
407   if (abfd->flags & D_PAGED) {
408     /* This is not strictly true, but will probably do for the default
409         case.  FIXME.  */
410     execp->a_text = obj_textsec (abfd)->size + sizeof(struct exec);
411     N_SET_MAGIC (*execp, ZMAGIC);
412   } else if (abfd->flags & WP_TEXT) {
413     N_SET_MAGIC (*execp, NMAGIC);
414   }
415   N_SET_FLAGS (*execp, 0x1);    /* copied from ld.c; who the hell knows? */
416
417   if (abfd->flags & D_PAGED) 
418       {
419         data_pad = ((obj_datasec(abfd)->size + PAGE_SIZE -1)
420                     & (- PAGE_SIZE)) - obj_datasec(abfd)->size;
421
422         if (data_pad > obj_bsssec(abfd)->size)
423           execp->a_bss = 0;
424         else 
425           execp->a_bss = obj_bsssec(abfd)->size - data_pad;
426         execp->a_data = obj_datasec(abfd)->size + data_pad;
427
428       }
429   else {
430     execp->a_data = obj_datasec (abfd)->size;
431     execp->a_bss = obj_bsssec (abfd)->size;
432   }
433
434   execp->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
435   execp->a_entry = bfd_get_start_address (abfd);
436
437   execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
438                      reloc_size_func(abfd));
439                        
440   execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
441                      reloc_size_func(abfd));
442
443   bfd_aout_swap_exec_header_out (abfd, execp, exec_bytes);
444
445   bfd_seek (abfd, 0L, false);
446   bfd_write ((PTR) exec_bytes, 1, EXEC_BYTES_SIZE, abfd);
447
448   /* Now write out reloc info, followed by syms and strings */
449
450   if (bfd_get_symcount (abfd) != 0) 
451     {
452       bfd_seek (abfd,
453                 (long)(N_SYMOFF(*execp)), false);
454
455       sunos4_write_syms (abfd);
456
457       bfd_seek (abfd,   (long)(N_TRELOFF(*execp)), false);
458
459       if (!sunos4_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
460       bfd_seek (abfd, (long)(N_DRELOFF(*execp)), false);
461
462       if (!sunos4_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
463     }
464   return true;
465 }
466 \f
467 /* core files */
468
469 #define CORE_MAGIC 0x080456
470 #define CORE_NAMELEN 16
471
472 /* The core structure is taken from the Sun documentation.
473    Unfortunately, they don't document the FPA structure, or at least I
474    can't find it easily.  Fortunately the core header contains its own
475    length.  So this shouldn't cause problems, except for c_ucode, which
476    so far we don't use but is easy to find with a little arithmetic. */
477
478 /* But the reg structure can be gotten from the SPARC processor handbook.
479    This really should be in a GNU include file though so that gdb can use
480    the same info. */
481 struct regs {
482   int r_psr;
483   int r_pc;
484   int r_npc;
485   int r_y;
486   int r_g1;
487   int r_g2;
488   int r_g3;
489   int r_g4;
490   int r_g5;
491   int r_g6;
492   int r_g7;
493   int r_o0;
494   int r_o1;
495   int r_o2;
496   int r_o3;
497   int r_o4;
498   int r_o5;
499   int r_o6;
500   int r_o7;
501 };
502
503 /* Taken from Sun documentation: */
504
505 /* FIXME:  It's worse than we expect.  This struct contains TWO substructs
506    neither of whose size we know, WITH STUFF IN BETWEEN THEM!  We can't
507    even portably access the stuff in between!  */
508
509 struct core {
510   int c_magic;                  /* Corefile magic number */
511   int c_len;                    /* Sizeof (struct core) */
512   struct regs c_regs;           /* General purpose registers */
513   struct exec c_aouthdr;        /* A.out header */
514   int c_signo;                  /* Killing signal, if any */
515   int c_tsize;                  /* Text size (bytes) */
516   int c_dsize;                  /* Data size (bytes) */
517   int c_ssize;                  /* Stack size (bytes) */
518   char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
519   double fp_stuff[1];           /* external FPU state (size unknown by us) */
520                 /* The type "double" is critical here, for alignment.
521                    SunOS declares a struct here, but the struct's alignment
522                    is double since it contains doubles.  */
523   int c_ucode;                  /* Exception no. from u_code */
524                 /* (this member is not accessible by name since we don't
525                     portably know the size of fp_stuff.) */
526 };
527
528 /* Supposedly the user stack grows downward from the bottom of kernel memory.
529    Presuming that this remains true, this definition will work. */
530 #define USRSTACK (-(128*1024*1024))
531
532 PROTO (static void, swapcore, (bfd *abfd, struct core *core));
533
534 /* need this cast b/c ptr is really void * */
535 #define core_hdr(bfd) (((struct suncordata *) (bfd->tdata))->hdr)
536 #define core_datasec(bfd) (((struct suncordata *) ((bfd)->tdata))->data_section)
537 #define core_stacksec(bfd) (((struct suncordata*)((bfd)->tdata))->stack_section)
538 #define core_regsec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg_section)
539 #define core_reg2sec(bfd) (((struct suncordata *) ((bfd)->tdata))->reg2_section)
540
541 /* These are stored in the bfd's tdata */
542 struct suncordata {
543   struct core *hdr;             /* core file header */
544   asection *data_section;
545   asection *stack_section;
546   asection *reg_section;
547   asection *reg2_section;
548 };
549
550 bfd_target *
551 sunos4_core_file_p (abfd)
552      bfd *abfd;
553 {
554   unsigned char longbuf[4];     /* Raw bytes of various header fields */
555   int core_size;
556   int core_mag;
557   struct core *core;
558   char *rawptr;
559
560   bfd_error = system_call_error;
561
562   if (bfd_read ((PTR)longbuf, 1, sizeof (longbuf), abfd) !=
563          sizeof (longbuf))
564     return 0;
565   core_mag = bfd_h_getlong (abfd, longbuf);
566
567   if (core_mag != CORE_MAGIC) return 0;
568
569   /* SunOS core headers can vary in length; second word is size; */
570   if (bfd_read ((PTR)longbuf, 1, sizeof (longbuf), abfd) !=
571          sizeof (longbuf))
572     return 0;
573   core_size = bfd_h_getlong (abfd, longbuf);
574   /* Sanity check */
575   if (core_size > 20000)
576     return 0;
577
578   if (bfd_seek (abfd, 0L, false) < 0) return 0;
579
580   rawptr = bfd_zalloc (abfd, core_size + sizeof (struct suncordata));
581   if (rawptr == NULL) {
582     bfd_error = no_memory;
583     return 0;
584   }
585
586   core = (struct core *) (rawptr + sizeof (struct suncordata));
587
588   if ((bfd_read ((PTR) core, 1, core_size, abfd)) != core_size) {
589     bfd_error = system_call_error;
590     bfd_release (abfd, rawptr);
591     return 0;
592   }
593
594   swapcore (abfd, core);
595   set_tdata (abfd, ((struct suncordata *) rawptr));
596   core_hdr (abfd) = core;
597
598   /* create the sections.  This is raunchy, but bfd_close wants to reclaim
599      them */
600   core_stacksec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
601   if (core_stacksec (abfd) == NULL) {
602 loser:
603     bfd_error = no_memory;
604     bfd_release (abfd, rawptr);
605     return 0;
606   }
607   core_datasec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
608   if (core_datasec (abfd) == NULL) {
609 loser1:
610     bfd_release (abfd, core_stacksec (abfd));
611     goto loser;
612   }
613   core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
614   if (core_regsec (abfd) == NULL) {
615 loser2:
616     bfd_release (abfd, core_datasec (abfd));
617     goto loser1;
618   }
619   core_reg2sec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
620   if (core_reg2sec (abfd) == NULL) {
621     bfd_release (abfd, core_regsec (abfd));
622     goto loser2;
623   }
624
625   core_stacksec (abfd)->name = ".stack";
626   core_datasec (abfd)->name = ".data";
627   core_regsec (abfd)->name = ".reg";
628   core_reg2sec (abfd)->name = ".reg2";
629
630   core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
631   core_datasec (abfd)->flags = SEC_ALLOC + SEC_LOAD;
632   core_regsec (abfd)->flags = SEC_ALLOC;
633   core_reg2sec (abfd)->flags = SEC_ALLOC;
634
635   core_stacksec (abfd)->size = core->c_ssize;
636   core_datasec (abfd)->size = core->c_dsize;
637   core_regsec (abfd)->size = (sizeof core->c_regs);
638   /* Float regs take up end of struct, except c_ucode.  */
639   core_reg2sec (abfd)->size = core_size - (sizeof core->c_ucode) -
640                               (file_ptr)(((struct core *)0)->fp_stuff);
641
642   core_stacksec (abfd)->vma = (USRSTACK - core->c_ssize);
643   core_datasec (abfd)->vma = N_DATADDR(core->c_aouthdr);
644   core_regsec (abfd)->vma = -1;
645   core_reg2sec (abfd)->vma = -1;
646
647   core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
648   core_datasec (abfd)->filepos = core->c_len;
649                         /* In file header: */
650   core_regsec (abfd)->filepos = (file_ptr)(&((struct core *)0)->c_regs);
651   core_reg2sec (abfd)->filepos = (file_ptr)(((struct core *)0)->fp_stuff);
652
653   /* Align to word at least */
654   core_stacksec (abfd)->alignment_power = 2;
655   core_datasec (abfd)->alignment_power = 2;
656   core_regsec (abfd)->alignment_power = 2;
657   core_reg2sec (abfd)->alignment_power = 2;
658
659   abfd->sections = core_stacksec (abfd);
660   core_stacksec (abfd)->next = core_datasec (abfd);
661   core_datasec (abfd)->next = core_regsec (abfd);
662   core_regsec (abfd)->next = core_reg2sec (abfd);
663
664   abfd->section_count = 4;
665
666   return abfd->xvec;
667 }
668
669 char *
670 sunos4_core_file_failing_command (abfd)
671      bfd *abfd;
672 {
673   return core_hdr (abfd)->c_cmdname;
674 }
675
676 int
677 sunos4_core_file_failing_signal (abfd)
678      bfd *abfd;
679 {
680   return core_hdr (abfd)->c_signo;
681 }
682
683 boolean
684 sunos4_core_file_matches_executable_p  (core_bfd, exec_bfd)
685      bfd *core_bfd, *exec_bfd;
686 {
687   if (core_bfd->xvec != exec_bfd->xvec) {
688     bfd_error = system_call_error;
689     return false;
690   }
691
692   return (bcmp ((char *)&core_hdr (core_bfd), (char*) &exec_hdr (exec_bfd),
693                 sizeof (struct exec)) == 0) ? true : false;
694 }
695
696 /* byte-swap core structure */
697 /* FIXME, this needs more work to swap IN a core struct from raw bytes */
698 static void
699 swapcore (abfd, core)
700      bfd *abfd;
701      struct core *core;
702 {
703   unsigned char exec_bytes[EXEC_BYTES_SIZE];
704
705   core->c_magic = bfd_h_getlong (abfd, (unsigned char *)&core->c_magic);
706   core->c_len   = bfd_h_getlong (abfd, (unsigned char *)&core->c_len  );
707   /* Leave integer registers in target byte order.  */
708   bcopy ((char *)&(core->c_aouthdr), (char *)exec_bytes, EXEC_BYTES_SIZE);
709   bfd_aout_swap_exec_header_in (abfd, exec_bytes, &core->c_aouthdr);
710   core->c_signo = bfd_h_getlong (abfd, (unsigned char *)&core->c_signo);
711   core->c_tsize = bfd_h_getlong (abfd, (unsigned char *)&core->c_tsize);
712   core->c_dsize = bfd_h_getlong (abfd, (unsigned char *)&core->c_dsize);
713   core->c_ssize = bfd_h_getlong (abfd, (unsigned char *)&core->c_ssize);
714   /* Leave FP registers in target byte order.  */
715   /* Leave "c_ucode" unswapped for now, since we can't find it easily.  */
716 }
717 \f
718 /** exec and core file sections */
719
720 boolean
721 sunos4_new_section_hook (abfd, newsect)
722      bfd *abfd;
723      asection *newsect;
724 {
725   /* align to double at least */
726   newsect->alignment_power = 3;
727
728   if (bfd_get_format (abfd) == bfd_object) {
729     if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
730       obj_textsec(abfd)= newsect;
731       return true;
732     }
733
734     if (obj_datasec(abfd) == NULL && !strcmp(newsect->name, ".data")) {
735       obj_datasec(abfd) = newsect;
736       return true;
737     }
738
739     if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
740       obj_bsssec(abfd) = newsect;
741       return true;
742     }
743   }
744
745   /* We allow more than three sections internally */
746   return true;
747 }
748
749 boolean
750 sunos4_set_section_contents (abfd, section, location, offset, count)
751      bfd *abfd;
752      sec_ptr section;
753      unsigned char *location;
754      file_ptr offset;
755       int count;
756 {
757   if (abfd->output_has_begun == false)
758       {                         /* set by bfd.c handler */
759         if ((obj_textsec (abfd) == NULL) || (obj_datasec (abfd) == NULL)) 
760             {
761               bfd_error = invalid_operation;
762               return false;
763             }
764
765           obj_textsec (abfd)->filepos = sizeof(struct exec);
766           obj_datasec(abfd)->filepos = obj_textsec (abfd)->filepos 
767                                      + obj_textsec (abfd)->size;
768       }
769   /* regardless, once we know what we're doing, we might as well get going */
770   if (section != obj_bsssec(abfd)) {
771     bfd_seek (abfd, section->filepos + offset, SEEK_SET);
772
773     if (count) {
774       return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
775         true : false;
776     }
777     return false;
778   }
779   return true;
780 }
781
782 boolean
783 sunos4_get_section_contents (abfd, section, location, offset, count)
784      bfd *abfd;
785      sec_ptr section;
786      PTR location;
787      file_ptr offset;
788      int count;
789 {
790   if (count) {
791     if (offset >= section->size) return false;
792
793     bfd_seek (abfd, section->filepos + offset, SEEK_SET);
794
795     return (bfd_read (location, 1, count, abfd) == count) ? true:false;
796   }
797   else return true;
798 }
799
800 \f
801 /* Classify stabs symbols */
802
803
804 #define sym_in_text_section(sym) \
805      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
806
807 #define sym_in_data_section(sym) \
808      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
809
810 #define sym_in_bss_section(sym) \
811      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
812
813 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
814    zero in the "value" field.  Nonzeroes there are fortrancommon
815    symbols.  */
816 #define sym_is_undefined(sym) \
817         ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
818
819 /* Symbol is a global definition if N_EXT is on and if it has
820    a nonzero type field.  */
821 #define sym_is_global_defn(sym) \
822         (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
823
824 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
825    are on.  */
826 #define sym_is_debugger_info(sym) \
827         ((sym)->n_type & ~(N_EXT | N_TYPE))
828
829 #define sym_is_fortrancommon(sym)       \
830         (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
831
832 /* Symbol is absolute if it has N_ABS set */
833 #define sym_is_absolute(sym) \
834                (((sym)->n_type  & N_TYPE)== N_ABS)
835
836
837 #define sym_is_indirect(sym) \
838                (((sym)->n_type  & N_ABS)== N_ABS)
839
840 /* Only in their own functions for ease of debugging; when sym flags have
841    stabilised these should be inlined into their (single) caller */
842
843 static void
844 translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
845      struct nlist *sym_pointer;
846      aout_symbol_type *cache_ptr;
847      bfd *abfd;
848 {
849   switch (cache_ptr->type & N_TYPE) {
850   case N_SETA:
851   case N_SETT:
852   case N_SETD:
853   case N_SETB:
854     {
855       asection *section = bfd_make_section(abfd,
856                                            cache_ptr->symbol.name);
857       arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain));
858
859       switch ( (cache_ptr->type  & N_TYPE) ) {
860       case N_SETA:
861         reloc->relent.section =  (asection *)NULL;
862         cache_ptr->symbol.section = (asection *)NULL;
863         break;
864       case N_SETT:
865         reloc->relent.section = (asection *)obj_textsec(abfd);
866         cache_ptr->symbol.value -= reloc->relent.section->vma;
867         break;
868       case N_SETD:
869         reloc->relent.section = (asection *)obj_datasec(abfd);
870         cache_ptr->symbol.value -= reloc->relent.section->vma;
871         break;
872       case N_SETB:
873         reloc->relent.section = (asection *)obj_bsssec(abfd);
874         cache_ptr->symbol.value -= reloc->relent.section->vma;
875         break;
876       }
877       cache_ptr->symbol.section = reloc->relent.section;
878       reloc->relent.addend = cache_ptr->symbol.value ;
879
880       /* We modify the symbol to belong to a section depending upon the
881          name of the symbol - probably __CTOR__ or __DTOR__ but we don't
882          really care, and add to the size of the section to contain a
883          pointer to the symbol. Build a reloc entry to relocate to this
884          symbol attached to this section.  */
885
886       section->flags = SEC_CONSTRUCTOR;
887       section->reloc_count++;
888       section->alignment_power = 2;
889       reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
890       reloc->next = section->constructor_chain;
891       section->constructor_chain = reloc;
892       reloc->relent.address = section->size;
893       section->size += sizeof(int *);
894
895       reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
896       cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
897       }
898     break;
899   default:
900
901     if (sym_is_debugger_info (sym_pointer)) {
902       cache_ptr->symbol.flags = BSF_DEBUGGING ;
903       /* Work out the section correct for this symbol */
904       switch (sym_pointer->n_type & N_TYPE) 
905         {
906         case N_TEXT:
907         case N_FN:
908           cache_ptr->symbol.section = obj_textsec (abfd);
909           cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
910           break;
911         case N_DATA:
912           cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
913           cache_ptr->symbol.section = obj_datasec (abfd);
914           break;
915         case N_BSS :
916           cache_ptr->symbol.section = obj_bsssec (abfd);
917           cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
918           break;
919         case N_ABS:
920         default:
921           cache_ptr->symbol.section = 0;
922           break;
923         }
924     }
925     else {
926       if (sym_is_fortrancommon (sym_pointer))
927         {
928           cache_ptr->symbol.flags = BSF_FORT_COMM;
929           cache_ptr->symbol.section = (asection *)NULL;
930         }
931       else {
932         if (sym_is_undefined (sym_pointer)) {
933           cache_ptr->symbol.flags = BSF_UNDEFINED;
934         }
935         else if (sym_is_global_defn (sym_pointer)) {
936           cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
937         }
938
939         else if (sym_is_absolute (sym_pointer)) {
940           cache_ptr->symbol.flags = BSF_ABSOLUTE;
941         }
942         else {
943           cache_ptr->symbol.flags = BSF_LOCAL;
944         }
945
946         /* In a.out, the value of a symbol is always relative to the 
947          * start of the file, if this is a data symbol we'll subtract
948          * the size of the text section to get the section relative
949          * value. If this is a bss symbol (which would be strange)
950          * we'll subtract the size of the previous two sections
951          * to find the section relative address.
952          */
953
954         if (sym_in_text_section (sym_pointer))   {
955           cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
956           cache_ptr->symbol.section = obj_textsec (abfd);
957         }
958         else if (sym_in_data_section (sym_pointer)){
959           cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
960           cache_ptr->symbol.section = obj_datasec (abfd);
961         }
962         else if (sym_in_bss_section(sym_pointer)) {
963           cache_ptr->symbol.section = obj_bsssec (abfd);
964           cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
965         }
966         else {
967           cache_ptr->symbol.section = (asection *)NULL;
968           cache_ptr->symbol.flags |= BSF_ABSOLUTE;
969         }
970       }
971     }
972   }
973 }
974
975 void
976 translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
977      struct nlist *sym_pointer;
978      PTR cache_ptr_g;
979      bfd *abfd;
980 {
981   asymbol *cache_ptr = (asymbol *)cache_ptr_g;
982
983   /* FIXME check for writing bss */
984   if (bfd_get_section(cache_ptr)) {
985     if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
986       sym_pointer->n_type |= N_BSS;
987     }
988     else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
989       sym_pointer->n_type |= N_DATA;
990     }
991     else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
992       sym_pointer->n_type |= N_TEXT;
993     }
994     else {
995       bfd_error_vector.nonrepresentable_section(abfd,
996                                  bfd_get_output_section(cache_ptr)->name);
997     }
998     /* Turn the symbol from section relative to absolute again */
999     sym_pointer->n_value +=
1000       cache_ptr->section->output_section->vma 
1001         + cache_ptr->section->output_offset ;
1002   }
1003   else {
1004     sym_pointer->n_type |= N_ABS;
1005   }
1006
1007   if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
1008     sym_pointer->n_type = (N_UNDF | N_EXT);
1009     return;
1010   }
1011
1012   if (cache_ptr->flags & BSF_ABSOLUTE) {
1013     sym_pointer->n_type |= N_ABS;
1014   }
1015
1016   if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
1017     sym_pointer->n_type |= N_EXT;
1018   }
1019   if (cache_ptr->flags & BSF_DEBUGGING) {
1020     sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
1021   }
1022 }
1023 \f
1024 /* Native-level interface to symbols. */
1025
1026 /* We read the symbols into a buffer, which is discarded when this
1027    function exits.  We read the strings into a buffer large enough to
1028    hold them all plus all the cached symbol entries. */
1029
1030 asymbol *
1031 sunos4_make_empty_symbol (abfd)
1032 bfd *abfd;
1033 {
1034   aout_symbol_type  *new =
1035     (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
1036   new->symbol.the_bfd = abfd;
1037
1038   return &new->symbol;
1039 }
1040
1041 boolean
1042 DEFUN(sunos4_slurp_symbol_table, (abfd),
1043       bfd *abfd)
1044 {
1045   size_t symbol_size;
1046   size_t string_size;
1047   unsigned char string_chars[LONG_SIZE];
1048   struct nlist *syms;
1049   char *strings;
1050   aout_symbol_type *cached;
1051
1052   /* If there's no work to be done, don't do any */
1053   if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
1054   symbol_size = exec_hdr(abfd)->a_syms;
1055   if (symbol_size == 0) {
1056     bfd_error = no_symbols;
1057     return false;
1058   }
1059
1060   bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1061   if (bfd_read ((PTR)string_chars, LONG_SIZE, 1, abfd) != LONG_SIZE)
1062     return false;
1063   string_size = bfd_h_getlong (abfd, string_chars);
1064
1065   strings = bfd_alloc(abfd, string_size + 1);
1066   cached = (aout_symbol_type *)
1067            bfd_zalloc(abfd, bfd_get_symcount (abfd) * sizeof(aout_symbol_type));
1068   /* Alloc this last, so we can free it if obstack is in use.  */
1069   syms = (struct nlist *) bfd_alloc(abfd, symbol_size);
1070
1071   bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1072   if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1073   bailout:
1074     if (syms)   bfd_release (abfd, syms);
1075     if (cached) bfd_release (abfd, cached);
1076     if (strings)bfd_release (abfd, strings);
1077     return false;
1078   }
1079
1080   bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1081   if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) {
1082     goto bailout;
1083   }
1084
1085   /* OK, now walk the new symtable, cacheing symbol properties */
1086     {
1087       register struct nlist *sym_pointer;
1088       register struct nlist *sym_end = syms + bfd_get_symcount (abfd);
1089       register aout_symbol_type *cache_ptr = cached;
1090
1091       /* run through the table and byte swap if needed */
1092       for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
1093         sym_pointer->n_un.n_strx =
1094           bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
1095         sym_pointer->n_desc =
1096           bfd_h_get_x (abfd, &sym_pointer->n_desc);
1097         sym_pointer->n_value =
1098           bfd_h_get_x (abfd, &sym_pointer->n_value);
1099         sym_pointer->n_other = (char)
1100           bfd_h_get_x(abfd, &sym_pointer->n_other);
1101         sym_pointer->n_type = (char)
1102           bfd_h_get_x(abfd, &sym_pointer->n_type);
1103       }
1104
1105       /* Run through table and copy values */
1106       for (sym_pointer = syms, cache_ptr = cached;
1107            sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
1108           {
1109             cache_ptr->symbol.the_bfd = abfd;
1110             if (sym_pointer->n_un.n_strx)
1111               cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
1112             else
1113               cache_ptr->symbol.name = (char *)NULL;
1114             cache_ptr->symbol.value = sym_pointer->n_value;
1115             cache_ptr->desc = sym_pointer->n_desc;
1116             cache_ptr->other = sym_pointer->n_other;
1117             cache_ptr->type = sym_pointer->n_type;
1118             cache_ptr->symbol.udata = 0;
1119             translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
1120
1121           }
1122     }
1123
1124   obj_aout_symbols (abfd) =  cached;
1125   bfd_release (abfd, (PTR)syms);
1126
1127   return true;
1128 }
1129
1130
1131 void
1132 DEFUN(sunos4_write_syms,(abfd),
1133      bfd *abfd)
1134 {
1135   unsigned int count ;
1136   asymbol **generic = bfd_get_outsymbols (abfd);
1137
1138   unsigned int stindex = sizeof(stindex); /* initial string length */
1139
1140   for (count = 0; count < bfd_get_symcount (abfd); count++) {
1141     asymbol *g = generic[count];
1142     struct nlist nsp;
1143
1144     if (g->name) {
1145       unsigned int length = strlen(g->name) +1;
1146       bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
1147       stindex += length;
1148     }
1149     else {
1150       bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
1151     }
1152
1153     if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
1154       {
1155         nsp.n_desc = aout_symbol( g)->desc;
1156         nsp.n_other = aout_symbol(g)->other;
1157         nsp.n_type = aout_symbol(g)->type;
1158       }
1159     else
1160       {
1161         nsp.n_desc = 0;
1162         nsp.n_other = 0;
1163         nsp.n_type = 0;
1164       }
1165
1166
1167     nsp.n_value = g->value;
1168     translate_to_native_sym_flags (&nsp, (PTR)g, abfd);
1169
1170
1171     bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
1172     bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
1173     bfd_write((PTR)&nsp,1, sizeof(nsp), abfd);
1174   }
1175
1176
1177   /* Now output the strings.  Be sure to put string length into correct
1178    * byte ordering before writing it.
1179    */
1180   bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
1181
1182   bfd_write((PTR)&stindex, 1, sizeof(stindex), abfd);
1183   
1184   generic = bfd_get_outsymbols(abfd);
1185   for (count = 0; count < bfd_get_symcount(abfd); count++) 
1186     {
1187       asymbol *g = *(generic++);
1188
1189       if (g->name)
1190         {
1191           size_t length = strlen(g->name)+1;
1192           bfd_write((PTR)g->name, 1, length, abfd);
1193         }
1194       if ((g->flags & BSF_FAKE)==0) {
1195         g->name = itos(count);  /* smash the generic symbol */
1196       }
1197     }
1198 }
1199
1200
1201 void
1202 DEFUN(sunos4_reclaim_symbol_table,(abfd),
1203      bfd *abfd)
1204 {
1205
1206 }
1207 \f
1208 unsigned int
1209 sunos4_get_symtab_upper_bound (abfd)
1210      bfd *abfd;
1211 {
1212   if (!sunos4_slurp_symbol_table (abfd)) return 0;
1213
1214   return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
1215 }
1216
1217 unsigned int
1218 sunos4_get_symtab (abfd, location)
1219      bfd *abfd;
1220      asymbol **location;
1221 {
1222   unsigned int counter = 0;
1223   aout_symbol_type *symbase;
1224
1225   if (!sunos4_slurp_symbol_table (abfd)) return 0;
1226
1227   for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
1228     *(location++) = (asymbol *)( symbase++);
1229   *location++ =0;
1230   return bfd_get_symcount(abfd);
1231 }
1232
1233 \f
1234 /* Standard reloc stuff */
1235 /* Output standard relocation information to a file in target byte order. */
1236
1237 void
1238 swap_std_reloc_out (abfd, g, natptr)
1239      bfd *abfd;
1240      arelent *g;                /* Generic relocation struct */
1241      struct reloc_std_bytes *natptr;
1242 {
1243   int r_index;
1244   int r_extern;
1245   unsigned int r_length;
1246   int r_pcrel;
1247   int r_baserel, r_jmptable, r_relative;
1248   unsigned int r_addend;
1249
1250   bfd_h_putlong (abfd, g->address, natptr->r_address);
1251
1252   r_length = g->howto->size ; /* Size as a power of two */
1253   r_pcrel  = (int) g->howto->pc_relative;       /* Relative to PC? */
1254   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
1255   r_baserel = 0;
1256   r_jmptable = 0;
1257   r_relative = 0;
1258
1259   r_addend = g->addend; /* Start here, see how it goes */
1260
1261   /* name was clobbered by sunos4_write_syms to be symbol index */
1262
1263   if (g->sym_ptr_ptr != NULL) 
1264     {
1265       if ((*(g->sym_ptr_ptr))->section) {
1266         /* put the section offset into the addend for output */
1267         r_addend += (*(g->sym_ptr_ptr))->section->vma;
1268       }
1269
1270       r_index = stoi((*(g->sym_ptr_ptr))->name);
1271       r_extern = 1;
1272     }
1273   else {
1274     r_extern = 0;
1275     if (g->section == NULL) {
1276       /* It is possible to have a reloc with nothing, we generate an
1277          abs + 0 */
1278       r_addend = 0;
1279       r_index = N_ABS | N_EXT;
1280     }
1281     else  if(g->section->output_section == obj_textsec(abfd)) {
1282       r_index = N_TEXT | N_EXT;
1283       r_addend += g->section->output_section->vma;
1284     }
1285     else if (g->section->output_section == obj_datasec(abfd)) {
1286       r_index = N_DATA | N_EXT;
1287       r_addend += g->section->output_section->vma;
1288     }
1289     else if (g->section->output_section == obj_bsssec(abfd)) {
1290       r_index = N_BSS | N_EXT ;
1291       r_addend += g->section->output_section->vma;
1292     }
1293     else {
1294       BFD_ASSERT(0);
1295     }
1296   }
1297
1298   /* now the fun stuff */
1299   if (abfd->xvec->header_byteorder_big_p != false) {
1300     natptr->r_index[0] = r_index >> 16;
1301     natptr->r_index[1] = r_index >> 8;
1302     natptr->r_index[2] = r_index;
1303     natptr->r_bits[0] =
1304       (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
1305         | (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
1306           | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
1307             | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
1308               | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
1309                 | (r_length <<  RELOC_STD_BITS_LENGTH_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_bits[0] =
1315       (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
1316         | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
1317           | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
1318             | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1319               | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1320                 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
1321   }
1322 }
1323
1324
1325 /* Extended stuff */
1326 /* Output extended relocation information to a file in target byte order. */
1327
1328 void
1329 swap_ext_reloc_out (abfd, g, natptr)
1330      bfd *abfd;
1331      arelent *g;                /* Generic relocation struct */
1332      register struct reloc_ext_bytes *natptr;
1333 {
1334   int r_index;
1335   int r_extern;
1336   unsigned int r_type;
1337   unsigned int r_addend;
1338
1339   bfd_h_putlong (abfd, g->address, natptr->r_address);
1340
1341   /* Find a type in the output format which matches the input howto - 
1342      at the moment we assume input format == output format FIXME!! */
1343   r_type = (enum reloc_type) g->howto->type;
1344
1345   r_addend = g->addend; /* Start here, see how it goes */
1346
1347   /* name was clobbered by sunos4_write_syms to be symbol index*/
1348
1349   if (g->sym_ptr_ptr != NULL) 
1350     {
1351       if ((*(g->sym_ptr_ptr))->section) {
1352         /* put the section offset into the addend for output */
1353         r_addend += (*(g->sym_ptr_ptr))->section->vma;
1354       }
1355
1356       r_index = stoi((*(g->sym_ptr_ptr))->name);
1357       r_extern = 1;
1358     }
1359   else {
1360     r_extern = 0;
1361     if (g->section == NULL) {
1362       BFD_ASSERT(0);
1363       r_index = N_ABS | N_EXT;
1364     }
1365     else  if(g->section->output_section == obj_textsec(abfd)) {
1366       r_index = N_TEXT | N_EXT;
1367       r_addend += g->section->output_section->vma;
1368     }
1369     else if (g->section->output_section == obj_datasec(abfd)) {
1370       r_index = N_DATA | N_EXT;
1371       r_addend += g->section->output_section->vma;
1372     }
1373     else if (g->section->output_section == obj_bsssec(abfd)) {
1374       r_index = N_BSS | N_EXT ;
1375       r_addend += g->section->output_section->vma;
1376     }
1377     else {
1378       BFD_ASSERT(0);
1379     }
1380   }
1381
1382   /* now the fun stuff */
1383   if (abfd->xvec->header_byteorder_big_p != false) {
1384     natptr->r_index[0] = r_index >> 16;
1385     natptr->r_index[1] = r_index >> 8;
1386     natptr->r_index[2] = r_index;
1387     natptr->r_bits[0] =
1388       (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1389         || (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1390   } else {
1391     natptr->r_index[2] = r_index >> 16;
1392     natptr->r_index[1] = r_index >> 8;
1393     natptr->r_index[0] = r_index;
1394     natptr->r_bits[0] =
1395       (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1396         || (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1397   }
1398
1399   bfd_h_putlong (abfd, r_addend, natptr->r_addend);
1400 }
1401
1402 #define MOVE_ADDRESS(ad)                                                \
1403   if (r_extern) {                                                       \
1404     cache_ptr->sym_ptr_ptr = symbols + r_index;                         \
1405     cache_ptr->section = (asection *)NULL;                              \
1406       cache_ptr->addend = ad;                                           \
1407   } else {                                                              \
1408     cache_ptr->sym_ptr_ptr = (asymbol **)NULL;                          \
1409     switch (r_index) {                                                  \
1410     case N_TEXT:                                                        \
1411     case N_TEXT | N_EXT:                                                \
1412       cache_ptr->section = obj_textsec(abfd);                           \
1413       cache_ptr->addend = ad  - su->textsec->vma;                       \
1414       break;                                                            \
1415     case N_DATA:                                                        \
1416     case N_DATA | N_EXT:                                                \
1417       cache_ptr->section = obj_datasec(abfd);                           \
1418       cache_ptr->addend = ad - su->datasec->vma;                        \
1419       break;                                                            \
1420     case N_BSS:                                                         \
1421     case N_BSS | N_EXT:                                                 \
1422       cache_ptr->section = obj_bsssec(abfd);                            \
1423       cache_ptr->addend = ad - su->bsssec->vma;                         \
1424       break;                                                            \
1425     case N_ABS:                                                         \
1426     case N_ABS | N_EXT:                                                 \
1427       cache_ptr->section = NULL;        /* No section */                \
1428       cache_ptr->addend = ad;           /* FIXME, is this right? */     \
1429       BFD_ASSERT(1);                                                    \
1430       break;                                                            \
1431     default:                                                            \
1432       cache_ptr->section = NULL;        /* No section */                \
1433       cache_ptr->addend = ad;           /* FIXME, is this right? */     \
1434       BFD_ASSERT(1);                                                    \
1435       break;                                                            \
1436     }                                                                   \
1437   }                                                                     \
1438
1439 void
1440 swap_ext_reloc_in (abfd, bytes, cache_ptr, symbols)
1441      bfd *abfd;
1442      struct reloc_ext_bytes *bytes;
1443      arelent *cache_ptr;
1444      asymbol **symbols;
1445 {
1446   int r_index;
1447   int r_extern;
1448   unsigned int r_type;
1449   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1450
1451   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1452
1453   /* now the fun stuff */
1454   if (abfd->xvec->header_byteorder_big_p != false) {
1455     r_index =  (bytes->r_index[0] << 16)
1456              | (bytes->r_index[1] << 8)
1457              |  bytes->r_index[2];
1458     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_BIG));
1459     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_BIG)
1460                                       >> RELOC_EXT_BITS_TYPE_SH_BIG;
1461   } else {
1462     r_index =  (bytes->r_index[2] << 16)
1463              | (bytes->r_index[1] << 8)
1464              |  bytes->r_index[0];
1465     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1466     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1467                                       >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1468   }
1469
1470   cache_ptr->howto =  howto_table_ext + r_type;
1471   MOVE_ADDRESS(bfd_h_getlong(abfd,bytes->r_addend));
1472 }
1473
1474 void
1475 swap_std_reloc_in (abfd, bytes, cache_ptr, symbols)
1476      bfd *abfd;
1477      struct reloc_std_bytes *bytes;
1478      arelent *cache_ptr;
1479      asymbol **symbols;
1480 {
1481   int r_index;
1482   int r_extern;
1483   unsigned int r_length;
1484   int r_pcrel;
1485   int r_baserel, r_jmptable, r_relative;
1486   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1487
1488   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1489
1490   /* now the fun stuff */
1491   if (abfd->xvec->header_byteorder_big_p != false) {
1492     r_index =  (bytes->r_index[0] << 16)
1493       | (bytes->r_index[1] << 8)
1494         |  bytes->r_index[2];
1495     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_BIG));
1496     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_BIG));
1497     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_BIG));
1498     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1499     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_BIG));
1500     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_BIG) 
1501                         >> RELOC_STD_BITS_LENGTH_SH_BIG;
1502   } else {
1503     r_index =  (bytes->r_index[2] << 16)
1504       | (bytes->r_index[1] << 8)
1505         |  bytes->r_index[0];
1506     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1507     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_LITTLE));
1508     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1509     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1510     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1511     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_LITTLE) 
1512                         >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1513   }
1514
1515   cache_ptr->howto =  howto_table_std + r_length + 4 * r_pcrel;
1516   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
1517
1518   MOVE_ADDRESS(0);
1519 }
1520
1521 /* Reloc hackery */
1522
1523 boolean
1524 sunos4_slurp_reloc_table (abfd, asect, symbols)
1525      bfd *abfd;
1526      sec_ptr asect;
1527      asymbol **symbols;
1528 {
1529   unsigned int count;
1530   size_t reloc_size;
1531   PTR relocs;
1532   arelent *reloc_cache;
1533   size_t each_size;
1534
1535   if (asect->relocation) return true;
1536
1537   if (asect->flags & SEC_CONSTRUCTOR) return true;
1538
1539   if (asect == obj_datasec (abfd)) {
1540     reloc_size = exec_hdr(abfd)->a_drsize;
1541     goto doit;
1542   }
1543
1544   if (asect == obj_textsec (abfd)) {
1545     reloc_size = exec_hdr(abfd)->a_trsize;
1546     goto doit;
1547   }
1548
1549   bfd_error = invalid_operation;
1550   return false;
1551
1552  doit:
1553   bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1554   each_size = reloc_size_func(abfd);
1555
1556   count = reloc_size / each_size;
1557
1558
1559   reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
1560                                                        (arelent)));
1561   if (!reloc_cache) {
1562 nomem:
1563     bfd_error = no_memory;
1564     return false;
1565   }
1566
1567   relocs =  bfd_alloc (abfd, reloc_size);
1568   if (!relocs) {
1569     bfd_release (abfd, reloc_cache);
1570     goto nomem;
1571   }
1572
1573   if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
1574     bfd_release (abfd, relocs);
1575     bfd_release (abfd, reloc_cache);
1576     bfd_error = system_call_error;
1577     return false;
1578   }
1579
1580   if (each_size == RELOC_EXT_SIZE) {
1581     register struct reloc_ext_bytes *rptr = (struct reloc_ext_bytes *) relocs;
1582     unsigned int counter = 0;
1583     arelent *cache_ptr = reloc_cache;
1584
1585     for (; counter < count; counter++, rptr++, cache_ptr++) {
1586       swap_ext_reloc_in(abfd, rptr, cache_ptr, symbols);
1587     }
1588   } else {
1589     register struct reloc_std_bytes *rptr = (struct reloc_std_bytes *) relocs;
1590     unsigned int counter = 0;
1591     arelent *cache_ptr = reloc_cache;
1592
1593     for (; counter < count; counter++, rptr++, cache_ptr++) {
1594         swap_std_reloc_in(abfd, rptr, cache_ptr, symbols);
1595     }
1596
1597   }
1598
1599   bfd_release (abfd,relocs);
1600   asect->relocation = reloc_cache;
1601   asect->reloc_count = count;
1602   return true;
1603 }
1604
1605
1606
1607 /* Write out a relocation section into an object file.  */
1608
1609 static boolean
1610 sunos4_squirt_out_relocs (abfd, section)
1611      bfd *abfd;
1612      asection *section;
1613 {
1614   arelent **generic;
1615   unsigned char *native, *natptr;
1616   size_t each_size;
1617
1618   unsigned int count = section->reloc_count;
1619   size_t natsize;
1620
1621   if (count == 0) return true;
1622
1623   each_size = reloc_size_func(abfd);
1624   natsize = each_size * count;
1625   native = (unsigned char *) bfd_zalloc (abfd, natsize);
1626   if (!native) {
1627     bfd_error = no_memory;
1628     return false;
1629   }
1630
1631   generic = section->orelocation;
1632
1633   if (each_size == RELOC_EXT_SIZE) 
1634     {
1635       for (natptr = native;
1636            count != 0;
1637            --count, natptr += each_size, ++generic)
1638         swap_ext_reloc_out (abfd, *generic, (struct reloc_ext_bytes *)natptr);
1639     }
1640   else 
1641     {
1642       for (natptr = native;
1643            count != 0;
1644            --count, natptr += each_size, ++generic)
1645         swap_std_reloc_out(abfd, *generic, (struct reloc_std_bytes *)natptr);
1646     }
1647
1648   if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1649     bfd_release(abfd, native);
1650     return false;
1651   }
1652   bfd_release (abfd, native);
1653
1654   return true;
1655 }
1656
1657 /* This is stupid.  This function should be a boolean predicate */
1658 unsigned int
1659 sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
1660      bfd *abfd;
1661      sec_ptr section;
1662      arelent **relptr;
1663      asymbol **symbols;
1664 {
1665   arelent *tblptr = section->relocation;
1666   unsigned int count;
1667
1668   if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
1669     return 0;
1670
1671   if (section->flags & SEC_CONSTRUCTOR) {
1672     arelent_chain *chain = section->constructor_chain;
1673     for (count = 0; count < section->reloc_count; count ++) {
1674       *relptr ++ = &chain->relent;
1675       chain = chain->next;
1676     }
1677   }
1678   else {
1679     tblptr = section->relocation;
1680     if (!tblptr) return 0;
1681
1682     for (count = 0; count++ < section->reloc_count;) 
1683       {
1684         *relptr++ = tblptr++;
1685       }
1686   }
1687   *relptr = 0;
1688
1689   return section->reloc_count;
1690 }
1691
1692 unsigned int
1693 sunos4_get_reloc_upper_bound (abfd, asect)
1694      bfd *abfd;
1695      sec_ptr asect;
1696 {
1697   if (bfd_get_format (abfd) != bfd_object) {
1698     bfd_error = invalid_operation;
1699     return 0;
1700   }
1701   if (asect->flags & SEC_CONSTRUCTOR) {
1702     return (sizeof (arelent *) * (asect->reloc_count+1));
1703   }
1704
1705
1706   if (asect == obj_datasec (abfd))
1707     return (sizeof (arelent *) *
1708             ((exec_hdr(abfd)->a_drsize / reloc_size_func(abfd))
1709              +1));
1710
1711   if (asect == obj_textsec (abfd))
1712     return (sizeof (arelent *) *
1713             ((exec_hdr(abfd)->a_trsize / reloc_size_func(abfd))
1714              +1));
1715
1716   bfd_error = invalid_operation;
1717   return 0;
1718 }
1719
1720 void
1721 sunos4_reclaim_reloc (ignore_abfd, ignore)
1722      bfd *ignore_abfd;
1723      sec_ptr ignore;
1724 {
1725
1726 }
1727 \f
1728
1729 alent *
1730 sunos4_get_lineno(ignore_abfd, ignore_symbol)
1731 bfd *ignore_abfd;
1732 PTR ignore_symbol;
1733 {
1734 return (alent *)NULL;
1735 }
1736
1737 void 
1738 sunos4_print_symbol(ignore_abfd, file,  symbol, how)
1739 bfd *ignore_abfd;
1740 FILE *file;
1741 asymbol *symbol;
1742 bfd_print_symbol_enum_type how;
1743 {
1744   switch (how) {
1745   case bfd_print_symbol_name_enum:
1746     fprintf(file,"%s", symbol->name);
1747     break;
1748   case bfd_print_symbol_type_enum:
1749     fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1750             (unsigned)(aout_symbol(symbol)->other & 0xff),
1751             (unsigned)(aout_symbol(symbol)->type));
1752     break;
1753   case bfd_print_symbol_all_enum:
1754     {
1755    CONST char *section_name = symbol->section == (asection *)NULL ?
1756         "*abs" : symbol->section->name;
1757
1758       bfd_print_symbol_vandf((PTR)file,symbol);
1759
1760       fprintf(file," %-5s %04x %02x %02x %s",
1761               section_name,
1762               (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1763               (unsigned)(aout_symbol(symbol)->other & 0xff),
1764               (unsigned)(aout_symbol(symbol)->type  & 0xff),
1765               symbol->name);
1766     }
1767     break;
1768   }
1769 }
1770 /* Once we know all the stuff that could be consed, we know how to clean
1771    it up.  So why don't we? */
1772
1773 boolean
1774 sunos4_close_and_cleanup (abfd)
1775      bfd *abfd;
1776 {
1777   if (!bfd_read_p (abfd))
1778     switch (abfd->format) {
1779     case bfd_archive:
1780       if (!_bfd_write_archive_contents (abfd)) return false; break;
1781     case bfd_object:
1782       if (!sunos4_write_object_contents (abfd))  return false; break;
1783     default: bfd_error = invalid_operation; return false;
1784     }
1785
1786   return true;
1787 }
1788
1789 /* 
1790  provided a bfd, a section and an offset into the section, calculate
1791  and return the name of the source file and the line nearest to the
1792  wanted location.
1793 */
1794  
1795 boolean
1796 DEFUN(sunos4_find_nearest_line,(abfd,
1797                                 section,
1798                                 symbols,
1799                                 offset,
1800                                 filename_ptr,
1801                                 functionname_ptr,
1802                                 line_ptr),
1803       bfd *abfd AND
1804       asection *section AND
1805       asymbol **symbols AND
1806       bfd_vma offset AND
1807       CONST char **filename_ptr AND
1808       CONST char **functionname_ptr AND
1809       unsigned int *line_ptr)
1810 {
1811   /* Run down the file looking for the filename, function and linenumber */
1812   asymbol **p;
1813   static  char buffer[100];
1814   bfd_vma high_line_vma = ~0;
1815   bfd_vma low_func_vma = 0;
1816   asymbol *func = 0;
1817   *filename_ptr = abfd->filename;
1818   *functionname_ptr = 0;
1819   *line_ptr = 0;
1820   if (symbols != (asymbol **)NULL) {
1821     for (p = symbols; *p; p++) {
1822       aout_symbol_type  *q = (aout_symbol_type *)(*p);
1823       switch (q->type){
1824       case N_SO:
1825         *filename_ptr = q->symbol.name;
1826         if (obj_textsec(abfd) != section) {
1827           return true;
1828         }
1829         break;
1830       case N_SLINE:
1831
1832       case N_DSLINE:
1833       case N_BSLINE:
1834         /* We'll keep this if it resolves nearer than the one we have already */
1835         if (q->symbol.value >= offset &&
1836             q->symbol.value < high_line_vma) {
1837           *line_ptr = q->desc;
1838           high_line_vma = q->symbol.value;
1839         }
1840         break;
1841       case N_FUN:
1842         {
1843           /* We'll keep this if it is nearer than the one we have already */
1844           if (q->symbol.value >= low_func_vma &&
1845               q->symbol.value <= offset) {
1846             low_func_vma = q->symbol.value;
1847             func = (asymbol *)q;
1848           }
1849           if (*line_ptr && func) {
1850             CONST char *function = func->name;
1851             char *p;
1852             strncpy(buffer, function, sizeof(buffer)-1);
1853             buffer[sizeof(buffer)-1] = 0;
1854             /* Have to remove : stuff */
1855             p = strchr(buffer,':');
1856             if (p != NULL) {*p = NULL; }
1857             *functionname_ptr = buffer;
1858             return true;
1859
1860           }
1861         }
1862         break;
1863       }
1864     }
1865   }
1866   
1867   return true;
1868
1869 }
1870
1871 static int 
1872 DEFUN(sunos4_sizeof_headers,(ignore_abfd),
1873       bfd *ignore_abfd)
1874 {
1875   return 0;             /* FIXME, this is the wrong value! */
1876 }
1877
1878 #define sunos4_openr_next_archived_file bfd_generic_openr_next_archived_file
1879 #define sunos4_generic_stat_arch_elt bfd_generic_stat_arch_elt
1880 #define sunos4_slurp_armap bfd_slurp_bsd_armap
1881 #define sunos4_slurp_extended_name_table bfd_true
1882 #define sunos4_write_armap bsd_write_armap
1883 #define sunos4_truncate_arname bfd_bsd_truncate_arname
1884 bfd_target aout_big_vec =
1885 {
1886   "a.out-generic-big",          /* name */
1887   bfd_target_aout_flavour_enum,
1888   true,                         /* target byte order */
1889   true,                         /* target headers byte order */
1890   (HAS_RELOC | EXEC_P |         /* object flags */
1891    HAS_LINENO | HAS_DEBUG |
1892    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1893   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1894   ' ',                          /* ar_pad_char */
1895   16,                           /* ar_max_namelen */
1896   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
1897   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
1898
1899     {_bfd_dummy_target, sunos4_object_p,
1900        bfd_generic_archive_p, sunos4_core_file_p},
1901     {bfd_false, sunos4_mkobject,
1902        _bfd_generic_mkarchive, bfd_false},
1903
1904   JUMP_TABLE(sunos4)
1905   };
1906
1907
1908 bfd_target aout_little_vec =
1909 {
1910   "a.out-generic-little",               /* name */
1911   bfd_target_aout_flavour_enum,
1912   false,                        /* target byte order */
1913   false,                        /* target headers byte order */
1914   (HAS_RELOC | EXEC_P |         /* object flags */
1915    HAS_LINENO | HAS_DEBUG |
1916    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1917   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1918   ' ',                          /* ar_pad_char */
1919   16,                           /* ar_max_namelen */
1920   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
1921   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */
1922
1923
1924     {_bfd_dummy_target, sunos4_object_p,
1925        bfd_generic_archive_p, sunos4_core_file_p},
1926     {bfd_false, sunos4_mkobject,
1927        _bfd_generic_mkarchive, bfd_false},
1928
1929   JUMP_TABLE(sunos4)
1930   };