*** empty log message ***
[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       BFD_ASSERT(0);
1277       r_index = N_ABS | N_EXT;
1278     }
1279     else  if(g->section->output_section == obj_textsec(abfd)) {
1280       r_index = N_TEXT | N_EXT;
1281       r_addend += g->section->output_section->vma;
1282     }
1283     else if (g->section->output_section == obj_datasec(abfd)) {
1284       r_index = N_DATA | N_EXT;
1285       r_addend += g->section->output_section->vma;
1286     }
1287     else if (g->section->output_section == obj_bsssec(abfd)) {
1288       r_index = N_BSS | N_EXT ;
1289       r_addend += g->section->output_section->vma;
1290     }
1291     else {
1292       BFD_ASSERT(0);
1293     }
1294   }
1295
1296   /* now the fun stuff */
1297   if (abfd->xvec->header_byteorder_big_p != false) {
1298     natptr->r_index[0] = r_index >> 16;
1299     natptr->r_index[1] = r_index >> 8;
1300     natptr->r_index[2] = r_index;
1301     natptr->r_bits[0] =
1302       (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
1303         | (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
1304           | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
1305             | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
1306               | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
1307                 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG);
1308   } else {
1309     natptr->r_index[2] = r_index >> 16;
1310     natptr->r_index[1] = r_index >> 8;
1311     natptr->r_index[0] = r_index;
1312     natptr->r_bits[0] =
1313       (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
1314         | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
1315           | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
1316             | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1317               | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1318                 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
1319   }
1320 }
1321
1322
1323 /* Extended stuff */
1324 /* Output extended relocation information to a file in target byte order. */
1325
1326 void
1327 swap_ext_reloc_out (abfd, g, natptr)
1328      bfd *abfd;
1329      arelent *g;                /* Generic relocation struct */
1330      register struct reloc_ext_bytes *natptr;
1331 {
1332   int r_index;
1333   int r_extern;
1334   unsigned int r_type;
1335   unsigned int r_addend;
1336
1337   bfd_h_putlong (abfd, g->address, natptr->r_address);
1338
1339   /* Find a type in the output format which matches the input howto - 
1340      at the moment we assume input format == output format FIXME!! */
1341   r_type = (enum reloc_type) g->howto->type;
1342
1343   r_addend = g->addend; /* Start here, see how it goes */
1344
1345   /* name was clobbered by sunos4_write_syms to be symbol index*/
1346
1347   if (g->sym_ptr_ptr != NULL) 
1348     {
1349       if ((*(g->sym_ptr_ptr))->section) {
1350         /* put the section offset into the addend for output */
1351         r_addend += (*(g->sym_ptr_ptr))->section->vma;
1352       }
1353
1354       r_index = stoi((*(g->sym_ptr_ptr))->name);
1355       r_extern = 1;
1356     }
1357   else {
1358     r_extern = 0;
1359     if (g->section == NULL) {
1360       BFD_ASSERT(0);
1361       r_index = N_ABS | N_EXT;
1362     }
1363     else  if(g->section->output_section == obj_textsec(abfd)) {
1364       r_index = N_TEXT | N_EXT;
1365       r_addend += g->section->output_section->vma;
1366     }
1367     else if (g->section->output_section == obj_datasec(abfd)) {
1368       r_index = N_DATA | N_EXT;
1369       r_addend += g->section->output_section->vma;
1370     }
1371     else if (g->section->output_section == obj_bsssec(abfd)) {
1372       r_index = N_BSS | N_EXT ;
1373       r_addend += g->section->output_section->vma;
1374     }
1375     else {
1376       BFD_ASSERT(0);
1377     }
1378   }
1379
1380   /* now the fun stuff */
1381   if (abfd->xvec->header_byteorder_big_p != false) {
1382     natptr->r_index[0] = r_index >> 16;
1383     natptr->r_index[1] = r_index >> 8;
1384     natptr->r_index[2] = r_index;
1385     natptr->r_bits[0] =
1386       (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1387         || (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1388   } else {
1389     natptr->r_index[2] = r_index >> 16;
1390     natptr->r_index[1] = r_index >> 8;
1391     natptr->r_index[0] = r_index;
1392     natptr->r_bits[0] =
1393       (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1394         || (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1395   }
1396
1397   bfd_h_putlong (abfd, r_addend, natptr->r_addend);
1398 }
1399
1400 #define MOVE_ADDRESS(ad)                                                \
1401   if (r_extern) {                                                       \
1402     cache_ptr->sym_ptr_ptr = symbols + r_index;                         \
1403     cache_ptr->section = (asection *)NULL;                              \
1404       cache_ptr->addend = ad;                                           \
1405   } else {                                                              \
1406     cache_ptr->sym_ptr_ptr = (asymbol **)NULL;                          \
1407     switch (r_index) {                                                  \
1408     case N_TEXT:                                                        \
1409     case N_TEXT | N_EXT:                                                \
1410       cache_ptr->section = obj_textsec(abfd);                           \
1411       cache_ptr->addend = ad  - su->textsec->vma;                       \
1412       break;                                                            \
1413     case N_DATA:                                                        \
1414     case N_DATA | N_EXT:                                                \
1415       cache_ptr->section = obj_datasec(abfd);                           \
1416       cache_ptr->addend = ad - su->datasec->vma;                        \
1417       break;                                                            \
1418     case N_BSS:                                                         \
1419     case N_BSS | N_EXT:                                                 \
1420       cache_ptr->section = obj_bsssec(abfd);                            \
1421       cache_ptr->addend = ad - su->bsssec->vma;                         \
1422       break;                                                            \
1423     case N_ABS:                                                         \
1424     case N_ABS | N_EXT:                                                 \
1425       cache_ptr->section = NULL;        /* No section */                \
1426       cache_ptr->addend = ad;           /* FIXME, is this right? */     \
1427       BFD_ASSERT(1);                                                    \
1428       break;                                                            \
1429     default:                                                            \
1430       cache_ptr->section = NULL;        /* No section */                \
1431       cache_ptr->addend = ad;           /* FIXME, is this right? */     \
1432       BFD_ASSERT(1);                                                    \
1433       break;                                                            \
1434     }                                                                   \
1435   }                                                                     \
1436
1437 void
1438 swap_ext_reloc_in (abfd, bytes, cache_ptr, symbols)
1439      bfd *abfd;
1440      struct reloc_ext_bytes *bytes;
1441      arelent *cache_ptr;
1442      asymbol **symbols;
1443 {
1444   int r_index;
1445   int r_extern;
1446   unsigned int r_type;
1447   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1448
1449   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1450
1451   /* now the fun stuff */
1452   if (abfd->xvec->header_byteorder_big_p != false) {
1453     r_index =  (bytes->r_index[0] << 16)
1454              | (bytes->r_index[1] << 8)
1455              |  bytes->r_index[2];
1456     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_BIG));
1457     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_BIG)
1458                                       >> RELOC_EXT_BITS_TYPE_SH_BIG;
1459   } else {
1460     r_index =  (bytes->r_index[2] << 16)
1461              | (bytes->r_index[1] << 8)
1462              |  bytes->r_index[0];
1463     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1464     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1465                                       >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1466   }
1467
1468   cache_ptr->howto =  howto_table_ext + r_type;
1469   MOVE_ADDRESS(bfd_h_getlong(abfd,bytes->r_addend));
1470 }
1471
1472 void
1473 swap_std_reloc_in (abfd, bytes, cache_ptr, symbols)
1474      bfd *abfd;
1475      struct reloc_std_bytes *bytes;
1476      arelent *cache_ptr;
1477      asymbol **symbols;
1478 {
1479   int r_index;
1480   int r_extern;
1481   unsigned int r_length;
1482   int r_pcrel;
1483   int r_baserel, r_jmptable, r_relative;
1484   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1485
1486   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1487
1488   /* now the fun stuff */
1489   if (abfd->xvec->header_byteorder_big_p != false) {
1490     r_index =  (bytes->r_index[0] << 16)
1491       | (bytes->r_index[1] << 8)
1492         |  bytes->r_index[2];
1493     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_BIG));
1494     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_BIG));
1495     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_BIG));
1496     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1497     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_BIG));
1498     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_BIG) 
1499                         >> RELOC_STD_BITS_LENGTH_SH_BIG;
1500   } else {
1501     r_index =  (bytes->r_index[2] << 16)
1502       | (bytes->r_index[1] << 8)
1503         |  bytes->r_index[0];
1504     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1505     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_LITTLE));
1506     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1507     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1508     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1509     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_LITTLE) 
1510                         >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1511   }
1512
1513   cache_ptr->howto =  howto_table_std + r_length + 4 * r_pcrel;
1514   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
1515
1516   MOVE_ADDRESS(0);
1517 }
1518
1519 /* Reloc hackery */
1520
1521 boolean
1522 sunos4_slurp_reloc_table (abfd, asect, symbols)
1523      bfd *abfd;
1524      sec_ptr asect;
1525      asymbol **symbols;
1526 {
1527   unsigned int count;
1528   size_t reloc_size;
1529   PTR relocs;
1530   arelent *reloc_cache;
1531   size_t each_size;
1532
1533   if (asect->relocation) return true;
1534
1535   if (asect->flags & SEC_CONSTRUCTOR) return true;
1536
1537   if (asect == obj_datasec (abfd)) {
1538     reloc_size = exec_hdr(abfd)->a_drsize;
1539     goto doit;
1540   }
1541
1542   if (asect == obj_textsec (abfd)) {
1543     reloc_size = exec_hdr(abfd)->a_trsize;
1544     goto doit;
1545   }
1546
1547   bfd_error = invalid_operation;
1548   return false;
1549
1550  doit:
1551   bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1552   each_size = reloc_size_func(abfd);
1553
1554   count = reloc_size / each_size;
1555
1556
1557   reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
1558                                                        (arelent)));
1559   if (!reloc_cache) {
1560 nomem:
1561     bfd_error = no_memory;
1562     return false;
1563   }
1564
1565   relocs =  bfd_alloc (abfd, reloc_size);
1566   if (!relocs) {
1567     bfd_release (abfd, reloc_cache);
1568     goto nomem;
1569   }
1570
1571   if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
1572     bfd_release (abfd, relocs);
1573     bfd_release (abfd, reloc_cache);
1574     bfd_error = system_call_error;
1575     return false;
1576   }
1577
1578   if (each_size == RELOC_EXT_SIZE) {
1579     register struct reloc_ext_bytes *rptr = (struct reloc_ext_bytes *) relocs;
1580     unsigned int counter = 0;
1581     arelent *cache_ptr = reloc_cache;
1582
1583     for (; counter < count; counter++, rptr++, cache_ptr++) {
1584       swap_ext_reloc_in(abfd, rptr, cache_ptr, symbols);
1585     }
1586   } else {
1587     register struct reloc_std_bytes *rptr = (struct reloc_std_bytes *) relocs;
1588     unsigned int counter = 0;
1589     arelent *cache_ptr = reloc_cache;
1590
1591     for (; counter < count; counter++, rptr++, cache_ptr++) {
1592         swap_std_reloc_in(abfd, rptr, cache_ptr, symbols);
1593     }
1594
1595   }
1596
1597   bfd_release (abfd,relocs);
1598   asect->relocation = reloc_cache;
1599   asect->reloc_count = count;
1600   return true;
1601 }
1602
1603
1604
1605 /* Write out a relocation section into an object file.  */
1606
1607 static boolean
1608 sunos4_squirt_out_relocs (abfd, section)
1609      bfd *abfd;
1610      asection *section;
1611 {
1612   arelent **generic;
1613   unsigned char *native, *natptr;
1614   size_t each_size;
1615
1616   unsigned int count = section->reloc_count;
1617   size_t natsize;
1618
1619   if (count == 0) return true;
1620
1621   each_size = reloc_size_func(abfd);
1622   natsize = each_size * count;
1623   native = (unsigned char *) bfd_zalloc (abfd, natsize);
1624   if (!native) {
1625     bfd_error = no_memory;
1626     return false;
1627   }
1628
1629   generic = section->orelocation;
1630
1631   if (each_size == RELOC_EXT_SIZE) 
1632     {
1633       for (natptr = native;
1634            count != 0;
1635            --count, natptr += each_size, ++generic)
1636         swap_ext_reloc_out (abfd, *generic, (struct reloc_ext_bytes *)natptr);
1637     }
1638   else 
1639     {
1640       for (natptr = native;
1641            count != 0;
1642            --count, natptr += each_size, ++generic)
1643         swap_std_reloc_out(abfd, *generic, (struct reloc_std_bytes *)natptr);
1644     }
1645
1646   if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1647     bfd_release(abfd, native);
1648     return false;
1649   }
1650   bfd_release (abfd, native);
1651
1652   return true;
1653 }
1654
1655 /* This is stupid.  This function should be a boolean predicate */
1656 unsigned int
1657 sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
1658      bfd *abfd;
1659      sec_ptr section;
1660      arelent **relptr;
1661      asymbol **symbols;
1662 {
1663   arelent *tblptr = section->relocation;
1664   unsigned int count;
1665
1666   if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
1667     return 0;
1668
1669   if (section->flags & SEC_CONSTRUCTOR) {
1670     arelent_chain *chain = section->constructor_chain;
1671     for (count = 0; count < section->reloc_count; count ++) {
1672       *relptr ++ = &chain->relent;
1673       chain = chain->next;
1674     }
1675   }
1676   else {
1677     tblptr = section->relocation;
1678     if (!tblptr) return 0;
1679
1680     for (count = 0; count++ < section->reloc_count;) 
1681       {
1682         *relptr++ = tblptr++;
1683       }
1684   }
1685   *relptr = 0;
1686
1687   return section->reloc_count;
1688 }
1689
1690 unsigned int
1691 sunos4_get_reloc_upper_bound (abfd, asect)
1692      bfd *abfd;
1693      sec_ptr asect;
1694 {
1695   if (bfd_get_format (abfd) != bfd_object) {
1696     bfd_error = invalid_operation;
1697     return 0;
1698   }
1699   if (asect->flags & SEC_CONSTRUCTOR) {
1700     return (sizeof (arelent *) * (asect->reloc_count+1));
1701   }
1702
1703
1704   if (asect == obj_datasec (abfd))
1705     return (sizeof (arelent *) *
1706             ((exec_hdr(abfd)->a_drsize / reloc_size_func(abfd))
1707              +1));
1708
1709   if (asect == obj_textsec (abfd))
1710     return (sizeof (arelent *) *
1711             ((exec_hdr(abfd)->a_trsize / reloc_size_func(abfd))
1712              +1));
1713
1714   bfd_error = invalid_operation;
1715   return 0;
1716 }
1717
1718 void
1719 sunos4_reclaim_reloc (ignore_abfd, section)
1720      bfd *ignore_abfd;
1721      sec_ptr section;
1722 {
1723
1724 }
1725 \f
1726
1727 alent *
1728 sunos4_get_lineno(ignore_abfd, ignore_symbol)
1729 bfd *ignore_abfd;
1730 PTR ignore_symbol;
1731 {
1732 return (alent *)NULL;
1733 }
1734
1735 void 
1736 sunos4_print_symbol(ignore_abfd, file,  symbol, how)
1737 bfd *ignore_abfd;
1738 FILE *file;
1739 asymbol *symbol;
1740 bfd_print_symbol_enum_type how;
1741 {
1742   switch (how) {
1743   case bfd_print_symbol_name_enum:
1744     fprintf(file,"%s", symbol->name);
1745     break;
1746   case bfd_print_symbol_type_enum:
1747     fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1748             (unsigned)(aout_symbol(symbol)->other & 0xff),
1749             (unsigned)(aout_symbol(symbol)->type));
1750     break;
1751   case bfd_print_symbol_all_enum:
1752     {
1753    CONST char *section_name = symbol->section == (asection *)NULL ?
1754         "*abs" : symbol->section->name;
1755
1756       bfd_print_symbol_vandf((PTR)file,symbol);
1757
1758       fprintf(file," %-5s %04x %02x %02x %s",
1759               section_name,
1760               (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1761               (unsigned)(aout_symbol(symbol)->other & 0xff),
1762               (unsigned)(aout_symbol(symbol)->type  & 0xff),
1763               symbol->name);
1764     }
1765     break;
1766   }
1767 }
1768 /* Once we know all the stuff that could be consed, we know how to clean
1769    it up.  So why don't we? */
1770
1771 boolean
1772 sunos4_close_and_cleanup (abfd)
1773      bfd *abfd;
1774 {
1775   if (!bfd_read_p (abfd))
1776     switch (abfd->format) {
1777     case bfd_archive:
1778       if (!_bfd_write_archive_contents (abfd)) return false; break;
1779     case bfd_object:
1780       if (!sunos4_write_object_contents (abfd))  return false; break;
1781     default: bfd_error = invalid_operation; return false;
1782     }
1783
1784   return true;
1785 }
1786
1787 /* 
1788  provided a bfd, a section and an offset into the section, calculate
1789  and return the name of the source file and the line nearest to the
1790  wanted location.
1791 */
1792  
1793 boolean
1794 DEFUN(sunos4_find_nearest_line,(abfd,
1795                                 section,
1796                                 symbols,
1797                                 offset,
1798                                 filename_ptr,
1799                                 functionname_ptr,
1800                                 line_ptr),
1801       bfd *abfd AND
1802       asection *section AND
1803       asymbol **symbols AND
1804       bfd_vma offset AND
1805       CONST char **filename_ptr AND
1806       CONST char **functionname_ptr AND
1807       unsigned int *line_ptr)
1808 {
1809   /* Run down the file looking for the filename, function and linenumber */
1810   asymbol **p;
1811   static  char buffer[100];
1812   bfd_vma high_line_vma = ~0;
1813   bfd_vma low_func_vma = 0;
1814   asymbol *func = 0;
1815   *filename_ptr = abfd->filename;
1816   *functionname_ptr = 0;
1817   *line_ptr = 0;
1818   if (symbols != (asymbol **)NULL) {
1819     for (p = symbols; *p; p++) {
1820       aout_symbol_type  *q = (aout_symbol_type *)(*p);
1821       switch (q->type){
1822       case N_SO:
1823         *filename_ptr = q->symbol.name;
1824         if (obj_textsec(abfd) != section) {
1825           return true;
1826         }
1827         break;
1828       case N_SLINE:
1829
1830       case N_DSLINE:
1831       case N_BSLINE:
1832         /* We'll keep this if it resolves nearer than the one we have already */
1833         if (q->symbol.value >= offset &&
1834             q->symbol.value < high_line_vma) {
1835           *line_ptr = q->desc;
1836           high_line_vma = q->symbol.value;
1837         }
1838         break;
1839       case N_FUN:
1840         {
1841           /* We'll keep this if it is nearer than the one we have already */
1842           if (q->symbol.value >= low_func_vma &&
1843               q->symbol.value <= offset) {
1844             low_func_vma = q->symbol.value;
1845             func = (asymbol *)q;
1846           }
1847           if (*line_ptr && func) {
1848             CONST char *function = func->name;
1849             char *p;
1850             strncpy(buffer, function, sizeof(buffer)-1);
1851             buffer[sizeof(buffer)-1] = 0;
1852             /* Have to remove : stuff */
1853             p = strchr(buffer,':');
1854             if (p != NULL) {*p = NULL; }
1855             *functionname_ptr = buffer;
1856             return true;
1857
1858           }
1859         }
1860         break;
1861       }
1862     }
1863   }
1864   
1865   return true;
1866
1867 }
1868
1869 static int 
1870 DEFUN(sunos4_sizeof_headers,(abfd),
1871       bfd *abfd)
1872 {
1873 return 0;
1874 }
1875
1876 #define sunos4_openr_next_archived_file bfd_generic_openr_next_archived_file
1877 #define sunos4_generic_stat_arch_elt bfd_generic_stat_arch_elt
1878 #define sunos4_slurp_armap bfd_slurp_bsd_armap
1879 #define sunos4_slurp_extended_name_table bfd_true
1880 #define sunos4_write_armap bsd_write_armap
1881 #define sunos4_truncate_arname bfd_bsd_truncate_arname
1882 bfd_target aout_big_vec =
1883 {
1884   "a.out-generic-big",          /* name */
1885   bfd_target_aout_flavour_enum,
1886   true,                         /* target byte order */
1887   true,                         /* target headers byte order */
1888   (HAS_RELOC | EXEC_P |         /* object flags */
1889    HAS_LINENO | HAS_DEBUG |
1890    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1891   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1892   ' ',                          /* ar_pad_char */
1893   16,                           /* ar_max_namelen */
1894   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
1895   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
1896
1897     {_bfd_dummy_target, sunos4_object_p,
1898        bfd_generic_archive_p, sunos4_core_file_p},
1899     {bfd_false, sunos4_mkobject,
1900        _bfd_generic_mkarchive, bfd_false},
1901
1902   JUMP_TABLE(sunos4)
1903   };
1904
1905
1906 bfd_target aout_little_vec =
1907 {
1908   "a.out-generic-little",               /* name */
1909   bfd_target_aout_flavour_enum,
1910   false,                        /* target byte order */
1911   false,                        /* target headers byte order */
1912   (HAS_RELOC | EXEC_P |         /* object flags */
1913    HAS_LINENO | HAS_DEBUG |
1914    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1915   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1916   ' ',                          /* ar_pad_char */
1917   16,                           /* ar_max_namelen */
1918   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
1919   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */
1920
1921
1922     {_bfd_dummy_target, sunos4_object_p,
1923        bfd_generic_archive_p, sunos4_core_file_p},
1924     {bfd_false, sunos4_mkobject,
1925        _bfd_generic_mkarchive, bfd_false},
1926
1927   JUMP_TABLE(sunos4)
1928   };