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