19990502 sourceware import
[platform/upstream/binutils.git] / bfd / aout-adobe.c
1 /* BFD back-end for a.out.adobe binaries.
2    Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3    Written by Cygnus Support.  Based on bout.c.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program 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 2 of the License, or
10 (at your option) any later version.
11
12 This program 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 this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24
25 #include "aout/adobe.h"
26
27 #include "aout/stab_gnu.h"
28 #include "libaout.h"            /* BFD a.out internal data structures */
29
30 extern const bfd_target a_out_adobe_vec;                /* Forward decl */
31
32 static const bfd_target *aout_adobe_callback PARAMS ((bfd *));
33
34 extern boolean aout_32_slurp_symbol_table PARAMS ((bfd *abfd));
35 extern boolean aout_32_write_syms PARAMS ((bfd *));
36 static void aout_adobe_write_section PARAMS ((bfd *abfd, sec_ptr sect));
37
38 /* Swaps the information in an executable header taken from a raw byte
39    stream memory image, into the internal exec_header structure.  */
40
41 void aout_adobe_swap_exec_header_in
42   PARAMS ((bfd *abfd, struct external_exec *raw_bytes,
43            struct internal_exec *execp));
44          
45 void
46 aout_adobe_swap_exec_header_in (abfd, raw_bytes, execp)
47      bfd *abfd;
48      struct external_exec *raw_bytes;
49      struct internal_exec *execp;
50 {
51   struct external_exec *bytes = (struct external_exec *)raw_bytes;
52
53   /* Now fill in fields in the execp, from the bytes in the raw data.  */
54   execp->a_info   = bfd_h_get_32 (abfd, bytes->e_info);
55   execp->a_text   = GET_WORD (abfd, bytes->e_text);
56   execp->a_data   = GET_WORD (abfd, bytes->e_data);
57   execp->a_bss    = GET_WORD (abfd, bytes->e_bss);
58   execp->a_syms   = GET_WORD (abfd, bytes->e_syms);
59   execp->a_entry  = GET_WORD (abfd, bytes->e_entry);
60   execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
61   execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
62 }
63
64 /* Swaps the information in an internal exec header structure into the
65    supplied buffer ready for writing to disk.  */
66
67 PROTO(void, aout_adobe_swap_exec_header_out,
68           (bfd *abfd,
69            struct internal_exec *execp,
70            struct external_exec *raw_bytes));
71 void
72 aout_adobe_swap_exec_header_out (abfd, execp, raw_bytes)
73      bfd *abfd;
74      struct internal_exec *execp;
75      struct external_exec *raw_bytes;
76 {
77   struct external_exec *bytes = (struct external_exec *)raw_bytes;
78
79   /* Now fill in fields in the raw data, from the fields in the exec struct. */
80   bfd_h_put_32 (abfd, execp->a_info  , bytes->e_info);
81   PUT_WORD (abfd, execp->a_text  , bytes->e_text);
82   PUT_WORD (abfd, execp->a_data  , bytes->e_data);
83   PUT_WORD (abfd, execp->a_bss   , bytes->e_bss);
84   PUT_WORD (abfd, execp->a_syms  , bytes->e_syms);
85   PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
86   PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
87   PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
88 }
89
90
91 static const bfd_target *
92 aout_adobe_object_p (abfd)
93      bfd *abfd;
94 {
95   struct internal_exec anexec;
96   struct external_exec exec_bytes;
97   char *targ;
98
99   if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
100       != EXEC_BYTES_SIZE) {
101     if (bfd_get_error () != bfd_error_system_call)
102       bfd_set_error (bfd_error_wrong_format);
103     return 0;
104   }
105
106   anexec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info);
107
108   /* Normally we just compare for the magic number.
109      However, a bunch of Adobe tools aren't fixed up yet; they generate
110      files using ZMAGIC(!).
111      If the environment variable GNUTARGET is set to "a.out.adobe", we will
112      take just about any a.out file as an Adobe a.out file.  FIXME!  */
113
114   if (N_BADMAG (anexec)) {
115     targ = getenv ("GNUTARGET");
116     if (targ && !strcmp (targ, a_out_adobe_vec.name))
117       ;         /* Just continue anyway, if specifically set to this format */
118     else
119       {
120         bfd_set_error (bfd_error_wrong_format);
121         return 0;
122       }
123   }
124
125   aout_adobe_swap_exec_header_in (abfd, &exec_bytes, &anexec);
126   return aout_32_some_aout_object_p (abfd, &anexec, aout_adobe_callback);
127 }
128
129
130 /* Finish up the opening of a b.out file for reading.  Fill in all the
131    fields that are not handled by common code.  */
132
133 static const bfd_target *
134 aout_adobe_callback (abfd)
135      bfd *abfd;
136 {
137   struct internal_exec *execp = exec_hdr (abfd);
138   asection *sect;
139   struct external_segdesc ext[1];
140   char *section_name;
141   char try_again[30];   /* name and number */
142   char *newname;
143   int trynum;
144   flagword flags;
145
146   /* Architecture and machine type -- unknown in this format.  */
147   bfd_set_arch_mach(abfd, bfd_arch_unknown, 0);
148
149   /* The positions of the string table and symbol table.  */
150   obj_str_filepos (abfd) = N_STROFF (*execp);
151   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
152
153   /* Suck up the section information from the file, one section at a time.  */
154
155   for (;;) {
156     if (bfd_read ((PTR) ext, 1, sizeof (*ext), abfd) != sizeof (*ext)) {
157       if (bfd_get_error () != bfd_error_system_call)
158         bfd_set_error (bfd_error_wrong_format);
159       return 0;
160     }
161     switch (ext->e_type[0]) {
162     case N_TEXT:
163       section_name = ".text";
164       flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
165       break;
166
167     case N_DATA:
168       section_name = ".data";
169       flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
170       break;
171
172     case N_BSS:
173       section_name = ".bss";
174       flags = SEC_DATA | SEC_HAS_CONTENTS;
175       break;
176
177     case 0:
178       goto no_more_sections;
179
180     default:
181       (*_bfd_error_handler)
182         (_("%s: Unknown section type in a.out.adobe file: %x\n"), 
183          bfd_get_filename (abfd), ext->e_type[0]);
184       goto no_more_sections;
185     }
186
187     /* First one is called ".text" or whatever; subsequent ones are
188        ".text1", ".text2", ... */
189
190     bfd_set_error (bfd_error_no_error);
191     sect = bfd_make_section (abfd, section_name);
192     trynum = 0;
193     while (!sect) {
194       if (bfd_get_error () != bfd_error_no_error)
195         return 0;       /* Some other error -- slide into the sunset */
196       sprintf (try_again, "%s%d", section_name, ++trynum);
197       sect = bfd_make_section (abfd, try_again);
198     }
199
200     /* Fix the name, if it is a sprintf'd name.  */
201     if (sect->name == try_again) {
202       newname = (char *) bfd_zalloc(abfd, strlen (sect->name));
203       if (newname == NULL)
204         return 0;
205       strcpy (newname, sect->name);
206       sect->name = newname;
207     }
208
209     /* Now set the section's attributes.  */
210     bfd_set_section_flags (abfd, sect, flags);
211     sect->_raw_size = ((ext->e_size[0] << 8)    /* Assumed big-endian */
212                       | ext->e_size[1] << 8)
213                       | ext->e_size[2];
214     sect->_cooked_size = sect->_raw_size;
215     sect->vma = bfd_h_get_32 (abfd, ext->e_virtbase);
216     sect->filepos = bfd_h_get_32 (abfd, ext->e_filebase);
217     /* FIXME XXX alignment? */
218
219     /* Set relocation information for first section of each type.  */
220     if (trynum == 0) switch (ext->e_type[0]) {
221     case N_TEXT:
222       sect->rel_filepos = N_TRELOFF (*execp);
223       sect->reloc_count = execp->a_trsize;
224       break;
225
226     case N_DATA:
227       sect->rel_filepos = N_DRELOFF (*execp);
228       sect->reloc_count = execp->a_drsize;
229       break;
230     }
231   }
232 no_more_sections:  
233
234   adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
235   adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
236   adata(abfd).page_size = 1; /* Not applicable. */
237   adata(abfd).segment_size = 1; /* Not applicable. */
238   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
239
240   return abfd->xvec;
241 }
242
243 struct bout_data_struct {
244     struct aoutdata a;
245     struct internal_exec e;
246 };
247
248 static boolean
249 aout_adobe_mkobject (abfd)
250      bfd *abfd;
251 {
252   struct bout_data_struct *rawptr;
253
254   rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
255   if (rawptr == NULL)
256       return false;
257
258   abfd->tdata.bout_data = rawptr;
259   exec_hdr (abfd) = &rawptr->e;
260
261   adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
262   adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
263   adata(abfd).page_size = 1; /* Not applicable. */
264   adata(abfd).segment_size = 1; /* Not applicable. */
265   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
266
267   return true;
268 }
269
270
271 static boolean
272 aout_adobe_write_object_contents (abfd)
273      bfd *abfd;
274 {
275   struct external_exec swapped_hdr;
276   static struct external_segdesc sentinel[1];   /* Initialized to zero */
277   asection *sect;
278
279   exec_hdr (abfd)->a_info = ZMAGIC;
280
281   /* Calculate text size as total of text sections, etc. */
282
283   exec_hdr (abfd)->a_text = 0;
284   exec_hdr (abfd)->a_data = 0;
285   exec_hdr (abfd)->a_bss  = 0;
286   exec_hdr (abfd)->a_trsize = 0;
287   exec_hdr (abfd)->a_drsize = 0;
288
289   for (sect = abfd->sections; sect; sect = sect->next) {
290     if (sect->flags & SEC_CODE) {
291       exec_hdr (abfd)->a_text += sect->_raw_size;
292       exec_hdr (abfd)->a_trsize += sect->reloc_count *
293                                    sizeof (struct reloc_std_external);
294     } else if (sect->flags & SEC_DATA)  {
295       exec_hdr (abfd)->a_data += sect->_raw_size;
296       exec_hdr (abfd)->a_drsize += sect->reloc_count *
297                                    sizeof (struct reloc_std_external);
298     } else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD)) {
299       exec_hdr (abfd)->a_bss  += sect->_raw_size;
300     }
301   }
302
303   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
304                                 * sizeof (struct external_nlist);
305   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
306
307   aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
308
309   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
310       || (bfd_write ((PTR) &swapped_hdr, 1, EXEC_BYTES_SIZE, abfd)
311           != EXEC_BYTES_SIZE))
312     return false;
313
314   /* Now write out the section information.  Text first, data next, rest
315      afterward.  */
316
317   for (sect = abfd->sections; sect; sect = sect->next) {
318     if (sect->flags & SEC_CODE) {
319       aout_adobe_write_section (abfd, sect);
320     }
321   }
322   for (sect = abfd->sections; sect; sect = sect->next) {
323     if (sect->flags & SEC_DATA) {
324       aout_adobe_write_section (abfd, sect);
325     }
326   }
327   for (sect = abfd->sections; sect; sect = sect->next) {
328     if (!(sect->flags & (SEC_CODE|SEC_DATA))) {
329       aout_adobe_write_section (abfd, sect);
330     }
331   }
332
333   /* Write final `sentinel` section header (with type of 0).  */
334   if (bfd_write ((PTR) sentinel, 1, sizeof (*sentinel), abfd)
335       != sizeof (*sentinel))
336     return false;
337
338   /* Now write out reloc info, followed by syms and strings */
339   if (bfd_get_symcount (abfd) != 0) 
340     {
341       if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET)
342           != 0)
343         return false;
344
345       if (! aout_32_write_syms (abfd))
346         return false;
347
348       if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*exec_hdr(abfd))), SEEK_SET)
349           != 0)
350         return false;
351
352       for (sect = abfd->sections; sect; sect = sect->next) {
353         if (sect->flags & SEC_CODE)     {
354           if (!aout_32_squirt_out_relocs (abfd, sect))
355             return false;
356         }
357       }
358
359       if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*exec_hdr(abfd))), SEEK_SET)
360           != 0)
361         return false;
362
363       for (sect = abfd->sections; sect; sect = sect->next) {
364         if (sect->flags & SEC_DATA)     {
365           if (!aout_32_squirt_out_relocs (abfd, sect))
366             return false;
367         }
368       }
369     }
370   return true;
371 }
372
373 static void
374 aout_adobe_write_section (abfd, sect)
375      bfd *abfd;
376      sec_ptr sect;
377 {
378   /* FIXME XXX */
379 }
380 \f
381 static boolean
382 aout_adobe_set_section_contents (abfd, section, location, offset, count)
383      bfd *abfd;
384      asection *section;
385      PTR location;
386      file_ptr offset;
387      bfd_size_type count;
388 {
389   file_ptr section_start;
390   sec_ptr sect;
391
392   if (abfd->output_has_begun == false) { /* set by bfd.c handler */
393
394     /* Assign file offsets to sections.  Text sections are first, and
395        are contiguous.  Then data sections.  Everything else at the end.  */
396
397     section_start = N_TXTOFF (ignore<-->me);
398
399     for (sect = abfd->sections; sect; sect = sect->next) {
400       if (sect->flags & SEC_CODE)       {
401         sect->filepos = section_start;
402         /* FIXME:  Round to alignment */
403         section_start += sect->_raw_size;
404       }
405     }
406
407     for (sect = abfd->sections; sect; sect = sect->next) {
408       if (sect->flags & SEC_DATA)       {
409         sect->filepos = section_start;
410         /* FIXME:  Round to alignment */
411         section_start += sect->_raw_size;
412       }
413     }
414
415     for (sect = abfd->sections; sect; sect = sect->next) {
416       if (sect->flags & SEC_HAS_CONTENTS &&
417           !(sect->flags & (SEC_CODE|SEC_DATA))) {
418         sect->filepos = section_start;
419         /* FIXME:  Round to alignment */
420         section_start += sect->_raw_size;
421       }
422     }
423   }
424
425   /* regardless, once we know what we're doing, we might as well get going */
426   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
427     return false;
428
429   if (count != 0) {
430     return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;
431   }
432   return true;
433 }
434
435 static boolean
436 aout_adobe_set_arch_mach (abfd, arch, machine)
437      bfd *abfd;
438      enum bfd_architecture arch;
439      unsigned long machine;
440 {
441   if (! bfd_default_set_arch_mach (abfd, arch, machine))
442     return false;
443
444   if (arch == bfd_arch_unknown
445       || arch == bfd_arch_m68k)
446     return true;
447
448   return false;
449 }
450
451 static int 
452 aout_adobe_sizeof_headers (ignore_abfd, ignore)
453      bfd *ignore_abfd;
454      boolean ignore;
455 {
456   return sizeof(struct internal_exec);
457 }
458
459
460
461
462 /* Build the transfer vector for Adobe A.Out files.  */
463
464 #define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
465
466 #define aout_32_bfd_make_debug_symbol \
467   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
468
469 #define aout_32_bfd_reloc_type_lookup \
470   ((reloc_howto_type *(*) \
471     PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
472
473 #define aout_32_set_arch_mach           aout_adobe_set_arch_mach
474 #define aout_32_set_section_contents    aout_adobe_set_section_contents
475
476 #define aout_32_sizeof_headers          aout_adobe_sizeof_headers
477 #define aout_32_bfd_get_relocated_section_contents \
478   bfd_generic_get_relocated_section_contents
479 #define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
480 #define aout_32_bfd_relax_section       bfd_generic_relax_section
481 #define aout_32_bfd_gc_sections         bfd_generic_gc_sections
482 #define aout_32_bfd_link_hash_table_create \
483   _bfd_generic_link_hash_table_create
484 #define aout_32_bfd_link_add_symbols    _bfd_generic_link_add_symbols
485 #define aout_32_bfd_final_link          _bfd_generic_final_link
486 #define aout_32_bfd_link_split_section  _bfd_generic_link_split_section
487
488 const bfd_target a_out_adobe_vec =
489 {
490   "a.out.adobe",                /* name */
491   bfd_target_aout_flavour,
492   BFD_ENDIAN_BIG,               /* data byte order is unknown (big assumed) */
493   BFD_ENDIAN_BIG,               /* hdr byte order is big */
494   (HAS_RELOC | EXEC_P |         /* object flags */
495    HAS_LINENO | HAS_DEBUG |
496    HAS_SYMS | HAS_LOCALS | WP_TEXT ),
497   /* section flags */
498   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
499   '_',                          /*  symbol leading char */
500   ' ',                          /* ar_pad_char */
501   16,                           /* ar_max_namelen */
502
503   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
504      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
505      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
506   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
507      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
508      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
509  {_bfd_dummy_target, aout_adobe_object_p, /* bfd_check_format */
510    bfd_generic_archive_p, _bfd_dummy_target},
511  {bfd_false, aout_adobe_mkobject, /* bfd_set_format */
512    _bfd_generic_mkarchive, bfd_false},
513  {bfd_false, aout_adobe_write_object_contents, /* bfd_write_contents */
514    _bfd_write_archive_contents, bfd_false},
515
516      BFD_JUMP_TABLE_GENERIC (aout_32),
517      BFD_JUMP_TABLE_COPY (_bfd_generic),
518      BFD_JUMP_TABLE_CORE (_bfd_nocore),
519      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
520      BFD_JUMP_TABLE_SYMBOLS (aout_32),
521      BFD_JUMP_TABLE_RELOCS (aout_32),
522      BFD_JUMP_TABLE_WRITE (aout_32),
523      BFD_JUMP_TABLE_LINK (aout_32),
524      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
525
526   (PTR) 0
527 };