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