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