Upload Tizen:Base source
[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, 2006, 2007, 2009
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 3 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
22
23 #include "sysdep.h"
24 #include "bfd.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_with_flags (abfd, section_name, flags);
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_with_flags (abfd, try_again, flags);
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       /* Assumed big-endian.  */
159       sect->size = ((ext->e_size[0] << 8)
160                     | ext->e_size[1] << 8
161                     | ext->e_size[2]);
162       sect->vma = H_GET_32 (abfd, ext->e_virtbase);
163       sect->filepos = H_GET_32 (abfd, ext->e_filebase);
164       /* FIXME XXX alignment?  */
165
166       /* Set relocation information for first section of each type.  */
167       if (trynum == 0)
168         switch (ext->e_type[0])
169           {
170           case N_TEXT:
171             sect->rel_filepos = N_TRELOFF (*execp);
172             sect->reloc_count = execp->a_trsize;
173             break;
174
175           case N_DATA:
176             sect->rel_filepos = N_DRELOFF (*execp);
177             sect->reloc_count = execp->a_drsize;
178             break;
179
180           default:
181             break;
182           }
183     }
184  no_more_sections:
185
186   adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
187   adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
188   adata (abfd).page_size = 1; /* Not applicable.  */
189   adata (abfd).segment_size = 1; /* Not applicable.  */
190   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
191
192   return abfd->xvec;
193 }
194
195 static const bfd_target *
196 aout_adobe_object_p (bfd *abfd)
197 {
198   struct internal_exec anexec;
199   struct external_exec exec_bytes;
200   char *targ;
201   bfd_size_type amt = EXEC_BYTES_SIZE;
202
203   if (bfd_bread (& exec_bytes, amt, abfd) != amt)
204     {
205       if (bfd_get_error () != bfd_error_system_call)
206         bfd_set_error (bfd_error_wrong_format);
207       return NULL;
208     }
209
210   anexec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
211
212   /* Normally we just compare for the magic number.
213      However, a bunch of Adobe tools aren't fixed up yet; they generate
214      files using ZMAGIC(!).
215      If the environment variable GNUTARGET is set to "a.out.adobe", we will
216      take just about any a.out file as an Adobe a.out file.  FIXME!  */
217
218   if (N_BADMAG (anexec))
219     {
220       targ = getenv ("GNUTARGET");
221       if (targ && !strcmp (targ, a_out_adobe_vec.name))
222         /* Just continue anyway, if specifically set to this format.  */
223         ;
224       else
225         {
226           bfd_set_error (bfd_error_wrong_format);
227           return NULL;
228         }
229     }
230
231   aout_adobe_swap_exec_header_in (abfd, &exec_bytes, &anexec);
232   return aout_32_some_aout_object_p (abfd, &anexec, aout_adobe_callback);
233 }
234
235 struct bout_data_struct
236 {
237   struct aoutdata a;
238   struct internal_exec e;
239 };
240
241 static bfd_boolean
242 aout_adobe_mkobject (bfd *abfd)
243 {
244   struct bout_data_struct *rawptr;
245   bfd_size_type amt = sizeof (struct bout_data_struct);
246
247   rawptr = bfd_zalloc (abfd, amt);
248   if (rawptr == NULL)
249     return FALSE;
250
251   abfd->tdata.bout_data = rawptr;
252   exec_hdr (abfd) = &rawptr->e;
253
254   adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
255   adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
256   adata (abfd).page_size = 1; /* Not applicable.  */
257   adata (abfd).segment_size = 1; /* Not applicable.  */
258   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
259
260   return TRUE;
261 }
262
263 static void
264 aout_adobe_write_section (bfd *abfd ATTRIBUTE_UNUSED,
265                           sec_ptr sect ATTRIBUTE_UNUSED)
266 {
267   /* FIXME XXX.  */
268 }
269
270 static bfd_boolean
271 aout_adobe_write_object_contents (bfd *abfd)
272 {
273   struct external_exec swapped_hdr;
274   static struct external_segdesc sentinel[1];   /* Initialized to zero.  */
275   asection *sect;
276   bfd_size_type amt;
277
278   exec_hdr (abfd)->a_info = ZMAGIC;
279
280   /* Calculate text size as total of text sections, etc.  */
281   exec_hdr (abfd)->a_text = 0;
282   exec_hdr (abfd)->a_data = 0;
283   exec_hdr (abfd)->a_bss  = 0;
284   exec_hdr (abfd)->a_trsize = 0;
285   exec_hdr (abfd)->a_drsize = 0;
286
287   for (sect = abfd->sections; sect; sect = sect->next)
288     {
289       if (sect->flags & SEC_CODE)
290         {
291           exec_hdr (abfd)->a_text += sect->size;
292           exec_hdr (abfd)->a_trsize += sect->reloc_count *
293             sizeof (struct reloc_std_external);
294         }
295       else if (sect->flags & SEC_DATA)
296         {
297           exec_hdr (abfd)->a_data += sect->size;
298           exec_hdr (abfd)->a_drsize += sect->reloc_count *
299             sizeof (struct reloc_std_external);
300         }
301       else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD))
302         exec_hdr (abfd)->a_bss += sect->size;
303     }
304
305   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
306     * sizeof (struct external_nlist);
307   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
308
309   aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
310
311   amt = EXEC_BYTES_SIZE;
312   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
313       || bfd_bwrite (& swapped_hdr, amt, abfd) != amt)
314     return FALSE;
315
316   /* Now write out the section information.  Text first, data next, rest
317      afterward.  */
318   for (sect = abfd->sections; sect; sect = sect->next)
319     if (sect->flags & SEC_CODE)
320       aout_adobe_write_section (abfd, sect);
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   for (sect = abfd->sections; sect; sect = sect->next)
327     if (!(sect->flags & (SEC_CODE | SEC_DATA)))
328       aout_adobe_write_section (abfd, sect);
329
330   /* Write final `sentinel` section header (with type of 0).  */
331   amt = sizeof (*sentinel);
332   if (bfd_bwrite (sentinel, amt, abfd) != amt)
333     return FALSE;
334
335   /* Now write out reloc info, followed by syms and strings.  */
336   if (bfd_get_symcount (abfd) != 0)
337     {
338       if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
339           != 0)
340         return FALSE;
341
342       if (! aout_32_write_syms (abfd))
343         return FALSE;
344
345       if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*exec_hdr (abfd))), SEEK_SET)
346           != 0)
347         return FALSE;
348
349       for (sect = abfd->sections; sect; sect = sect->next)
350         if (sect->flags & SEC_CODE)
351           if (!aout_32_squirt_out_relocs (abfd, sect))
352             return FALSE;
353
354       if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*exec_hdr (abfd))), SEEK_SET)
355           != 0)
356         return FALSE;
357
358       for (sect = abfd->sections; sect; sect = sect->next)
359         if (sect->flags & SEC_DATA)
360           if (!aout_32_squirt_out_relocs (abfd, sect))
361             return FALSE;
362     }
363
364   return TRUE;
365 }
366 \f
367 static bfd_boolean
368 aout_adobe_set_section_contents (bfd *abfd,
369                                  asection *section,
370                                  const void * location,
371                                  file_ptr offset,
372                                  bfd_size_type count)
373 {
374   file_ptr section_start;
375   sec_ptr sect;
376
377   /* Set by bfd.c handler.  */
378   if (! abfd->output_has_begun)
379     {
380       /* Assign file offsets to sections.  Text sections are first, and
381          are contiguous.  Then data sections.  Everything else at the end.  */
382       section_start = N_TXTOFF (ignore<-->me);
383
384       for (sect = abfd->sections; sect; sect = sect->next)
385         {
386           if (sect->flags & SEC_CODE)
387             {
388               sect->filepos = section_start;
389               /* FIXME:  Round to alignment.  */
390               section_start += sect->size;
391             }
392         }
393
394       for (sect = abfd->sections; sect; sect = sect->next)
395         {
396           if (sect->flags & SEC_DATA)
397             {
398               sect->filepos = section_start;
399               /* FIXME:  Round to alignment.  */
400               section_start += sect->size;
401             }
402         }
403
404       for (sect = abfd->sections; sect; sect = sect->next)
405         {
406           if (sect->flags & SEC_HAS_CONTENTS &&
407               !(sect->flags & (SEC_CODE | SEC_DATA)))
408             {
409               sect->filepos = section_start;
410               /* FIXME:  Round to alignment.  */
411               section_start += sect->size;
412             }
413         }
414     }
415
416   /* Regardless, once we know what we're doing, we might as well get
417      going.  */
418   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
419     return FALSE;
420
421   if (count == 0)
422     return TRUE;
423
424   return bfd_bwrite (location, count, abfd) == count;
425 }
426
427 static bfd_boolean
428 aout_adobe_set_arch_mach (bfd *abfd,
429                           enum bfd_architecture arch,
430                           unsigned long machine)
431 {
432   if (! bfd_default_set_arch_mach (abfd, arch, machine))
433     return FALSE;
434
435   if (arch == bfd_arch_unknown
436       || arch == bfd_arch_m68k)
437     return TRUE;
438
439   return FALSE;
440 }
441
442 static int
443 aout_adobe_sizeof_headers (bfd *ignore_abfd ATTRIBUTE_UNUSED,
444                            struct bfd_link_info *info ATTRIBUTE_UNUSED)
445 {
446   return sizeof (struct internal_exec);
447 }
448
449 /* Build the transfer vector for Adobe A.Out files.  */
450
451 #define aout_32_bfd_make_debug_symbol ((asymbol *(*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
452 #define aout_32_bfd_reloc_type_lookup ((reloc_howto_type *(*) (bfd *, bfd_reloc_code_real_type)) bfd_nullvoidptr)
453 #define aout_32_bfd_reloc_name_lookup ((reloc_howto_type *(*) (bfd *, const char *)) bfd_nullvoidptr)
454 #define aout_32_close_and_cleanup                   aout_32_bfd_free_cached_info
455 #define aout_32_set_arch_mach                       aout_adobe_set_arch_mach
456 #define aout_32_set_section_contents                aout_adobe_set_section_contents
457 #define aout_32_sizeof_headers                      aout_adobe_sizeof_headers
458 #define aout_32_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
459 #define aout_32_get_section_contents_in_window      _bfd_generic_get_section_contents_in_window
460 #define aout_32_bfd_relax_section                   bfd_generic_relax_section
461 #define aout_32_bfd_gc_sections                     bfd_generic_gc_sections
462 #define aout_32_bfd_merge_sections                  bfd_generic_merge_sections
463 #define aout_32_bfd_is_group_section                bfd_generic_is_group_section
464 #define aout_32_bfd_discard_group                   bfd_generic_discard_group
465 #define aout_32_section_already_linked              _bfd_generic_section_already_linked
466 #define aout_32_bfd_define_common_symbol            bfd_generic_define_common_symbol
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_copy_link_hash_symbol_type \
472   _bfd_generic_copy_link_hash_symbol_type
473 #define aout_32_bfd_final_link                      _bfd_generic_final_link
474 #define aout_32_bfd_link_split_section              _bfd_generic_link_split_section
475
476 const bfd_target a_out_adobe_vec =
477 {
478   "a.out.adobe",                /* Name.  */
479   bfd_target_aout_flavour,
480   BFD_ENDIAN_BIG,               /* Data byte order is unknown (big assumed).  */
481   BFD_ENDIAN_BIG,               /* Header byte order is big.  */
482   (HAS_RELOC | EXEC_P |         /* Object flags.  */
483    HAS_LINENO | HAS_DEBUG |
484    HAS_SYMS | HAS_LOCALS | WP_TEXT ),
485   /* section flags */
486   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
487   '_',                          /* Symbol leading char.  */
488   ' ',                          /* AR_pad_char.  */
489   16,                           /* AR_max_namelen.  */
490
491   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
492   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
493   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
494   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
495   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
496   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
497
498   {_bfd_dummy_target, aout_adobe_object_p,      /* bfd_check_format.  */
499    bfd_generic_archive_p, _bfd_dummy_target},
500   {bfd_false, aout_adobe_mkobject,              /* bfd_set_format.  */
501    _bfd_generic_mkarchive, bfd_false},
502   {bfd_false, aout_adobe_write_object_contents,/* bfd_write_contents.  */
503    _bfd_write_archive_contents, bfd_false},
504
505   BFD_JUMP_TABLE_GENERIC (aout_32),
506   BFD_JUMP_TABLE_COPY (_bfd_generic),
507   BFD_JUMP_TABLE_CORE (_bfd_nocore),
508   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
509   BFD_JUMP_TABLE_SYMBOLS (aout_32),
510   BFD_JUMP_TABLE_RELOCS (aout_32),
511   BFD_JUMP_TABLE_WRITE (aout_32),
512   BFD_JUMP_TABLE_LINK (aout_32),
513   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
514
515   NULL,
516
517   NULL
518 };