Merged in some changes from Intel,
[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 typedef void generic_symbol_type;
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) zalloc (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 =  zalloc (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_UNKNOWN; 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 = zalloc (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 *) zalloc (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 *) zalloc (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 *) zalloc (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 *) zalloc (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
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 boolean
850 sunos4_get_section_contents (abfd, section, location, offset, count)
851      bfd *abfd;
852      sec_ptr section;
853      PTR location;
854      file_ptr offset;
855      int count;
856 {
857   if (count) {
858     if (offset >= section->size) return false;
859
860     bfd_seek (abfd, section->filepos + offset, SEEK_SET);
861
862     return (bfd_read (location, 1, count, abfd) == count) ? true:false;
863   }
864   else return true;
865 }
866
867 \f
868 /* Classify stabs symbols */
869
870
871 #define sym_in_text_section(sym) \
872      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_TEXT)
873
874 #define sym_in_data_section(sym) \
875      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_DATA)
876
877 #define sym_in_bss_section(sym) \
878      (((sym)->n_type  & (N_ABS | N_TEXT | N_DATA | N_BSS))== N_BSS)
879
880 /* Symbol is undefined if type is N_UNDF|N_EXT and if it has
881    zero in the "value" field.  Nonzeroes there are fortrancommon
882    symbols.  */
883 #define sym_is_undefined(sym) \
884         ((sym)->n_type == (N_UNDF | N_EXT) && (sym)->n_value == 0)
885
886 /* Symbol is a global definition if N_EXT is on and if it has
887    a nonzero type field.  */
888 #define sym_is_global_defn(sym) \
889         (((sym)->n_type & N_EXT) && (sym)->n_type & N_TYPE)
890
891 /* Symbol is debugger info if any bits outside N_TYPE or N_EXT
892    are on.  */
893 #define sym_is_debugger_info(sym) \
894         ((sym)->n_type & ~(N_EXT | N_TYPE))
895
896 #define sym_is_fortrancommon(sym)       \
897         (((sym)->n_type == (N_EXT)) && (sym)->n_value != 0)
898
899 /* Symbol is absolute if it has N_ABS set */
900 #define sym_is_absolute(sym) \
901                (((sym)->n_type  & N_TYPE)== N_ABS)
902
903
904 #define sym_is_indirect(sym) \
905                (((sym)->n_type  & N_ABS)== N_ABS)
906
907 /* Only in their own functions for ease of debugging; when sym flags have
908    stabilised these should be inlined into their (single) caller */
909
910 static void
911 translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd)
912      struct nlist *sym_pointer;
913      aout_symbol_type *cache_ptr;
914      bfd *abfd;
915 {
916   switch (cache_ptr->type & N_TYPE) {
917   case N_SETA:
918   case N_SETT:
919   case N_SETD:
920   case N_SETB:
921     {
922       asection *section = bfd_make_section(abfd,
923                                            cache_ptr->symbol.name);
924       arelent_chain *reloc = (arelent_chain *)malloc(sizeof(arelent_chain));
925
926       switch ( (cache_ptr->type  & N_TYPE) ) {
927       case N_SETA:
928         reloc->relent.section =  (asection *)NULL;
929         cache_ptr->symbol.section = (asection *)NULL;
930         break;
931       case N_SETT:
932         reloc->relent.section = (asection *)obj_textsec(abfd);
933         cache_ptr->symbol.value -= reloc->relent.section->vma;
934         break;
935       case N_SETD:
936         reloc->relent.section = (asection *)obj_datasec(abfd);
937         cache_ptr->symbol.value -= reloc->relent.section->vma;
938         break;
939       case N_SETB:
940         reloc->relent.section = (asection *)obj_bsssec(abfd);
941         cache_ptr->symbol.value -= reloc->relent.section->vma;
942         break;
943       }
944       cache_ptr->symbol.section = reloc->relent.section;
945       reloc->relent.addend = cache_ptr->symbol.value ;
946       /* 
947          We modify the symbol to belong to a section depending upon the
948          name of the symbol - probably __CTOR__ or __DTOR__ but we don't
949          really care, and add to the size of the section to contain a
950          pointer to the symbol. Build a reloc entry to relocate to this
951          symbol attached to this section.
952          */
953
954
955       section->flags = SEC_CONSTRUCTOR;
956       section->reloc_count++;
957       section->alignment_power = 2;
958       reloc->relent.sym_ptr_ptr = (asymbol **)NULL;
959       reloc->next = section->constructor_chain;
960       section->constructor_chain = reloc;
961       reloc->relent.address = section->size;
962       section->size += sizeof(int *);
963
964       reloc->relent.howto = howto_table_ext +CTOR_TABLE_RELOC_IDX;
965       cache_ptr->symbol.flags |=  BSF_DEBUGGING ;
966       }
967     break;
968   default:
969
970     if (sym_is_debugger_info (sym_pointer)) {
971       cache_ptr->symbol.flags = BSF_DEBUGGING ;
972       /* Work out the section correct for this symbol */
973       switch (sym_pointer->n_type & N_TYPE) 
974         {
975         case N_TEXT:
976         case N_FN:
977           cache_ptr->symbol.section = obj_textsec (abfd);
978           cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
979           break;
980         case N_DATA:
981           cache_ptr->symbol.value  -= obj_datasec(abfd)->vma;
982           cache_ptr->symbol.section = obj_datasec (abfd);
983           break;
984         case N_BSS :
985           cache_ptr->symbol.section = obj_bsssec (abfd);
986           cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
987           break;
988         case N_ABS:
989         default:
990           cache_ptr->symbol.section = 0;
991           break;
992         }
993     }
994     else {
995       if (sym_is_fortrancommon (sym_pointer))
996         {
997           cache_ptr->symbol.flags = BSF_FORT_COMM;
998           cache_ptr->symbol.section = (asection *)NULL;
999         }
1000       else {
1001         if (sym_is_undefined (sym_pointer)) {
1002           cache_ptr->symbol.flags = BSF_UNDEFINED;
1003         }
1004         else if (sym_is_global_defn (sym_pointer)) {
1005           cache_ptr->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
1006         }
1007
1008         else if (sym_is_absolute (sym_pointer)) {
1009           cache_ptr->symbol.flags = BSF_ABSOLUTE;
1010         }
1011         else {
1012           cache_ptr->symbol.flags = BSF_LOCAL;
1013         }
1014
1015         /* In a.out, the value of a symbol is always relative to the 
1016          * start of the file, if this is a data symbol we'll subtract
1017          * the size of the text section to get the section relative
1018          * value. If this is a bss symbol (which would be strange)
1019          * we'll subtract the size of the previous two sections
1020          * to find the section relative address.
1021          */
1022
1023         if (sym_in_text_section (sym_pointer))   {
1024           cache_ptr->symbol.value -= obj_textsec(abfd)->vma;
1025           cache_ptr->symbol.section = obj_textsec (abfd);
1026         }
1027         else if (sym_in_data_section (sym_pointer)){
1028           cache_ptr->symbol.value -= obj_datasec(abfd)->vma;
1029           cache_ptr->symbol.section = obj_datasec (abfd);
1030         }
1031         else if (sym_in_bss_section(sym_pointer)) {
1032           cache_ptr->symbol.section = obj_bsssec (abfd);
1033           cache_ptr->symbol.value -= obj_bsssec(abfd)->vma;
1034         }
1035         else {
1036           cache_ptr->symbol.section = (asection *)NULL;
1037           cache_ptr->symbol.flags |= BSF_ABSOLUTE;
1038         }
1039       }
1040     }
1041   }
1042 }
1043
1044 void
1045 translate_to_native_sym_flags (sym_pointer, cache_ptr_g, abfd)
1046      struct nlist *sym_pointer;
1047      generic_symbol_type *cache_ptr_g;
1048      bfd *abfd;
1049 {
1050   asymbol *cache_ptr = (asymbol *)cache_ptr_g;
1051
1052   /* FIXME check for wrigin bss */
1053   if (bfd_get_section(cache_ptr)) {
1054     if (bfd_get_output_section(cache_ptr) == obj_bsssec (abfd)) {
1055       sym_pointer->n_type |= N_BSS;
1056     }
1057     else if (bfd_get_output_section(cache_ptr) == obj_datasec (abfd)) {
1058       sym_pointer->n_type |= N_DATA;
1059     }
1060     else  if (bfd_get_output_section(cache_ptr) == obj_textsec (abfd)) {
1061       sym_pointer->n_type |= N_TEXT;
1062     }
1063     else {
1064
1065       bfd_error_vector.nonrepresentable_section(abfd, bfd_get_output_section(cache_ptr)->name);
1066
1067     }
1068     /* Turn the symbol from section relative to absolute again */
1069     sym_pointer->n_value +=
1070       cache_ptr->section->output_section->vma 
1071         + cache_ptr->section->output_offset ;
1072   }
1073   else {
1074     sym_pointer->n_type |= N_ABS;
1075   }
1076
1077   if (cache_ptr->flags & (BSF_FORT_COMM | BSF_UNDEFINED)) {
1078     sym_pointer->n_type = (N_UNDF | N_EXT);
1079     return;
1080   }
1081
1082   if (cache_ptr->flags & BSF_ABSOLUTE) {
1083     sym_pointer->n_type |= N_ABS;
1084   }
1085
1086   if (cache_ptr->flags & (BSF_GLOBAL | BSF_EXPORT)) {
1087     sym_pointer->n_type |= N_EXT;
1088   }
1089   if (cache_ptr->flags & BSF_DEBUGGING) {
1090     sym_pointer->n_type = ((aout_symbol_type *)cache_ptr)->type;
1091   }
1092   
1093 }
1094 \f
1095 /* Native-level interface to symbols. */
1096
1097 /* We read the symbols into a buffer, which is discarded when this
1098    function exits.  We read the strings into a buffer large enough to
1099    hold them all plus all the cached symbol entries. */
1100
1101 asymbol *
1102 sunos4_make_empty_symbol (abfd)
1103 bfd *abfd;
1104 {
1105   aout_symbol_type  *new =
1106     (aout_symbol_type *)zalloc (sizeof (aout_symbol_type));
1107   new->symbol.the_bfd = abfd;
1108
1109   return &new->symbol;
1110 }
1111
1112 boolean
1113 DEFUN(sunos4_slurp_symbol_table, (abfd),
1114       bfd *abfd)
1115 {
1116   unsigned int symbol_count;
1117   size_t symbol_size;
1118   size_t string_size;
1119   struct nlist *syms;
1120   char *strings;
1121   aout_symbol_type *cached;
1122
1123   /* If there's no work to be done, don't do any */
1124   if (obj_aout_symbols (abfd) != (aout_symbol_type *)NULL) return true;
1125   symbol_size = exec_hdr(abfd)->a_syms;
1126   if (symbol_size == 0) {
1127     bfd_error = no_symbols;
1128     return false;
1129   }
1130
1131   bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1132   if (bfd_read ((PTR)&string_size, 4, 1, abfd) != 4)
1133     return false;
1134   string_size = bfd_h_getlong (abfd, (unsigned char *)&string_size);
1135
1136   symbol_count = symbol_size / sizeof (struct nlist);
1137
1138   /* Malloc (should alloca) space for native symbols, and
1139      malloc space for string table and symbol cache. */
1140
1141   syms = (struct nlist *) zalloc (symbol_size);
1142   if (syms == NULL) {
1143     bfd_error = no_memory;
1144     return false;
1145   }
1146
1147   cached = (aout_symbol_type *) zalloc ((size_t)(string_size + 1 +
1148                                (symbol_count * sizeof (aout_symbol_type))));
1149   if (cached == NULL) {
1150     bfd_error = no_memory;
1151     free ((PTR)syms);
1152     return false;
1153   }
1154
1155   strings = ((char *) cached) + (symbol_count * sizeof (aout_symbol_type));
1156
1157   bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET);
1158   if (bfd_read ((PTR)syms, 1, symbol_size, abfd) != symbol_size) {
1159   bailout:
1160     free ((PTR)cached);
1161     free ((PTR)syms);
1162     return false;
1163   }
1164
1165   bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET);
1166   if (bfd_read ((PTR)strings, 1, string_size, abfd) != string_size) {
1167     goto bailout;
1168   }
1169
1170   /* OK, now walk the new symtable, cacheing symbol properties */
1171   {
1172     register struct nlist *sym_pointer;
1173     register struct nlist *sym_end = syms + symbol_count;
1174     register aout_symbol_type *cache_ptr = cached;
1175
1176       /* run through the table and byte swap if needed */
1177       for (sym_pointer = syms; sym_pointer < sym_end;  sym_pointer++) {
1178         sym_pointer->n_un.n_strx =
1179           bfd_h_get_x (abfd, &sym_pointer->n_un.n_strx);
1180         sym_pointer->n_desc =
1181           bfd_h_get_x (abfd, &sym_pointer->n_desc);
1182         sym_pointer->n_value =
1183           bfd_h_get_x (abfd, &sym_pointer->n_value);
1184         sym_pointer->n_other = (char)
1185           bfd_h_get_x(abfd, &sym_pointer->n_other);
1186         sym_pointer->n_type = (char)
1187           bfd_h_get_x(abfd, &sym_pointer->n_type);
1188
1189       }
1190
1191     /* Run through table and copy values */
1192     for (sym_pointer = syms, cache_ptr = cached;
1193          sym_pointer < sym_end; sym_pointer++, cache_ptr++) 
1194       {
1195         cache_ptr->symbol.the_bfd = abfd;
1196         if (sym_pointer->n_un.n_strx)
1197           cache_ptr->symbol.name = sym_pointer->n_un.n_strx + strings;
1198         else
1199           cache_ptr->symbol.name = (char *)NULL;
1200         cache_ptr->symbol.value = sym_pointer->n_value;
1201         cache_ptr->desc = sym_pointer->n_desc;
1202         cache_ptr->other = sym_pointer->n_other;
1203         cache_ptr->type = sym_pointer->n_type;
1204         cache_ptr->symbol.udata = 0;
1205         translate_from_native_sym_flags (sym_pointer, cache_ptr, abfd);
1206
1207       }
1208   }
1209
1210   obj_aout_symbols (abfd) =  cached;
1211   bfd_get_symcount (abfd) = symbol_count;
1212   free ((PTR)syms);
1213
1214   return true;
1215 }
1216
1217
1218 void
1219 DEFUN(sunos4_write_syms,(abfd),
1220      bfd *abfd)
1221 {
1222   unsigned int count ;
1223   asymbol **generic = bfd_get_outsymbols (abfd);
1224
1225   unsigned int stindex = sizeof(stindex); /* initial string length */
1226
1227   for (count = 0; count < bfd_get_symcount (abfd); count++) {
1228     asymbol *g = generic[count];
1229     struct nlist nsp;
1230
1231     if (g->name) {
1232       unsigned int length = strlen(g->name) +1;
1233       bfd_h_putlong  (abfd, stindex, (unsigned char *)&nsp.n_un.n_strx);
1234       stindex += length;
1235     }
1236     else {
1237       bfd_h_putlong  (abfd, 0, (unsigned char *)&nsp.n_un.n_strx);
1238     }
1239
1240     if (g->the_bfd->xvec->flavour == abfd->xvec->flavour) 
1241       {
1242         nsp.n_desc = aout_symbol( g)->desc;
1243         nsp.n_other = aout_symbol(g)->other;
1244         nsp.n_type = aout_symbol(g)->type;
1245       }
1246     else
1247       {
1248         nsp.n_desc = 0;
1249         nsp.n_other = 0;
1250         nsp.n_type = 0;
1251       }
1252
1253
1254     nsp.n_value = g->value;
1255     translate_to_native_sym_flags (&nsp, (generic_symbol_type *)g, abfd);
1256
1257
1258     bfd_h_putshort (abfd, nsp.n_desc, (unsigned char *)&nsp.n_desc);
1259     bfd_h_putlong  (abfd, nsp.n_value, (unsigned char *)&nsp.n_value);
1260     bfd_write((PTR)&nsp,1, sizeof(nsp), abfd);
1261   }
1262
1263
1264   /* Now output the strings.  Be sure to put string length into correct
1265    * byte ordering before writing it.
1266    */
1267   bfd_h_putlong  (abfd, stindex, (unsigned char *)&stindex);
1268
1269   bfd_write((PTR)&stindex, 1, sizeof(stindex), abfd);
1270   
1271   generic = bfd_get_outsymbols(abfd);
1272   for (count = 0; count < bfd_get_symcount(abfd); count++) 
1273     {
1274       asymbol *g = *(generic++);
1275
1276       if (g->name != (char *)NULL) 
1277         {
1278           size_t length = strlen(g->name)+1;
1279           bfd_write((PTR)g->name, 1, length, abfd);
1280         }
1281       if ((g->flags & BSF_FAKE)==0) {
1282         g->name = itos(count);  /* smash the generic symbol */
1283       }
1284     }
1285 }
1286
1287
1288 void
1289 DEFUN(sunos4_reclaim_symbol_table,(abfd),
1290      bfd *abfd)
1291 {
1292   asection *section;
1293
1294   if (!bfd_get_symcount (abfd)) return;
1295
1296   for (section = abfd->sections;
1297        section != (asection *) NULL;
1298        section = section->next)
1299     if (section->relocation) {
1300       free ((PTR)section->relocation);
1301       section->relocation = NULL;
1302       section->reloc_count = 0;
1303     }
1304
1305   bfd_get_symcount (abfd) = 0;
1306   free ((PTR)obj_aout_symbols (abfd));
1307   obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
1308 }
1309 \f
1310 unsigned int
1311 sunos4_get_symtab_upper_bound (abfd)
1312      bfd *abfd;
1313 {
1314   if (!sunos4_slurp_symbol_table (abfd)) return 0;
1315
1316   return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
1317 }
1318
1319 unsigned int
1320 sunos4_get_symtab (abfd, location)
1321      bfd *abfd;
1322      asymbol **location;
1323 {
1324   unsigned int counter = 0;
1325   aout_symbol_type *symbase;
1326
1327   if (!sunos4_slurp_symbol_table (abfd)) return 0;
1328
1329   for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
1330     *(location++) = (asymbol *)( symbase++);
1331   *location++ =0;
1332   return bfd_get_symcount(abfd);
1333 }
1334
1335 \f
1336 /* Obsolete procedural interface; better to look at the cache directly */
1337
1338 /* User should have checked the file flags; perhaps we should return
1339    BFD_NO_MORE_SYMBOLS if there are none? */
1340
1341 int
1342 sunos4_get_symcount_upper_bound (abfd)
1343      bfd *abfd;
1344 {
1345   /* In case we're doing an output file or something...?  */
1346   if (bfd_get_symcount (abfd)) return bfd_get_symcount (abfd);
1347
1348   return (exec_hdr (abfd)->a_syms) / (sizeof (struct nlist));
1349 }
1350
1351 symindex
1352 sunos4_get_first_symbol (ignore_abfd)
1353      bfd * ignore_abfd;
1354 {
1355   return 0;
1356 }
1357
1358 symindex
1359 sunos4_get_next_symbol (abfd, oidx)
1360      bfd *abfd;
1361      symindex oidx;
1362 {
1363   if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
1364   return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
1365 }
1366
1367 CONST char *
1368 sunos4_symbol_name (abfd, idx)
1369      bfd *abfd;
1370      symindex idx;
1371 {
1372   return (obj_aout_symbols (abfd) + idx)->symbol.name;
1373 }
1374
1375 long
1376 sunos4_symbol_value (abfd, idx)
1377      bfd *abfd;
1378      symindex idx;
1379 {
1380   return (obj_aout_symbols (abfd) + idx)->symbol.value;
1381 }
1382
1383 symclass
1384 sunos4_classify_symbol (abfd, idx)
1385      bfd *abfd;
1386      symindex idx;
1387 {
1388   aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
1389
1390   if ((sym->symbol.flags & BSF_FORT_COMM) != 0)   return bfd_symclass_fcommon;
1391   if ((sym->symbol.flags & BSF_GLOBAL) != 0)    return bfd_symclass_global;
1392   if ((sym->symbol.flags & BSF_DEBUGGING) != 0)  return bfd_symclass_debugger;
1393   if ((sym->symbol.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined;
1394
1395   return bfd_symclass_unknown;
1396 }
1397
1398 boolean
1399 sunos4_symbol_hasclass (abfd, idx, class)
1400      bfd *abfd;
1401      symindex idx;
1402      symclass class;
1403 {
1404   aout_symbol_type *sym = obj_aout_symbols (abfd) + idx;
1405   switch (class) {
1406   case bfd_symclass_fcommon:
1407     return (sym->symbol.flags & BSF_FORT_COMM) ? true :false;
1408   case bfd_symclass_global:
1409     return (sym->symbol.flags & BSF_GLOBAL) ? true:false;
1410   case bfd_symclass_debugger:
1411     return (sym->symbol.flags & BSF_DEBUGGING) ? true:false;;
1412   case bfd_symclass_undefined:
1413     return (sym->symbol.flags & BSF_UNDEFINED) ? true:false;;
1414   default: return false;
1415   }
1416 }
1417 \f
1418 /* Standard reloc stuff */
1419 /* Output standard relocation information to a file in target byte order. */
1420
1421 void
1422 swap_std_reloc_out (abfd, p, natptr, count)
1423      bfd *abfd;
1424      arelent **p;               /* Generic relocation struct */
1425      struct reloc_std_bytes *natptr;
1426      unsigned int count;
1427 {
1428   int r_index;
1429   int r_extern;
1430   unsigned int r_length;
1431   int r_pcrel;
1432   int r_baserel, r_jmptable, r_relative;
1433   unsigned int r_addend;
1434   unsigned int idx;
1435   for (idx = 0; idx < count; idx++, p++, natptr++) 
1436     {
1437       arelent *g = *p;
1438       bfd_h_putlong (abfd, g->address, natptr->r_address);
1439
1440       r_length = g->howto->size; /* Size as a power of two */
1441       r_pcrel  = (int) g->howto->pc_relative;   /* Relative to PC? */
1442       /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
1443       r_baserel = 0;
1444       r_jmptable = 0;
1445       r_relative = 0;
1446
1447       r_addend = g->addend;     /* Start here, see how it goes */
1448
1449       /* name was clobbered by sunos4_write_syms to be symbol index */
1450
1451       if (g->sym_ptr_ptr != NULL) 
1452         {
1453           if ((*(g->sym_ptr_ptr))->section) {
1454             /* put the section offset into the addend for output */
1455             r_addend += (*(g->sym_ptr_ptr))->section->vma;
1456           }
1457
1458           r_index = stoi((*(g->sym_ptr_ptr))->name);
1459           r_extern = 1;
1460         }
1461       else {
1462         r_extern = 0;
1463         if (g->section == NULL) {
1464           BFD_ASSERT(0);
1465           r_index = N_ABS | N_EXT;
1466         }
1467         else  if(g->section->output_section == obj_textsec(abfd)) {
1468           r_index = N_TEXT | N_EXT;
1469           r_addend += g->section->output_section->vma;
1470         }
1471         else if (g->section->output_section == obj_datasec(abfd)) {
1472           r_index = N_DATA | N_EXT;
1473           r_addend += g->section->output_section->vma;
1474         }
1475         else if (g->section->output_section == obj_bsssec(abfd)) {
1476           r_index = N_BSS | N_EXT ;
1477           r_addend += g->section->output_section->vma;
1478         }
1479         else {
1480           BFD_ASSERT(0);
1481         }
1482       }
1483
1484       /* now the fun stuff */
1485       if (abfd->xvec->header_byteorder_big_p != false) {
1486         natptr->r_index[0] = r_index >> 16;
1487         natptr->r_index[1] = r_index >> 8;
1488         natptr->r_index[2] = r_index;
1489         natptr->r_bits[0] =
1490           (r_extern?    RELOC_STD_BITS_EXTERN_BIG: 0)
1491             | (r_pcrel?     RELOC_STD_BITS_PCREL_BIG: 0)
1492               | (r_baserel?   RELOC_STD_BITS_BASEREL_BIG: 0)
1493                 | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_BIG: 0)
1494                   | (r_relative?  RELOC_STD_BITS_RELATIVE_BIG: 0)
1495                     | (r_length <<  RELOC_STD_BITS_LENGTH_SH_BIG);
1496       } else {
1497         natptr->r_index[2] = r_index >> 16;
1498         natptr->r_index[1] = r_index >> 8;
1499         natptr->r_index[0] = r_index;
1500         natptr->r_bits[0] =
1501           (r_extern?    RELOC_STD_BITS_EXTERN_LITTLE: 0)
1502             | (r_pcrel?     RELOC_STD_BITS_PCREL_LITTLE: 0)
1503               | (r_baserel?   RELOC_STD_BITS_BASEREL_LITTLE: 0)
1504                 | (r_jmptable?  RELOC_STD_BITS_JMPTABLE_LITTLE: 0)
1505                   | (r_relative?  RELOC_STD_BITS_RELATIVE_LITTLE: 0)
1506                     | (r_length <<  RELOC_STD_BITS_LENGTH_SH_LITTLE);
1507       }
1508
1509
1510     }
1511 }
1512
1513
1514 /* Extended stuff */
1515 /* Output extended relocation information to a file in target byte order. */
1516
1517 void
1518 swap_ext_reloc_out (abfd, p, natptr, count)
1519      bfd *abfd;
1520      arelent **p;               /* Generic relocation struct */
1521      register struct reloc_ext_bytes *natptr;
1522      unsigned int count;
1523 {
1524
1525   int r_index;
1526   int r_extern;
1527   unsigned int r_type;
1528   unsigned int r_addend;
1529   unsigned int idx;
1530   for (idx = 0; idx < count; idx++, p++, natptr++) {
1531     arelent *g = *p;
1532
1533     bfd_h_putlong (abfd, g->address, natptr->r_address);
1534
1535     /* Find a type in the output format which matches the input howto - 
1536        at the moment we assume input format == output format FIXME!! */
1537     r_type = (enum reloc_type) g->howto->type;
1538
1539     r_addend = g->addend;       /* Start here, see how it goes */
1540
1541     /* name was clobbered by sunos4_write_syms to be symbol index*/
1542
1543     if (g->sym_ptr_ptr != NULL) 
1544       {
1545         if ((*(g->sym_ptr_ptr))->section) {
1546           /* put the section offset into the addend for output */
1547           r_addend += (*(g->sym_ptr_ptr))->section->vma;
1548         }
1549
1550         r_index = stoi((*(g->sym_ptr_ptr))->name);
1551         r_extern = 1;
1552       }
1553     else {
1554       r_extern = 0;
1555       if (g->section == NULL) {
1556         BFD_ASSERT(0);
1557         r_index = N_ABS | N_EXT;
1558       }
1559       else  if(g->section->output_section == obj_textsec(abfd)) {
1560         r_index = N_TEXT | N_EXT;
1561         r_addend += g->section->output_section->vma;
1562       }
1563       else if (g->section->output_section == obj_datasec(abfd)) {
1564         r_index = N_DATA | N_EXT;
1565         r_addend += g->section->output_section->vma;
1566       }
1567       else if (g->section->output_section == obj_bsssec(abfd)) {
1568         r_index = N_BSS | N_EXT ;
1569         r_addend += g->section->output_section->vma;
1570       }
1571       else {
1572         BFD_ASSERT(0);
1573       }
1574     }
1575
1576     /* now the fun stuff */
1577     if (abfd->xvec->header_byteorder_big_p != false) {
1578       natptr->r_index[0] = r_index >> 16;
1579       natptr->r_index[1] = r_index >> 8;
1580       natptr->r_index[2] = r_index;
1581       natptr->r_bits[0] =
1582         (r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
1583           || (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
1584     } else {
1585       natptr->r_index[2] = r_index >> 16;
1586       natptr->r_index[1] = r_index >> 8;
1587       natptr->r_index[0] = r_index;
1588       natptr->r_bits[0] =
1589         (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
1590           || (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
1591     }
1592
1593     bfd_h_putlong (abfd, r_addend, natptr->r_addend);
1594   }
1595 }
1596 #define MOVE_ADDRESS(ad)                                                \
1597   if (r_extern) {                                                       \
1598     cache_ptr->sym_ptr_ptr = symbols + r_index;                         \
1599     cache_ptr->section = (asection *)NULL;                              \
1600       cache_ptr->addend = ad;                                           \
1601   } else {                                                              \
1602     cache_ptr->sym_ptr_ptr = (asymbol **)NULL;                          \
1603     switch (r_index) {                                                  \
1604     case N_TEXT:                                                        \
1605     case N_TEXT | N_EXT:                                                \
1606       cache_ptr->section = obj_textsec(abfd);                           \
1607       cache_ptr->addend = ad  - su->textsec->vma;                       \
1608       break;                                                            \
1609     case N_DATA:                                                        \
1610     case N_DATA | N_EXT:                                                \
1611       cache_ptr->section = obj_datasec(abfd);                           \
1612       cache_ptr->addend = ad - su->datasec->vma;                        \
1613       break;                                                            \
1614     case N_BSS:                                                         \
1615     case N_BSS | N_EXT:                                                 \
1616       cache_ptr->section = obj_bsssec(abfd);                            \
1617       cache_ptr->addend = ad - su->bsssec->vma;                         \
1618       break;                                                            \
1619     case N_ABS:                                                         \
1620     case N_ABS | N_EXT:                                                 \
1621       BFD_ASSERT(1);                                                    \
1622       break;                                                            \
1623     default:                                                            \
1624       BFD_ASSERT(1);                                                    \
1625       break;                                                            \
1626     }                                                                   \
1627   }                                                                     \
1628
1629 void
1630 swap_ext_reloc_in (abfd, bytes, cache_ptr, symbols)
1631      bfd *abfd;
1632      struct reloc_ext_bytes *bytes;
1633      arelent *cache_ptr;
1634      asymbol **symbols;
1635 {
1636   int r_index;
1637   int r_extern;
1638   unsigned int r_type;
1639   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1640
1641   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1642
1643   /* now the fun stuff */
1644   if (abfd->xvec->header_byteorder_big_p != false) {
1645     r_index =  (bytes->r_index[0] << 16)
1646              | (bytes->r_index[1] << 8)
1647              |  bytes->r_index[2];
1648     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_BIG));
1649     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_BIG)
1650                                       >> RELOC_EXT_BITS_TYPE_SH_BIG;
1651   } else {
1652     r_index =  (bytes->r_index[2] << 16)
1653              | (bytes->r_index[1] << 8)
1654              |  bytes->r_index[0];
1655     r_extern = (0 != (bytes->r_bits[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
1656     r_type   =       (bytes->r_bits[0] & RELOC_EXT_BITS_TYPE_LITTLE)
1657                                       >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
1658   }
1659
1660   cache_ptr->howto =  howto_table_ext + r_type;
1661   MOVE_ADDRESS(bfd_h_getlong(abfd,bytes->r_addend));
1662                                                                          
1663 }
1664
1665 void
1666 swap_std_reloc_in (abfd, bytes, cache_ptr, symbols)
1667      bfd *abfd;
1668  struct reloc_std_bytes *bytes;
1669      arelent *cache_ptr;
1670      asymbol **symbols;
1671 {
1672   int r_index;
1673   int r_extern;
1674   unsigned int r_length;
1675   int r_pcrel;
1676   int r_baserel, r_jmptable, r_relative;
1677   struct sunexdata *su = (struct sunexdata *)(abfd->tdata);
1678   cache_ptr->address = bfd_h_getlong (abfd, bytes->r_address);
1679
1680   /* now the fun stuff */
1681   if (abfd->xvec->header_byteorder_big_p != false) {
1682     r_index =  (bytes->r_index[0] << 16)
1683       | (bytes->r_index[1] << 8)
1684         |  bytes->r_index[2];
1685     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_BIG));
1686     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_BIG));
1687     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_BIG));
1688     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_BIG));
1689     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_BIG));
1690     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_BIG) 
1691       >> RELOC_STD_BITS_LENGTH_SH_BIG;
1692   } else {
1693     r_index =  (bytes->r_index[2] << 16)
1694       | (bytes->r_index[1] << 8)
1695         |  bytes->r_index[0];
1696     r_extern  = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1697     r_pcrel   = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_PCREL_LITTLE));
1698     r_baserel = (0 != (bytes->r_bits[0] & RELOC_STD_BITS_BASEREL_LITTLE));
1699     r_jmptable= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
1700     r_relative= (0 != (bytes->r_bits[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
1701     r_length  =       (bytes->r_bits[0] & RELOC_STD_BITS_LENGTH_LITTLE) 
1702       >> RELOC_STD_BITS_LENGTH_SH_LITTLE;
1703   }
1704
1705   cache_ptr->howto =  howto_table_std + r_length + 4 * r_pcrel;
1706   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
1707
1708   MOVE_ADDRESS(0);
1709 }
1710
1711 /* Reloc hackery */
1712
1713 boolean
1714 sunos4_slurp_reloc_table (abfd, asect, symbols)
1715      bfd *abfd;
1716      sec_ptr asect;
1717      asymbol **symbols;
1718 {
1719   unsigned int count;
1720   size_t reloc_size;
1721   PTR relocs;
1722   arelent *reloc_cache;
1723   size_t each_size;
1724
1725   if (asect->relocation) return true;
1726
1727   if (asect->flags & SEC_CONSTRUCTOR) return true;
1728
1729   if (asect == obj_datasec (abfd)) {
1730     reloc_size = exec_hdr(abfd)->a_drsize;
1731     goto doit;
1732   }
1733
1734   if (asect == obj_textsec (abfd)) {
1735     reloc_size = exec_hdr(abfd)->a_trsize;
1736     goto doit;
1737   }
1738
1739   bfd_error = invalid_operation;
1740   return false;
1741
1742  doit:
1743   bfd_seek (abfd, asect->rel_filepos, SEEK_SET);
1744   each_size = reloc_size_func(abfd);
1745
1746   count = reloc_size / each_size;
1747
1748   relocs =  (PTR) malloc (reloc_size);
1749   if (!relocs) {
1750     bfd_error = no_memory;
1751     return false;
1752   }
1753   reloc_cache = (arelent *) zalloc ((size_t)(count * sizeof (arelent)));
1754   if (reloc_cache == (arelent *)NULL) {
1755     free (relocs);
1756     bfd_error = no_memory;
1757     return false;
1758   }
1759
1760   if (bfd_read ( relocs, 1, reloc_size, abfd) != reloc_size) {
1761     bfd_error = system_call_error;
1762     free (reloc_cache);
1763     free (relocs);
1764     return false;
1765   }
1766
1767   if (each_size == RELOC_EXT_SIZE)
1768     {
1769       register struct reloc_ext_bytes *rptr = (struct reloc_ext_bytes *) relocs;
1770       unsigned int counter = 0;
1771       arelent *cache_ptr = reloc_cache;
1772
1773       for (; counter < count; counter++, rptr++, cache_ptr++) {
1774         swap_ext_reloc_in(abfd, rptr, cache_ptr, symbols);
1775       }
1776     }
1777   else {
1778     register struct reloc_std_bytes *rptr = (struct reloc_std_bytes *) relocs;
1779     unsigned int counter = 0;
1780     arelent *cache_ptr = reloc_cache;
1781
1782     for (; counter < count; counter++, rptr++, cache_ptr++) {
1783         swap_std_reloc_in(abfd, rptr, cache_ptr, symbols);
1784     }
1785
1786   }
1787   free (relocs);
1788   asect->relocation = reloc_cache;
1789   asect->reloc_count = count;
1790   return true;
1791 }
1792
1793
1794
1795 /* Write out a relocation section into an object file.  */
1796
1797 static boolean
1798 sunos4_squirt_out_relocs (abfd, section)
1799      bfd *abfd;
1800      asection *section;
1801 {
1802   arelent **generic;
1803   unsigned char *native;
1804   size_t each_size;
1805
1806   unsigned int count = section->reloc_count;
1807   size_t natsize;
1808
1809   if (count == 0) return true;
1810
1811   each_size = reloc_size_func(abfd);
1812   natsize = each_size * count;
1813   native = (unsigned char *) zalloc (natsize);
1814   if (!native) {
1815     bfd_error = no_memory;
1816     return false;
1817   }
1818
1819   generic = section->orelocation;
1820
1821   if (each_size == RELOC_EXT_SIZE) 
1822     {
1823       swap_ext_reloc_out (abfd,
1824                           generic,
1825                           (struct reloc_ext_bytes *)native,
1826                           count);
1827     }
1828   else 
1829     {
1830       swap_std_reloc_out(abfd, generic, native, count);
1831     }
1832
1833   if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
1834     free(native);
1835     return false;
1836   }
1837   free (native);
1838
1839   return true;
1840 }
1841
1842 /* This is stupid.  This function should be a boolean predicate */
1843 unsigned int
1844 sunos4_canonicalize_reloc (abfd, section, relptr, symbols)
1845      bfd *abfd;
1846      sec_ptr section;
1847      arelent **relptr;
1848      asymbol **symbols;
1849 {
1850   arelent *tblptr = section->relocation;
1851   unsigned int count;
1852
1853   if (!(tblptr || sunos4_slurp_reloc_table (abfd, section, symbols)))
1854     return 0;
1855
1856   if (section->flags & SEC_CONSTRUCTOR) {
1857     arelent_chain *chain = section->constructor_chain;
1858     for (count = 0; count < section->reloc_count; count ++) {
1859       *relptr ++ = &chain->relent;
1860       chain = chain->next;
1861     }
1862   }
1863   else {
1864     tblptr = section->relocation;
1865     if (!tblptr) return 0;
1866
1867     for (count = 0; count++ < section->reloc_count;) 
1868       {
1869         *relptr++ = tblptr++;
1870       }
1871   }
1872   *relptr = 0;
1873
1874   return section->reloc_count;
1875 }
1876
1877 unsigned int
1878 sunos4_get_reloc_upper_bound (abfd, asect)
1879      bfd *abfd;
1880      sec_ptr asect;
1881 {
1882   if (bfd_get_format (abfd) != bfd_object) {
1883     bfd_error = invalid_operation;
1884     return 0;
1885   }
1886   if (asect->flags & SEC_CONSTRUCTOR) {
1887     return (sizeof (arelent *) * (asect->reloc_count+1));
1888   }
1889
1890
1891   if (asect == obj_datasec (abfd))
1892     return (sizeof (arelent *) *
1893             ((exec_hdr(abfd)->a_drsize / reloc_size_func(abfd))
1894              +1));
1895
1896   if (asect == obj_textsec (abfd))
1897     return (sizeof (arelent *) *
1898             ((exec_hdr(abfd)->a_trsize / reloc_size_func(abfd))
1899              +1));
1900
1901   bfd_error = invalid_operation;
1902   return 0;
1903 }
1904
1905 void
1906 sunos4_reclaim_reloc (ignore_abfd, section)
1907      bfd *ignore_abfd;
1908      sec_ptr section;
1909 {
1910   if (section->relocation) {
1911     free (section->relocation);
1912     section->relocation = NULL;
1913     section->reloc_count = 0;
1914     }
1915 }
1916 \f
1917
1918 alent *
1919 sunos4_get_lineno(ignore_abfd, ignore_symbol)
1920 bfd *ignore_abfd;
1921 generic_symbol_type *ignore_symbol;
1922 {
1923 return (alent *)NULL;
1924 }
1925
1926 void 
1927 sunos4_print_symbol(ignore_abfd, file,  symbol, how)
1928 bfd *ignore_abfd;
1929 FILE *file;
1930 asymbol *symbol;
1931 bfd_print_symbol_enum_type how;
1932 {
1933   switch (how) {
1934   case bfd_print_symbol_name_enum:
1935     fprintf(file,"%s", symbol->name);
1936     break;
1937   case bfd_print_symbol_type_enum:
1938     fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
1939             (unsigned)(   aout_symbol(symbol)->other  & 0xff),
1940             (unsigned)(aout_symbol(symbol)->type));
1941     break;
1942   case bfd_print_symbol_all_enum:
1943     {
1944    CONST char *section_name = symbol->section == (asection *)NULL ?
1945         "*abs" : symbol->section->name;
1946
1947       bfd_print_symbol_vandf((PTR)file,symbol);
1948
1949       fprintf(file," %-5s %04x %02x %02x %s",
1950               section_name,
1951               (unsigned)(aout_symbol(symbol)->desc & 0xffff),
1952               (unsigned)(aout_symbol(symbol)->other  & 0xff),
1953               (unsigned)(aout_symbol(symbol)->type  & 0xff),
1954               symbol->name);
1955     }
1956     break;
1957   }
1958 }
1959 /* Once we know all the stuff that could be consed, we know how to clean
1960    it up.  So why don't we? */
1961
1962 boolean
1963 sunos4_close_and_cleanup (abfd)
1964      bfd *abfd;
1965 {
1966   if (!bfd_read_p (abfd))
1967     switch (abfd->format) {
1968     case bfd_archive:
1969       if (!_bfd_write_archive_contents (abfd)) return false; break;
1970     case bfd_object:
1971       if (!sunos4_write_object_contents (abfd))  return false; break;
1972     default: bfd_error = invalid_operation; return false;
1973     }
1974
1975 #define cleaner(ptr) if (abfd->ptr) free (abfd->ptr)
1976   cleaner (tdata);
1977
1978   if (abfd->my_archive)
1979     cleaner (filename);
1980
1981 #undef cleaner
1982   return true;
1983 }
1984
1985 /* 
1986  provided a bfd, a section and an offset into the section, calculate
1987  and return the name of the source file and the line nearest to the
1988  wanted location.
1989 */
1990  
1991 boolean
1992 DEFUN(sunos4_find_nearest_line,(abfd,
1993                                 section,
1994                                 symbols,
1995                                 offset,
1996                                 filename_ptr,
1997                                 functionname_ptr,
1998                                 line_ptr),
1999       bfd *abfd AND
2000       asection *section AND
2001       asymbol **symbols AND
2002       bfd_vma offset AND
2003       CONST char **filename_ptr AND
2004       CONST char **functionname_ptr AND
2005       unsigned int *line_ptr)
2006 {
2007   /* Run down the file looking for the filename, function and linenumber */
2008   asymbol **p;
2009   static  char buffer[100];
2010   bfd_vma high_line_vma = ~0;
2011   bfd_vma low_func_vma = 0;
2012   asymbol *func = 0;
2013   *filename_ptr = abfd->filename;
2014   *functionname_ptr = 0;
2015   *line_ptr = 0;
2016   if (symbols != (asymbol **)NULL) {
2017     for (p = symbols; *p; p++) {
2018       aout_symbol_type  *q = (aout_symbol_type *)(*p);
2019       switch (q->type){
2020       case N_SO:
2021         *filename_ptr = q->symbol.name;
2022         if (obj_textsec(abfd) != section) {
2023           return true;
2024         }
2025         break;
2026       case N_SLINE:
2027
2028       case N_DSLINE:
2029       case N_BSLINE:
2030         /* We'll keep this if it resolves nearer than the one we have already */
2031         if (q->symbol.value >= offset &&
2032             q->symbol.value < high_line_vma) {
2033           *line_ptr = q->desc;
2034           high_line_vma = q->symbol.value;
2035         }
2036         break;
2037       case N_FUN:
2038         {
2039           /* We'll keep this if it is nearer than the one we have already */
2040           if (q->symbol.value >= low_func_vma &&
2041               q->symbol.value <= offset) {
2042             low_func_vma = q->symbol.value;
2043             func = (asymbol *)q;
2044           }
2045           if (*line_ptr && func) {
2046             CONST char *function = func->name;
2047             char *p;
2048             strncpy(buffer, function, sizeof(buffer)-1);
2049             buffer[sizeof(buffer)-1] = 0;
2050             /* Have to remove : stuff */
2051             p = strchr(buffer,':');
2052             if (p != NULL) {*p = NULL; }
2053             *functionname_ptr = buffer;
2054             return true;
2055
2056           }
2057         }
2058         break;
2059       }
2060     }
2061   }
2062   
2063   return true;
2064
2065 }
2066
2067 bfd_target aout_big_vec =
2068 {
2069   "a.out-generic-big",          /* name */
2070   bfd_target_aout_flavour_enum,
2071   true,                         /* target byte order */
2072   true,                         /* target headers byte order */
2073   (HAS_RELOC | EXEC_P |         /* object flags */
2074    HAS_LINENO | HAS_DEBUG |
2075    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
2076   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2077   0,                            /* valid reloc types */
2078   ' ',                          /* ar_pad_char */
2079   16,                           /* ar_max_namelen */
2080   sunos4_close_and_cleanup,     /* _close_and_cleanup */
2081   sunos4_set_section_contents,  /* bfd_set_section_contents */
2082   sunos4_get_section_contents,  /* bfd_get_section_contents */
2083   sunos4_new_section_hook,      /* new_section_hook */
2084   sunos4_core_file_failing_command, /* _core_file_failing_command */
2085   sunos4_core_file_failing_signal, /* _core_file_failing_signal */
2086   sunos4_core_file_matches_executable_p, /* _core_file_matches_ex...p */
2087
2088   bfd_slurp_bsd_armap,          /* bfd_slurp_armap */
2089   bfd_true,                     /* bfd_slurp_extended_name_table */
2090   bfd_bsd_truncate_arname,      /* bfd_truncate_arname */
2091
2092   sunos4_get_symtab_upper_bound, /* get_symtab_upper_bound */
2093   sunos4_get_symtab,            /* canonicalize_symtab */
2094   sunos4_reclaim_symbol_table,  /* bfd_reclaim_symbol_table */
2095   sunos4_get_reloc_upper_bound, /* get_reloc_upper_bound */
2096   sunos4_canonicalize_reloc,    /* bfd_canonicalize_reloc */
2097   sunos4_reclaim_reloc,         /* bfd_reclaim_reloc */
2098   sunos4_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
2099   sunos4_get_first_symbol,      /* bfd_get_first_symbol */
2100   sunos4_get_next_symbol,       /* bfd_get_next_symbol */
2101   sunos4_classify_symbol,       /* bfd_classify_symbol */
2102   sunos4_symbol_hasclass,       /* bfd_symbol_hasclass */
2103   sunos4_symbol_name,           /* bfd_symbol_name */
2104   sunos4_symbol_value,          /* bfd_symbol_value */
2105
2106   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */
2107   _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */
2108
2109   {_bfd_dummy_target, sunos4_object_p, /* bfd_check_format */
2110      bfd_generic_archive_p, sunos4_core_file_p},
2111   {bfd_false, sunos4_mkobject,  /* bfd_zxset_format */
2112      _bfd_generic_mkarchive, bfd_false},
2113   sunos4_make_empty_symbol,
2114   sunos4_print_symbol,
2115   sunos4_get_lineno,
2116   sunos4_set_arch_mach,
2117   bsd_write_armap,
2118   bfd_generic_openr_next_archived_file,
2119   sunos4_find_nearest_line,     /* bfd_find_nearest_line */
2120   bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
2121   };
2122
2123 bfd_target aout_little_vec =
2124 {
2125   "a.out-generic-little",               /* name */
2126   bfd_target_aout_flavour_enum,
2127   true,                         /* target byte order */
2128   true,                         /* target headers byte order */
2129   (HAS_RELOC | EXEC_P |         /* object flags */
2130    HAS_LINENO | HAS_DEBUG |
2131    HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
2132   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
2133   0,                            /* valid reloc types */
2134   ' ',                          /* ar_pad_char */
2135   16,                           /* ar_max_namelen */
2136   sunos4_close_and_cleanup,     /* _close_and_cleanup */
2137   sunos4_set_section_contents,  /* bfd_set_section_contents */
2138   sunos4_get_section_contents,  /* bfd_get_section_contents */
2139   sunos4_new_section_hook,      /* new_section_hook */
2140   sunos4_core_file_failing_command, /* _core_file_failing_command */
2141   sunos4_core_file_failing_signal, /* _core_file_failing_signal */
2142   sunos4_core_file_matches_executable_p, /* _core_file_matches_ex...p */
2143
2144   bfd_slurp_bsd_armap,          /* bfd_slurp_armap */
2145   bfd_true,                     /* bfd_slurp_extended_name_table */
2146   bfd_bsd_truncate_arname,      /* bfd_truncate_arname */
2147
2148   sunos4_get_symtab_upper_bound, /* get_symtab_upper_bound */
2149   sunos4_get_symtab,            /* canonicalize_symtab */
2150   sunos4_reclaim_symbol_table,  /* bfd_reclaim_symbol_table */
2151   sunos4_get_reloc_upper_bound, /* get_reloc_upper_bound */
2152   sunos4_canonicalize_reloc,    /* bfd_canonicalize_reloc */
2153   sunos4_reclaim_reloc,         /* bfd_reclaim_reloc */
2154   sunos4_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */
2155   sunos4_get_first_symbol,      /* bfd_get_first_symbol */
2156   sunos4_get_next_symbol,       /* bfd_get_next_symbol */
2157   sunos4_classify_symbol,       /* bfd_classify_symbol */
2158   sunos4_symbol_hasclass,       /* bfd_symbol_hasclass */
2159   sunos4_symbol_name,           /* bfd_symbol_name */
2160   sunos4_symbol_value,          /* bfd_symbol_value */
2161
2162   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */
2163   _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */
2164
2165   {_bfd_dummy_target, sunos4_object_p, /* bfd_check_format */
2166      bfd_generic_archive_p, sunos4_core_file_p},
2167   {bfd_false, sunos4_mkobject,  /* bfd_zxset_format */
2168      _bfd_generic_mkarchive, bfd_false},
2169   sunos4_make_empty_symbol,
2170   sunos4_print_symbol,
2171   sunos4_get_lineno,
2172   sunos4_set_arch_mach,
2173   bsd_write_armap,
2174   bfd_generic_openr_next_archived_file,
2175   sunos4_find_nearest_line,     /* bfd_find_nearest_line */
2176   bfd_generic_stat_arch_elt /* bfd_stat_arch_elt */
2177   };
2178