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