Thu May 9 11:00:45 1991 Steve Chamberlain (steve at cygint.cygnus.com)
[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_textsec(abfd)->size = align_power(obj_textsec(abfd)->size,
767                                               obj_textsec(abfd)->alignment_power);
768         obj_datasec(abfd)->filepos = obj_textsec (abfd)->filepos  + obj_textsec (abfd)->size;
769         obj_datasec(abfd)->size = align_power(obj_datasec(abfd)->size,
770                                               obj_datasec(abfd)->alignment_power);
771
772       }
773   /* regardless, once we know what we're doing, we might as well get going */
774   if (section != obj_bsssec(abfd)) {
775     bfd_seek (abfd, section->filepos + offset, SEEK_SET);
776
777     if (count) {
778       return (bfd_write ((PTR)location, 1, count, abfd) == count) ?
779         true : false;
780     }
781     return false;
782   }
783   return true;
784 }
785
786 boolean
787 sunos4_get_section_contents (abfd, section, location, offset, count)
788      bfd *abfd;
789      sec_ptr section;
790      PTR location;
791      file_ptr offset;
792      int count;
793 {
794   if (count) {
795     if (offset >= section->size) return false;
796
797     bfd_seek (abfd, section->filepos + offset, SEEK_SET);
798
799     return (bfd_read (location, 1, count, abfd) == count) ? true:false;
800   }
801   else return true;
802 }
803
804 \f
805 /* Classify stabs symbols */
806
807
808 #define sym_in_text_section(sym) \
809      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
810
811 #define sym_in_data_section(sym) \
812      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
813
814 #define sym_in_bss_section(sym) \
815      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
816
817 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
818    zero in the "value" field.  Nonzeroes there are fortrancommon
819    symbols.  */
820 #define sym_is_undefined(sym) \
821         ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
822
823 /* Symbol is a global definition if N_EXT is on and if it has
824    a nonzero type field.  */
825 #define sym_is_global_defn(sym) \
826         (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
827
828 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
829    are on.  */
830 #define sym_is_debugger_info(sym) \
831         ((sym)->n_type & ~(N_EXT | N_TYPE))
832
833 #define sym_is_fortrancommon(sym)       \
834         (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
835
836 /* Symbol is absolute if it has N_ABS set */
837 #define sym_is_absolute(sym) \
838                (((sym)->n_type  & N_TYPE)== N_ABS)
839
840
841 #define sym_is_indirect(sym) \
842                (((sym)->n_type  & N_ABS)== N_ABS)
843
844 /* Only in their own functions for ease of debugging; when sym flags have
845    stabilised these should be inlined into their (single) caller */
846
847 static void
848 translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
849      struct nlist *sym_pointer;
850      aout_symbol_type *cache_ptr;
851      bfd *abfd;
852 {
853   switch (cache_ptr->type & N_TYPE) {
854   case N_SETA:
855   case N_SETT:
856   case N_SETD:
857   case N_SETB:
858     {
859       asection *section = bfd_make_section(abfd,
860                                            cache_ptr->symbol.name);
861       arelent_chain *reloc = (arelent_chain *)bfd_alloc(abfd, sizeof(arelent_chain));
862
863       switch ( (cache_ptr->type  & N_TYPE) ) {
864       case N_SETA:
865         reloc->relent.section =  (asection *)NULL;
866         cache_ptr->symbol.section = (asection *)NULL;
867         break;
868       case N_SETT:
869         reloc->relent.section = (asection *)obj_textsec(abfd);
870         cache_ptr->symbol.value -= reloc->relent.section->vma;
871         break;
872       case N_SETD:
873         reloc->relent.section = (asection *)obj_datasec(abfd);
874         cache_ptr->symbol.value -= reloc->relent.section->vma;
875         break;
876       case N_SETB:
877         reloc->relent.section = (asection *)obj_bsssec(abfd);
878         cache_ptr->symbol.value -= reloc->relent.section->vma;
879         break;
880       }
881       cache_ptr->symbol.section = reloc->relent.section;
882       reloc->relent.addend = cache_ptr->symbol.value ;
883
884       /* We modify the symbol to belong to a section depending upon the
885          name of the symbol - probably __CTOR__ or __DTOR__ but we don't
886          really care, and add to the size of the section to contain a
887          pointer to the symbol. Build a reloc entry to relocate to this
888          symbol attached to this section.  */
889
890       section->flags = SEC_CONSTRUCTOR;
891       section->reloc_count++;
892       section->alignment_power = 2;
893       reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
894       reloc->next = section->constructor_chain;
895       section->constructor_chain = reloc;
896       reloc->relent.address = section->size;
897       section->size += sizeof(int *);
898
899       reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
900       cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
901       }
902     break;
903   default:
904
905     if (sym_is_debugger_info (sym_pointer)) {
906       cache_ptr->symbol.flags = BSF_DEBUGGING ;
907       /* Work out the section correct for this symbol */
908       switch (sym_pointer->n_type & N_TYPE) 
909         {
910         case N_TEXT:
911         case N_FN:
912           cache_ptr->symbol.section = obj_textsec (abfd);
913           cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
914           break;
915         case N_DATA:
916           cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
917           cache_ptr->symbol.section = obj_datasec (abfd);
918           break;
919         case N_BSS :
920           cache_ptr->symbol.section = obj_bsssec (abfd);
921           cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
922           break;
923         case N_ABS:
924         default:
925           cache_ptr->symbol.section = 0;
926           break;
927         }
928     }
929     else {
930       if (sym_is_fortrancommon (sym_pointer))
931         {
932           cache_ptr->symbol.flags = BSF_FORT_COMM;
933           cache_ptr->symbol.section = (asection *)NULL;
934         }
935       else {
936         if (sym_is_undefined (sym_pointer)) {
937           cache_ptr->symbol.flags = BSF_UNDEFINED;
938         }
939         else if (sym_is_global_defn (sym_pointer)) {
940           cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
941         }
942
943         else if (sym_is_absolute (sym_pointer)) {
944           cache_ptr->symbol.flags = BSF_ABSOLUTE;
945         }
946         else {
947           cache_ptr->symbol.flags = BSF_LOCAL;
948         }
949
950         /* In a.out, the value of a symbol is always relative to the 
951          * start of the file, if this is a data symbol we'll subtract
952          * the size of the text section to get the section relative
953          * value. If this is a bss symbol (which would be strange)
954          * we'll subtract the size of the previous two sections
955          * to find the section relative address.
956          */
957
958         if (sym_in_text_section (sym_pointer))   {
959           cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
960           cache_ptr->symbol.section = obj_textsec (abfd);
961         }
962         else if (sym_in_data_section (sym_pointer)){
963           cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
964           cache_ptr->symbol.section = obj_datasec (abfd);
965         }
966         else if (sym_in_bss_section(sym_pointer)) {
967           cache_ptr->symbol.section = obj_bsssec (abfd);
968           cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
969         }
970         else {
971           cache_ptr->symbol.section = (asection *)NULL;
972           cache_ptr->symbol.flags |= BSF_ABSOLUTE;
973         }
974       }
975     }
976   }
977 }
978
979 void
980 translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
981      struct nlist *sym_pointer;
982      PTR cache_ptr_g;
983      bfd *abfd;
984 {
985   asymbol *cache_ptr = (asymbol *)cache_ptr_g;
986
987   /* FIXME check for writing bss */
988   if (bfd_get_section(cache_ptr)) {
989     if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
990       sym_pointer->n_type |= N_BSS;
991     }
992     else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
993       sym_pointer->n_type |= N_DATA;
994     }
995     else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
996       sym_pointer->n_type |= N_TEXT;
997     }
998     else {
999       bfd_error_vector.nonrepresentable_section(abfd,
1000                                  bfd_get_output_section(cache_ptr)->name);
1001     }
1002     /* Turn the symbol from section relative to absolute again */
1003     sym_pointer->n_value +=
1004       cache_ptr->section->output_section->vma 
1005         + cache_ptr->section->output_offset ;
1006   }
1007   else {
1008     sym_pointer->n_type |= N_ABS;
1009   }
1010
1011   if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
1012     sym_pointer->n_type = (N_UNDF | N_EXT);
1013     return;
1014   }
1015
1016   if (cache_ptr->flags & BSF_ABSOLUTE) {
1017     sym_pointer->n_type |= N_ABS;
1018   }
1019
1020   if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
1021     sym_pointer->n_type |= N_EXT;
1022   }
1023   if (cache_ptr->flags & BSF_DEBUGGING) {
1024     sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
1025   }
1026 }
1027 \f
1028 /* Native-level interface to symbols. */
1029
1030 /* We read the symbols into a buffer, which is discarded when this
1031    function exits.  We read the strings into a buffer large enough to
1032    hold them all plus all the cached symbol entries. */
1033
1034 asymbol *
1035 sunos4_make_empty_symbol (abfd)
1036 bfd *abfd;
1037 {
1038   aout_symbol_type  *new =
1039     (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
1040   new->symbol.the_bfd = abfd;
1041
1042   return &new->symbol;
1043 }
1044
1045 boolean
1046 DEFUN(sunos4_slurp_symbol_table, (abfd),
1047       bfd *abfd)
1048 {
1049   size_t symbol_size;
1050   size_t string_size;
1051   unsigned char string_chars[LONG_SIZE];
1052   struct nlist *syms;
1053   char *strings;
1054   aout_symbol_type *cached;
1055
1056   /* If there's no work to be done, don't do any */
1057   if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
1058   symbol_size = exec_hdr(abfd)->a_syms;
1059   if (symbol_size == 0) {
1060     bfd_error = no_symbols;
1061     return false;
1062   }
1063
1064   bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1065   if (bfd_read ((PTR)string_chars, LONG_SIZE, 1, abfd) != LONG_SIZE)
1066     return false;
1067   string_size = bfd_h_getlong (abfd, string_chars);
1068
1069   strings = bfd_alloc(abfd, string_size + 1);
1070   cached = (aout_symbol_type *)
1071            bfd_zalloc(abfd, bfd_get_symcount (abfd) * sizeof(aout_symbol_type));
1072   /* Alloc this last, so we can free it if obstack is in use.  */
1073   syms = (struct nlist *) bfd_alloc(abfd, symbol_size);
1074
1075   bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1076   if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1077   bailout:
1078     if (syms)   bfd_release (abfd, syms);
1079     if (cached) bfd_release (abfd, cached);
1080     if (strings)bfd_release (abfd, strings);
1081     return false;
1082   }
1083
1084   bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1085   if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) {
1086     goto bailout;
1087   }
1088
1089   /* OK, now walk the new symtable, cacheing symbol properties */
1090     {
1091       register struct nlist *sym_pointer;
1092       register struct nlist *sym_end = syms + bfd_get_symcount (abfd);
1093       register aout_symbol_type *cache_ptr = cached;
1094
1095       /* run through the table and byte swap if needed */
1096       for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
1097         sym_pointer->n_un.n_strx =
1098           bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
1099         sym_pointer->n_desc =
1100           bfd_h_get_x (abfd, &sym_pointer->n_desc);
1101         sym_pointer->n_value =
1102           bfd_h_get_x (abfd, &sym_pointer->n_value);
1103         sym_pointer->n_other = (char)
1104           bfd_h_get_x(abfd, &sym_pointer->n_other);
1105         sym_pointer->n_type = (char)
1106           bfd_h_get_x(abfd, &sym_pointer->n_type);
1107       }
1108
1109       /* Run through table and copy values */
1110       for (sym_pointer = syms, cache_ptr = cached;
1111            sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
1112           {
1113             cache_ptr->symbol.the_bfd = abfd;
1114             if (sym_pointer->n_un.n_strx)
1115               cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
1116             else
1117               cache_ptr->symbol.name = (char *)NULL;
1118             cache_ptr->symbol.value = sym_pointer->n_value;
1119             cache_ptr->desc = sym_pointer->n_desc;
1120             cache_ptr->other = sym_pointer->n_other;
1121             cache_ptr->type = sym_pointer->n_type;
1122             cache_ptr->symbol.udata = 0;
1123             translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
1124
1125           }
1126     }
1127
1128   obj_aout_symbols (abfd) =  cached;
1129   bfd_release (abfd, (PTR)syms);
1130
1131   return true;
1132 }
1133
1134
1135 void
1136 DEFUN(sunos4_write_syms,(abfd),
1137      bfd *abfd)
1138 {
1139   unsigned int count ;
1140   asymbol **generic = bfd_get_outsymbols (abfd);
1141
1142   unsigned int stindex = sizeof(stindex); /* initial string length */
1143
1144   for (count = 0; count < bfd_get_symcount (abfd); count++) {
1145     asymbol *g = generic[count];
1146     struct nlist nsp;
1147
1148     if (g->name) {
1149       unsigned int length = strlen(g->name) +1;
1150       bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
1151       stindex += length;
1152     }
1153     else {
1154       bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
1155     }
1156
1157     if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
1158       {
1159         nsp.n_desc = aout_symbol( g)->desc;
1160         nsp.n_other = aout_symbol(g)->other;
1161         nsp.n_type = aout_symbol(g)->type;
1162       }
1163     else
1164       {
1165         nsp.n_desc = 0;
1166         nsp.n_other = 0;
1167         nsp.n_type = 0;
1168       }
1169
1170
1171     nsp.n_value = g->value;
1172     translate_to_native_sym_flags (&nsp, (PTR)g, abfd);
1173
1174
1175     bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
1176     bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
1177     bfd_write((PTR)&nsp,1, sizeof(nsp), abfd);
1178   }
1179
1180
1181   /* Now output the strings.  Be sure to put string length into correct
1182    * byte ordering before writing it.
1183    */
1184   bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
1185
1186   bfd_write((PTR)&stindex, 1, sizeof(stindex), abfd);
1187   
1188   generic = bfd_get_outsymbols(abfd);
1189   for (count = 0; count < bfd_get_symcount(abfd); count++) 
1190     {
1191       asymbol *g = *(generic++);
1192
1193       if (g->name)
1194         {
1195           size_t length = strlen(g->name)+1;
1196           bfd_write((PTR)g->name, 1, length, abfd);
1197         }
1198       if ((g->flags & BSF_FAKE)==0) {
1199         g->name = itos(count);  /* smash the generic symbol */
1200       }
1201     }
1202 }
1203
1204
1205 void
1206 DEFUN(sunos4_reclaim_symbol_table,(abfd),
1207      bfd *abfd)
1208 {
1209
1210 }
1211 \f
1212 unsigned int
1213 sunos4_get_symtab_upper_bound (abfd)
1214      bfd *abfd;
1215 {
1216   if (!sunos4_slurp_symbol_table (abfd)) return 0;
1217
1218   return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
1219 }
1220
1221 unsigned int
1222 sunos4_get_symtab (abfd, location)
1223      bfd *abfd;
1224      asymbol **location;
1225 {
1226   unsigned int counter = 0;
1227   aout_symbol_type *symbase;
1228
1229   if (!sunos4_slurp_symbol_table (abfd)) return 0;
1230
1231   for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
1232     *(location++) = (asymbol *)( symbase++);
1233   *location++ =0;
1234   return bfd_get_symcount(abfd);
1235 }
1236
1237 \f
1238 /* Standard reloc stuff */
1239 /* Output standard relocation information to a file in target byte order. */
1240
1241 void
1242 swap_std_reloc_out (abfd, g, natptr)
1243      bfd *abfd;
1244      arelent *g;                /* Generic relocation struct */
1245      struct reloc_std_bytes *natptr;
1246 {
1247   int r_index;
1248   int r_extern;
1249   unsigned int r_length;
1250   int r_pcrel;
1251   int r_baserel, r_jmptable, r_relative;
1252   unsigned int r_addend;
1253
1254   bfd_h_putlong (abfd, g->address, natptr->r_address);
1255
1256   r_length = g->howto->size ; /* Size as a power of two */
1257   r_pcrel  = (int) g->howto->pc_relative;       /* Relative to PC? */
1258   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
1259   r_baserel = 0;
1260   r_jmptable = 0;
1261   r_relative = 0;
1262
1263   r_addend = g->addend; /* Start here, see how it goes */
1264
1265   /* name was clobbered by sunos4_write_syms to be symbol index */
1266
1267   if (g->sym_ptr_ptr != NULL) 
1268     {
1269       if ((*(g->sym_ptr_ptr))->section) {
1270         /* put the section offset into the addend for output */
1271         r_addend += (*(g->sym_ptr_ptr))->section->vma;
1272       }
1273
1274       r_index = stoi((*(g->sym_ptr_ptr))->name);
1275       r_extern = 1;
1276     }
1277   else {
1278     r_extern = 0;
1279     if (g->section == NULL) {
1280       /* It is possible to have a reloc with nothing, we generate an
1281          abs + 0 */
1282       r_addend = 0;
1283       r_index = N_ABS | N_EXT;
1284     }
1285     else  if(g->section->output_section == obj_textsec(abfd)) {
1286       r_index = N_TEXT | N_EXT;
1287       r_addend += g->section->output_section->vma;
1288     }
1289     else if (g->section->output_section == obj_datasec(abfd)) {
1290       r_index = N_DATA | N_EXT;
1291       r_addend += g->section->output_section->vma;
1292     }
1293     else if (g->section->output_section == obj_bsssec(abfd)) {
1294       r_index = N_BSS | N_EXT ;
1295       r_addend += g->section->output_section->vma;
1296     }
1297     else {
1298       BFD_ASSERT(0);
1299     }
1300   }
1301
1302   /* now the fun stuff */
1303   if (abfd->xvec->header_byteorder_big_p != false) {
1304     natptr->r_index[0] = r_index >> 16;
1305     natptr->r_index[1] = r_index >> 8;
1306     natptr->r_index[2] = r_index;
1307     natptr->r_bits[0] =
1308       (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
1309         | (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
1310           | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
1311             | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
1312               | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
1313                 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG);
1314   } else {
1315     natptr->r_index[2] = r_index >> 16;
1316     natptr->r_index[1] = r_index >> 8;
1317     natptr->r_index[0] = r_index;
1318     natptr->r_bits[0] =
1319       (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
1320         | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
1321           | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
1322             | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1323               | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1324                 | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
1325   }
1326 }
1327
1328
1329 /* Extended stuff */
1330 /* Output extended relocation information to a file in target byte order. */
1331
1332 void
1333 swap_ext_reloc_out (abfd, g, natptr)
1334      bfd *abfd;
1335      arelent *g;                /* Generic relocation struct */
1336      register struct reloc_ext_bytes *natptr;
1337 {
1338   int r_index;
1339   int r_extern;
1340   unsigned int r_type;
1341   unsigned int r_addend;
1342
1343   bfd_h_putlong (abfd, g->address, natptr->r_address);
1344
1345   /* Find a type in the output format which matches the input howto - 
1346      at the moment we assume input format == output format FIXME!! */
1347   r_type = (enum reloc_type) g->howto->type;
1348
1349   r_addend = g->addend; /* Start here, see how it goes */
1350
1351   /* name was clobbered by sunos4_write_syms to be symbol index*/
1352
1353   if (g->sym_ptr_ptr != NULL) 
1354     {
1355       if ((*(g->sym_ptr_ptr))->section) {
1356         /* put the section offset into the addend for output */
1357         r_addend += (*(g->sym_ptr_ptr))->section->vma;
1358       }
1359
1360       r_index = stoi((*(g->sym_ptr_ptr))->name);
1361       r_extern = 1;
1362     }
1363   else {
1364     r_extern = 0;
1365     if (g->section == NULL) {
1366       BFD_ASSERT(0);
1367       r_index = N_ABS | N_EXT;
1368     }
1369     else  if(g->section->output_section == obj_textsec(abfd)) {
1370       r_index = N_TEXT | N_EXT;
1371       r_addend += g->section->output_section->vma;
1372     }
1373     else if (g->section->output_section == obj_datasec(abfd)) {
1374       r_index = N_DATA | N_EXT;
1375       r_addend += g->section->output_section->vma;
1376     }
1377     else if (g->section->output_section == obj_bsssec(abfd)) {
1378       r_index = N_BSS | N_EXT ;
1379       r_addend += g->section->output_section->vma;
1380     }
1381     else {
1382       BFD_ASSERT(0);
1383     }
1384   }
1385
1386   /* now the fun stuff */
1387   if (abfd->xvec->header_byteorder_big_p != false) {
1388     natptr->r_index[0] = r_index >> 16;
1389     natptr->r_index[1] = r_index >> 8;
1390     natptr->r_index[2] = r_index;
1391     natptr->r_bits[0] =
1392       (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1393         || (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1394   } else {
1395     natptr->r_index[2] = r_index >> 16;
1396     natptr->r_index[1] = r_index >> 8;
1397     natptr->r_index[0] = r_index;
1398     natptr->r_bits[0] =
1399       (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1400         || (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1401   }
1402
1403   bfd_h_putlong (abfd, r_addend, natptr->r_addend);
1404 }
1405
1406 #define MOVE_ADDRESS(ad)                                                \
1407   if (r_extern) {                                                       \
1408     cache_ptr->sym_ptr_ptr = symbols + r_index;                         \
1409     cache_ptr->section = (asection *)NULL;                              \
1410       cache_ptr->addend = ad;                                           \
1411   } else {                                                              \
1412     cache_ptr->sym_ptr_ptr = (asymbol **)NULL;                          \
1413     switch (r_index) {                                                  \
1414     case N_TEXT:                                                        \
1415     case N_TEXT | N_EXT:                                                \
1416       cache_ptr->section = obj_textsec(abfd);                           \
1417       cache_ptr->addend = ad  - su->textsec->vma;                       \
1418       break;                                                            \
1419     case N_DATA:                                                        \
1420     case N_DATA | N_EXT:                                                \
1421       cache_ptr->section = obj_datasec(abfd);                           \
1422       cache_ptr->addend = ad - su->datasec->vma;                        \
1423       break;                                                            \
1424     case N_BSS:                                                         \
1425     case N_BSS | N_EXT:                                                 \
1426       cache_ptr->section = obj_bsssec(abfd);                            \
1427       cache_ptr->addend = ad - su->bsssec->vma;                         \
1428       break;                                                            \
1429     case N_ABS:                                                         \
1430     case N_ABS | N_EXT:                                                 \
1431       cache_ptr->section = NULL;        /* No section */                \
1432       cache_ptr->addend = ad;           /* FIXME, is this right? */     \
1433       BFD_ASSERT(1);                                                    \
1434       break;                                                            \
1435     default:                                                            \
1436       cache_ptr->section = NULL;        /* No section */                \
1437       cache_ptr->addend = ad;           /* FIXME, is this right? */     \
1438       BFD_ASSERT(1);                                                    \
1439       break;                                                            \
1440     }                                                                   \
1441   }                                                                     \
1442
1443 void
1444 swap_ext_reloc_in (abfd, bytes, cache_ptr, symbols)
1445      bfd *abfd;
1446      struct reloc_ext_bytes *bytes;
1447      arelent *cache_ptr;
1448      asymbol **symbols;
1449 {
1450   int r_index;
1451   int r_extern;
1452   unsigned int r_type;
1453   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1454
1455   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1456
1457   /* now the fun stuff */
1458   if (abfd->xvec->header_byteorder_big_p != false) {
1459     r_index =  (bytes->r_index[0] << 16)
1460              | (bytes->r_index[1] << 8)
1461              |  bytes->r_index[2];
1462     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_BIG));
1463     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_BIG)
1464                                       >> RELOC_EXT_BITS_TYPE_SH_BIG;
1465   } else {
1466     r_index =  (bytes->r_index[2] << 16)
1467              | (bytes->r_index[1] << 8)
1468              |  bytes->r_index[0];
1469     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1470     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1471                                       >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1472   }
1473
1474   cache_ptr->howto =  howto_table_ext + r_type;
1475   MOVE_ADDRESS(bfd_h_getlong(abfd,bytes->r_addend));
1476 }
1477
1478 void
1479 swap_std_reloc_in (abfd, bytes, cache_ptr, symbols)
1480      bfd *abfd;
1481      struct reloc_std_bytes *bytes;
1482      arelent *cache_ptr;
1483      asymbol **symbols;
1484 {
1485   int r_index;
1486   int r_extern;
1487   unsigned int r_length;
1488   int r_pcrel;
1489   int r_baserel, r_jmptable, r_relative;
1490   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1491
1492   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1493
1494   /* now the fun stuff */
1495   if (abfd->xvec->header_byteorder_big_p != false) {
1496     r_index =  (bytes->r_index[0] << 16)
1497       | (bytes->r_index[1] << 8)
1498         |  bytes->r_index[2];
1499     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_BIG));
1500     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_BIG));
1501     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_BIG));
1502     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1503     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_BIG));
1504     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_BIG) 
1505                         >> RELOC_STD_BITS_LENGTH_SH_BIG;
1506   } else {
1507     r_index =  (bytes->r_index[2] << 16)
1508       | (bytes->r_index[1] << 8)
1509         |  bytes->r_index[0];
1510     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1511     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_LITTLE));
1512     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1513     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1514     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1515     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_LITTLE) 
1516                         >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1517   }
1518
1519   cache_ptr->howto =  howto_table_std + r_length + 4 * r_pcrel;
1520   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
1521
1522   MOVE_ADDRESS(0);
1523 }
1524
1525 /* Reloc hackery */
1526
1527 boolean
1528 sunos4_slurp_reloc_table (abfd, asect, symbols)
1529      bfd *abfd;
1530      sec_ptr asect;
1531      asymbol **symbols;
1532 {
1533   unsigned int count;
1534   size_t reloc_size;
1535   PTR relocs;
1536   arelent *reloc_cache;
1537   size_t each_size;
1538
1539   if (asect->relocation) return true;
1540
1541   if (asect->flags & SEC_CONSTRUCTOR) return true;
1542
1543   if (asect == obj_datasec (abfd)) {
1544     reloc_size = exec_hdr(abfd)->a_drsize;
1545     goto doit;
1546   }
1547
1548   if (asect == obj_textsec (abfd)) {
1549     reloc_size = exec_hdr(abfd)->a_trsize;
1550     goto doit;
1551   }
1552
1553   bfd_error = invalid_operation;
1554   return false;
1555
1556  doit:
1557   bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1558   each_size = reloc_size_func(abfd);
1559
1560   count = reloc_size / each_size;
1561
1562
1563   reloc_cache = (arelent *) bfd_zalloc (abfd, (size_t)(count * sizeof
1564                                                        (arelent)));
1565   if (!reloc_cache) {
1566 nomem:
1567     bfd_error = no_memory;
1568     return false;
1569   }
1570
1571   relocs =  bfd_alloc (abfd, reloc_size);
1572   if (!relocs) {
1573     bfd_release (abfd, reloc_cache);
1574     goto nomem;
1575   }
1576
1577   if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size) {
1578     bfd_release (abfd, relocs);
1579     bfd_release (abfd, reloc_cache);
1580     bfd_error = system_call_error;
1581     return false;
1582   }
1583
1584   if (each_size == RELOC_EXT_SIZE) {
1585     register struct reloc_ext_bytes *rptr = (struct reloc_ext_bytes *) relocs;
1586     unsigned int counter = 0;
1587     arelent *cache_ptr = reloc_cache;
1588
1589     for (; counter < count; counter++, rptr++, cache_ptr++) {
1590       swap_ext_reloc_in(abfd, rptr, cache_ptr, symbols);
1591     }
1592   } else {
1593     register struct reloc_std_bytes *rptr = (struct reloc_std_bytes *) relocs;
1594     unsigned int counter = 0;
1595     arelent *cache_ptr = reloc_cache;
1596
1597     for (; counter < count; counter++, rptr++, cache_ptr++) {
1598         swap_std_reloc_in(abfd, rptr, cache_ptr, symbols);
1599     }
1600
1601   }
1602
1603   bfd_release (abfd,relocs);
1604   asect->relocation = reloc_cache;
1605   asect->reloc_count = count;
1606   return true;
1607 }
1608
1609
1610
1611 /* Write out a relocation section into an object file.  */
1612
1613 static boolean
1614 sunos4_squirt_out_relocs (abfd, section)
1615      bfd *abfd;
1616      asection *section;
1617 {
1618   arelent **generic;
1619   unsigned char *native, *natptr;
1620   size_t each_size;
1621
1622   unsigned int count = section->reloc_count;
1623   size_t natsize;
1624
1625   if (count == 0) return true;
1626
1627   each_size = reloc_size_func(abfd);
1628   natsize = each_size * count;
1629   native = (unsigned char *) bfd_zalloc (abfd, natsize);
1630   if (!native) {
1631     bfd_error = no_memory;
1632     return false;
1633   }
1634
1635   generic = section->orelocation;
1636
1637   if (each_size == RELOC_EXT_SIZE) 
1638     {
1639       for (natptr = native;
1640            count != 0;
1641            --count, natptr += each_size, ++generic)
1642         swap_ext_reloc_out (abfd, *generic, (struct reloc_ext_bytes *)natptr);
1643     }
1644   else 
1645     {
1646       for (natptr = native;
1647            count != 0;
1648            --count, natptr += each_size, ++generic)
1649         swap_std_reloc_out(abfd, *generic, (struct reloc_std_bytes *)natptr);
1650     }
1651
1652   if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1653     bfd_release(abfd, native);
1654     return false;
1655   }
1656   bfd_release (abfd, native);
1657
1658   return true;
1659 }
1660
1661 /* This is stupid.  This function should be a boolean predicate */
1662 unsigned int
1663 sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
1664      bfd *abfd;
1665      sec_ptr section;
1666      arelent **relptr;
1667      asymbol **symbols;
1668 {
1669   arelent *tblptr = section->relocation;
1670   unsigned int count;
1671
1672   if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
1673     return 0;
1674
1675   if (section->flags & SEC_CONSTRUCTOR) {
1676     arelent_chain *chain = section->constructor_chain;
1677     for (count = 0; count < section->reloc_count; count ++) {
1678       *relptr ++ = &chain->relent;
1679       chain = chain->next;
1680     }
1681   }
1682   else {
1683     tblptr = section->relocation;
1684     if (!tblptr) return 0;
1685
1686     for (count = 0; count++ < section->reloc_count;) 
1687       {
1688         *relptr++ = tblptr++;
1689       }
1690   }
1691   *relptr = 0;
1692
1693   return section->reloc_count;
1694 }
1695
1696 unsigned int
1697 sunos4_get_reloc_upper_bound (abfd, asect)
1698      bfd *abfd;
1699      sec_ptr asect;
1700 {
1701   if (bfd_get_format (abfd) != bfd_object) {
1702     bfd_error = invalid_operation;
1703     return 0;
1704   }
1705   if (asect->flags & SEC_CONSTRUCTOR) {
1706     return (sizeof (arelent *) * (asect->reloc_count+1));
1707   }
1708
1709
1710   if (asect == obj_datasec (abfd))
1711     return (sizeof (arelent *) *
1712             ((exec_hdr(abfd)->a_drsize / reloc_size_func(abfd))
1713              +1));
1714
1715   if (asect == obj_textsec (abfd))
1716     return (sizeof (arelent *) *
1717             ((exec_hdr(abfd)->a_trsize / reloc_size_func(abfd))
1718              +1));
1719
1720   bfd_error = invalid_operation;
1721   return 0;
1722 }
1723
1724 void
1725 sunos4_reclaim_reloc (ignore_abfd, ignore)
1726      bfd *ignore_abfd;
1727      sec_ptr ignore;
1728 {
1729
1730 }
1731 \f
1732
1733 alent *
1734 sunos4_get_lineno(ignore_abfd, ignore_symbol)
1735 bfd *ignore_abfd;
1736 PTR ignore_symbol;
1737 {
1738 return (alent *)NULL;
1739 }
1740
1741 void 
1742 sunos4_print_symbol(ignore_abfd, file,  symbol, how)
1743 bfd *ignore_abfd;
1744 FILE *file;
1745 asymbol *symbol;
1746 bfd_print_symbol_enum_type how;
1747 {
1748   switch (how) {
1749   case bfd_print_symbol_name_enum:
1750     fprintf(file,"%s", symbol->name);
1751     break;
1752   case bfd_print_symbol_type_enum:
1753     fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1754             (unsigned)(aout_symbol(symbol)->other & 0xff),
1755             (unsigned)(aout_symbol(symbol)->type));
1756     break;
1757   case bfd_print_symbol_all_enum:
1758     {
1759    CONST char *section_name = symbol->section == (asection *)NULL ?
1760         "*abs" : symbol->section->name;
1761
1762       bfd_print_symbol_vandf((PTR)file,symbol);
1763
1764       fprintf(file," %-5s %04x %02x %02x %s",
1765               section_name,
1766               (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1767               (unsigned)(aout_symbol(symbol)->other & 0xff),
1768               (unsigned)(aout_symbol(symbol)->type  & 0xff),
1769               symbol->name);
1770     }
1771     break;
1772   }
1773 }
1774 /* Once we know all the stuff that could be consed, we know how to clean
1775    it up.  So why don't we? */
1776
1777 boolean
1778 sunos4_close_and_cleanup (abfd)
1779      bfd *abfd;
1780 {
1781   if (!bfd_read_p (abfd))
1782     switch (abfd->format) {
1783     case bfd_archive:
1784       if (!_bfd_write_archive_contents (abfd)) return false; break;
1785     case bfd_object:
1786       if (!sunos4_write_object_contents (abfd))  return false; break;
1787     default: bfd_error = invalid_operation; return false;
1788     }
1789
1790   return true;
1791 }
1792
1793 /* 
1794  provided a bfd, a section and an offset into the section, calculate
1795  and return the name of the source file and the line nearest to the
1796  wanted location.
1797 */
1798  
1799 boolean
1800 DEFUN(sunos4_find_nearest_line,(abfd,
1801                                 section,
1802                                 symbols,
1803                                 offset,
1804                                 filename_ptr,
1805                                 functionname_ptr,
1806                                 line_ptr),
1807       bfd *abfd AND
1808       asection *section AND
1809       asymbol **symbols AND
1810       bfd_vma offset AND
1811       CONST char **filename_ptr AND
1812       CONST char **functionname_ptr AND
1813       unsigned int *line_ptr)
1814 {
1815   /* Run down the file looking for the filename, function and linenumber */
1816   asymbol **p;
1817   static  char buffer[100];
1818   bfd_vma high_line_vma = ~0;
1819   bfd_vma low_func_vma = 0;
1820   asymbol *func = 0;
1821   *filename_ptr = abfd->filename;
1822   *functionname_ptr = 0;
1823   *line_ptr = 0;
1824   if (symbols != (asymbol **)NULL) {
1825     for (p = symbols; *p; p++) {
1826       aout_symbol_type  *q = (aout_symbol_type *)(*p);
1827       switch (q->type){
1828       case N_SO:
1829         *filename_ptr = q->symbol.name;
1830         if (obj_textsec(abfd) != section) {
1831           return true;
1832         }
1833         break;
1834       case N_SLINE:
1835
1836       case N_DSLINE:
1837       case N_BSLINE:
1838         /* We'll keep this if it resolves nearer than the one we have already */
1839         if (q->symbol.value >= offset &&
1840             q->symbol.value < high_line_vma) {
1841           *line_ptr = q->desc;
1842           high_line_vma = q->symbol.value;
1843         }
1844         break;
1845       case N_FUN:
1846         {
1847           /* We'll keep this if it is nearer than the one we have already */
1848           if (q->symbol.value >= low_func_vma &&
1849               q->symbol.value <= offset) {
1850             low_func_vma = q->symbol.value;
1851             func = (asymbol *)q;
1852           }
1853           if (*line_ptr && func) {
1854             CONST char *function = func->name;
1855             char *p;
1856             strncpy(buffer, function, sizeof(buffer)-1);
1857             buffer[sizeof(buffer)-1] = 0;
1858             /* Have to remove : stuff */
1859             p = strchr(buffer,':');
1860             if (p != NULL) {*p = NULL; }
1861             *functionname_ptr = buffer;
1862             return true;
1863
1864           }
1865         }
1866         break;
1867       }
1868     }
1869   }
1870   
1871   return true;
1872
1873 }
1874
1875 static int 
1876 DEFUN(sunos4_sizeof_headers,(ignore_abfd),
1877       bfd *ignore_abfd)
1878 {
1879   return 0;             /* FIXME, this is the wrong value! */
1880 }
1881
1882 #define sunos4_openr_next_archived_file bfd_generic_openr_next_archived_file
1883 #define sunos4_generic_stat_arch_elt bfd_generic_stat_arch_elt
1884 #define sunos4_slurp_armap bfd_slurp_bsd_armap
1885 #define sunos4_slurp_extended_name_table bfd_true
1886 #define sunos4_write_armap bsd_write_armap
1887 #define sunos4_truncate_arname bfd_bsd_truncate_arname
1888 bfd_target aout_big_vec =
1889 {
1890   "a.out-generic-big",          /* name */
1891   bfd_target_aout_flavour_enum,
1892   true,                         /* target byte order */
1893   true,                         /* target headers byte order */
1894   (HAS_RELOC | EXEC_P |         /* object flags */
1895    HAS_LINENO | HAS_DEBUG |
1896    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1897   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1898   ' ',                          /* ar_pad_char */
1899   16,                           /* ar_max_namelen */
1900   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
1901   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
1902
1903     {_bfd_dummy_target, sunos4_object_p,
1904        bfd_generic_archive_p, sunos4_core_file_p},
1905     {bfd_false, sunos4_mkobject,
1906        _bfd_generic_mkarchive, bfd_false},
1907
1908   JUMP_TABLE(sunos4)
1909   };
1910
1911
1912 bfd_target aout_little_vec =
1913 {
1914   "a.out-generic-little",               /* name */
1915   bfd_target_aout_flavour_enum,
1916   false,                        /* target byte order */
1917   false,                        /* target headers byte order */
1918   (HAS_RELOC | EXEC_P |         /* object flags */
1919    HAS_LINENO | HAS_DEBUG |
1920    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1921   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
1922   ' ',                          /* ar_pad_char */
1923   16,                           /* ar_max_namelen */
1924   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
1925   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */
1926
1927
1928     {_bfd_dummy_target, sunos4_object_p,
1929        bfd_generic_archive_p, sunos4_core_file_p},
1930     {bfd_false, sunos4_mkobject,
1931        _bfd_generic_mkarchive, bfd_false},
1932
1933   JUMP_TABLE(sunos4)
1934   };