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