OSDN Git Service

2000-11-20 Kazu Hirata <kazu@hxi.com>
[pf3gnuchains/pf3gnuchains3x.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 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 /* Finish up the opening of a b.out file for reading.  Fill in all the
130    fields that are not handled by common code.  */
131
132 static const bfd_target *
133 aout_adobe_callback (abfd)
134      bfd *abfd;
135 {
136   struct internal_exec *execp = exec_hdr (abfd);
137   asection *sect;
138   struct external_segdesc ext[1];
139   char *section_name;
140   char try_again[30];   /* name and number */
141   char *newname;
142   int trynum;
143   flagword flags;
144
145   /* Architecture and machine type -- unknown in this format.  */
146   bfd_set_arch_mach(abfd, bfd_arch_unknown, 0);
147
148   /* The positions of the string table and symbol table.  */
149   obj_str_filepos (abfd) = N_STROFF (*execp);
150   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
151
152   /* Suck up the section information from the file, one section at a time.  */
153
154   for (;;) {
155     if (bfd_read ((PTR) ext, 1, sizeof (*ext), abfd) != sizeof (*ext)) {
156       if (bfd_get_error () != bfd_error_system_call)
157         bfd_set_error (bfd_error_wrong_format);
158       return 0;
159     }
160     switch (ext->e_type[0]) {
161     case N_TEXT:
162       section_name = ".text";
163       flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
164       break;
165
166     case N_DATA:
167       section_name = ".data";
168       flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
169       break;
170
171     case N_BSS:
172       section_name = ".bss";
173       flags = SEC_DATA | SEC_HAS_CONTENTS;
174       break;
175
176     case 0:
177       goto no_more_sections;
178
179     default:
180       (*_bfd_error_handler)
181         (_("%s: Unknown section type in a.out.adobe file: %x\n"),
182          bfd_get_filename (abfd), ext->e_type[0]);
183       goto no_more_sections;
184     }
185
186     /* First one is called ".text" or whatever; subsequent ones are
187        ".text1", ".text2", ...  */
188
189     bfd_set_error (bfd_error_no_error);
190     sect = bfd_make_section (abfd, section_name);
191     trynum = 0;
192     while (!sect) {
193       if (bfd_get_error () != bfd_error_no_error)
194         return 0;       /* Some other error -- slide into the sunset */
195       sprintf (try_again, "%s%d", section_name, ++trynum);
196       sect = bfd_make_section (abfd, try_again);
197     }
198
199     /* Fix the name, if it is a sprintf'd name.  */
200     if (sect->name == try_again) {
201       newname = (char *) bfd_zalloc(abfd, strlen (sect->name));
202       if (newname == NULL)
203         return 0;
204       strcpy (newname, sect->name);
205       sect->name = newname;
206     }
207
208     /* Now set the section's attributes.  */
209     bfd_set_section_flags (abfd, sect, flags);
210     sect->_raw_size = ((ext->e_size[0] << 8)    /* Assumed big-endian */
211                       | ext->e_size[1] << 8)
212                       | ext->e_size[2];
213     sect->_cooked_size = sect->_raw_size;
214     sect->vma = bfd_h_get_32 (abfd, ext->e_virtbase);
215     sect->filepos = bfd_h_get_32 (abfd, ext->e_filebase);
216     /* FIXME XXX alignment? */
217
218     /* Set relocation information for first section of each type.  */
219     if (trynum == 0) switch (ext->e_type[0]) {
220     case N_TEXT:
221       sect->rel_filepos = N_TRELOFF (*execp);
222       sect->reloc_count = execp->a_trsize;
223       break;
224
225     case N_DATA:
226       sect->rel_filepos = N_DRELOFF (*execp);
227       sect->reloc_count = execp->a_drsize;
228       break;
229     }
230   }
231 no_more_sections:
232
233   adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
234   adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
235   adata(abfd).page_size = 1; /* Not applicable.  */
236   adata(abfd).segment_size = 1; /* Not applicable.  */
237   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
238
239   return abfd->xvec;
240 }
241
242 struct bout_data_struct {
243     struct aoutdata a;
244     struct internal_exec e;
245 };
246
247 static boolean
248 aout_adobe_mkobject (abfd)
249      bfd *abfd;
250 {
251   struct bout_data_struct *rawptr;
252
253   rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
254   if (rawptr == NULL)
255       return false;
256
257   abfd->tdata.bout_data = rawptr;
258   exec_hdr (abfd) = &rawptr->e;
259
260   adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
261   adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
262   adata(abfd).page_size = 1; /* Not applicable.  */
263   adata(abfd).segment_size = 1; /* Not applicable.  */
264   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
265
266   return true;
267 }
268
269 static boolean
270 aout_adobe_write_object_contents (abfd)
271      bfd *abfd;
272 {
273   struct external_exec swapped_hdr;
274   static struct external_segdesc sentinel[1];   /* Initialized to zero */
275   asection *sect;
276
277   exec_hdr (abfd)->a_info = ZMAGIC;
278
279   /* Calculate text size as total of text sections, etc.  */
280
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     if (sect->flags & SEC_CODE) {
289       exec_hdr (abfd)->a_text += sect->_raw_size;
290       exec_hdr (abfd)->a_trsize += sect->reloc_count *
291                                    sizeof (struct reloc_std_external);
292     } else if (sect->flags & SEC_DATA)  {
293       exec_hdr (abfd)->a_data += sect->_raw_size;
294       exec_hdr (abfd)->a_drsize += sect->reloc_count *
295                                    sizeof (struct reloc_std_external);
296     } else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD)) {
297       exec_hdr (abfd)->a_bss  += sect->_raw_size;
298     }
299   }
300
301   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
302                                 * sizeof (struct external_nlist);
303   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
304
305   aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
306
307   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
308       || (bfd_write ((PTR) &swapped_hdr, 1, EXEC_BYTES_SIZE, abfd)
309           != EXEC_BYTES_SIZE))
310     return false;
311
312   /* Now write out the section information.  Text first, data next, rest
313      afterward.  */
314
315   for (sect = abfd->sections; sect; sect = sect->next) {
316     if (sect->flags & SEC_CODE) {
317       aout_adobe_write_section (abfd, sect);
318     }
319   }
320   for (sect = abfd->sections; sect; sect = sect->next) {
321     if (sect->flags & SEC_DATA) {
322       aout_adobe_write_section (abfd, sect);
323     }
324   }
325   for (sect = abfd->sections; sect; sect = sect->next) {
326     if (!(sect->flags & (SEC_CODE|SEC_DATA))) {
327       aout_adobe_write_section (abfd, sect);
328     }
329   }
330
331   /* Write final `sentinel` section header (with type of 0).  */
332   if (bfd_write ((PTR) sentinel, 1, sizeof (*sentinel), abfd)
333       != sizeof (*sentinel))
334     return false;
335
336   /* Now write out reloc info, followed by syms and strings */
337   if (bfd_get_symcount (abfd) != 0)
338     {
339       if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*exec_hdr(abfd))), SEEK_SET)
340           != 0)
341         return false;
342
343       if (! aout_32_write_syms (abfd))
344         return false;
345
346       if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*exec_hdr(abfd))), SEEK_SET)
347           != 0)
348         return false;
349
350       for (sect = abfd->sections; sect; sect = sect->next) {
351         if (sect->flags & SEC_CODE)     {
352           if (!aout_32_squirt_out_relocs (abfd, sect))
353             return false;
354         }
355       }
356
357       if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*exec_hdr(abfd))), SEEK_SET)
358           != 0)
359         return false;
360
361       for (sect = abfd->sections; sect; sect = sect->next) {
362         if (sect->flags & SEC_DATA)     {
363           if (!aout_32_squirt_out_relocs (abfd, sect))
364             return false;
365         }
366       }
367     }
368   return true;
369 }
370
371 static void
372 aout_adobe_write_section (abfd, sect)
373      bfd *abfd ATTRIBUTE_UNUSED;
374      sec_ptr sect ATTRIBUTE_UNUSED;
375 {
376   /* FIXME XXX */
377 }
378 \f
379 static boolean
380 aout_adobe_set_section_contents (abfd, section, location, offset, count)
381      bfd *abfd;
382      asection *section;
383      PTR location;
384      file_ptr offset;
385      bfd_size_type count;
386 {
387   file_ptr section_start;
388   sec_ptr sect;
389
390   if (abfd->output_has_begun == false) { /* set by bfd.c handler */
391
392     /* Assign file offsets to sections.  Text sections are first, and
393        are contiguous.  Then data sections.  Everything else at the end.  */
394
395     section_start = N_TXTOFF (ignore<-->me);
396
397     for (sect = abfd->sections; sect; sect = sect->next) {
398       if (sect->flags & SEC_CODE)       {
399         sect->filepos = section_start;
400         /* FIXME:  Round to alignment */
401         section_start += sect->_raw_size;
402       }
403     }
404
405     for (sect = abfd->sections; sect; sect = sect->next) {
406       if (sect->flags & SEC_DATA)       {
407         sect->filepos = section_start;
408         /* FIXME:  Round to alignment */
409         section_start += sect->_raw_size;
410       }
411     }
412
413     for (sect = abfd->sections; sect; sect = sect->next) {
414       if (sect->flags & SEC_HAS_CONTENTS &&
415           !(sect->flags & (SEC_CODE|SEC_DATA))) {
416         sect->filepos = section_start;
417         /* FIXME:  Round to alignment */
418         section_start += sect->_raw_size;
419       }
420     }
421   }
422
423   /* regardless, once we know what we're doing, we might as well get going */
424   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
425     return false;
426
427   if (count != 0) {
428     return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;
429   }
430   return true;
431 }
432
433 static boolean
434 aout_adobe_set_arch_mach (abfd, arch, machine)
435      bfd *abfd;
436      enum bfd_architecture arch;
437      unsigned long machine;
438 {
439   if (! bfd_default_set_arch_mach (abfd, arch, machine))
440     return false;
441
442   if (arch == bfd_arch_unknown
443       || arch == bfd_arch_m68k)
444     return true;
445
446   return false;
447 }
448
449 static int
450 aout_adobe_sizeof_headers (ignore_abfd, ignore)
451      bfd *ignore_abfd ATTRIBUTE_UNUSED;
452      boolean ignore ATTRIBUTE_UNUSED;
453 {
454   return sizeof (struct internal_exec);
455 }
456
457 /* Build the transfer vector for Adobe A.Out files.  */
458
459 #define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
460
461 #define aout_32_bfd_make_debug_symbol \
462   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
463
464 #define aout_32_bfd_reloc_type_lookup \
465   ((reloc_howto_type *(*) \
466     PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
467
468 #define aout_32_set_arch_mach           aout_adobe_set_arch_mach
469 #define aout_32_set_section_contents    aout_adobe_set_section_contents
470
471 #define aout_32_sizeof_headers          aout_adobe_sizeof_headers
472 #define aout_32_bfd_get_relocated_section_contents \
473   bfd_generic_get_relocated_section_contents
474 #define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
475 #define aout_32_bfd_relax_section       bfd_generic_relax_section
476 #define aout_32_bfd_gc_sections         bfd_generic_gc_sections
477 #define aout_32_bfd_link_hash_table_create \
478   _bfd_generic_link_hash_table_create
479 #define aout_32_bfd_link_add_symbols    _bfd_generic_link_add_symbols
480 #define aout_32_bfd_final_link          _bfd_generic_final_link
481 #define aout_32_bfd_link_split_section  _bfd_generic_link_split_section
482
483 const bfd_target a_out_adobe_vec =
484 {
485   "a.out.adobe",                /* name */
486   bfd_target_aout_flavour,
487   BFD_ENDIAN_BIG,               /* data byte order is unknown (big assumed) */
488   BFD_ENDIAN_BIG,               /* hdr byte order is big */
489   (HAS_RELOC | EXEC_P |         /* object flags */
490    HAS_LINENO | HAS_DEBUG |
491    HAS_SYMS | HAS_LOCALS | WP_TEXT ),
492   /* section flags */
493   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
494   '_',                          /*  symbol leading char */
495   ' ',                          /* ar_pad_char */
496   16,                           /* ar_max_namelen */
497
498   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
499      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
500      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
501   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
502      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
503      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
504  {_bfd_dummy_target, aout_adobe_object_p, /* bfd_check_format */
505    bfd_generic_archive_p, _bfd_dummy_target},
506  {bfd_false, aout_adobe_mkobject, /* bfd_set_format */
507    _bfd_generic_mkarchive, bfd_false},
508  {bfd_false, aout_adobe_write_object_contents, /* bfd_write_contents */
509    _bfd_write_archive_contents, bfd_false},
510
511      BFD_JUMP_TABLE_GENERIC (aout_32),
512      BFD_JUMP_TABLE_COPY (_bfd_generic),
513      BFD_JUMP_TABLE_CORE (_bfd_nocore),
514      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
515      BFD_JUMP_TABLE_SYMBOLS (aout_32),
516      BFD_JUMP_TABLE_RELOCS (aout_32),
517      BFD_JUMP_TABLE_WRITE (aout_32),
518      BFD_JUMP_TABLE_LINK (aout_32),
519      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
520
521   NULL,
522
523   (PTR) 0
524 };