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