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