Made sure that every call to bfd_read, bfd_write, and bfd_seek
[platform/upstream/binutils.git] / bfd / aout-adobe.c
1 /* BFD back-end for a.out.adobe binaries.
2    Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3    Written by Cygnus Support.  Based on bout.c.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24
25 #include "aout/adobe.h"
26
27 #include "aout/stab_gnu.h"
28 #include "libaout.h"            /* BFD a.out internal data structures */
29
30 extern bfd_target a_out_adobe_vec;              /* Forward decl */
31
32 PROTO (static bfd_target *, aout_adobe_callback, (bfd *));
33
34 PROTO (boolean, aout_32_slurp_symbol_table, (bfd *abfd));
35 PROTO (boolean , aout_32_write_syms, ());
36 PROTO (static void, aout_adobe_write_section, (bfd *abfd, sec_ptr sect));
37
38 /* Swaps the information in an executable header taken from a raw byte
39    stream memory image, into the internal exec_header structure.  */
40
41 PROTO(void, aout_adobe_swap_exec_header_in,
42       (bfd *abfd,
43       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 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     extern char *getenv ();
117
118     targ = getenv ("GNUTARGET");
119     if (targ && !strcmp (targ, a_out_adobe_vec.name))
120       ;         /* Just continue anyway, if specifically set to this format */
121     else
122       {
123         bfd_set_error (bfd_error_wrong_format);
124         return 0;
125       }
126   }
127
128   aout_adobe_swap_exec_header_in (abfd, &exec_bytes, &anexec);
129   return aout_32_some_aout_object_p (abfd, &anexec, aout_adobe_callback);
130 }
131
132
133 /* Finish up the opening of a b.out file for reading.  Fill in all the
134    fields that are not handled by common code.  */
135
136 static bfd_target *
137 aout_adobe_callback (abfd)
138      bfd *abfd;
139 {
140   struct internal_exec *execp = exec_hdr (abfd);
141   asection *sect;
142   struct external_segdesc ext[1];
143   char *section_name;
144   char try_again[30];   /* name and number */
145   char *newname;
146   int trynum;
147   flagword flags;
148
149   /* Architecture and machine type -- unknown in this format.  */
150   bfd_set_arch_mach(abfd, bfd_arch_unknown, 0);
151
152   /* The positions of the string table and symbol table.  */
153   obj_str_filepos (abfd) = N_STROFF (*execp);
154   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
155
156   /* Suck up the section information from the file, one section at a time.  */
157
158   for (;;) {
159     if (bfd_read ((PTR) ext, 1, sizeof (*ext), abfd) != sizeof (*ext)) {
160       if (bfd_get_error () != bfd_error_system_call)
161         bfd_set_error (bfd_error_wrong_format);
162       return 0;
163     }
164     switch (ext->e_type[0]) {
165     case N_TEXT:
166       section_name = ".text";
167       flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
168       break;
169
170     case N_DATA:
171       section_name = ".data";
172       flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
173       break;
174
175     case N_BSS:
176       section_name = ".bss";
177       flags = SEC_DATA | SEC_HAS_CONTENTS;
178       break;
179
180     case 0:
181       goto no_more_sections;
182
183     default:
184       fprintf (stderr, "Unknown section type in a.out.adobe file: %x\n", 
185                ext->e_type[0]);
186       goto no_more_sections;
187     }
188
189     /* First one is called ".text" or whatever; subsequent ones are
190        ".text1", ".text2", ... */
191
192     bfd_set_error (bfd_error_no_error);
193     sect = bfd_make_section (abfd, section_name);
194     trynum = 0;
195     while (!sect) {
196       if (bfd_get_error () != bfd_error_no_error)
197         return 0;       /* Some other error -- slide into the sunset */
198       sprintf (try_again, "%s%d", section_name, ++trynum);
199       sect = bfd_make_section (abfd, try_again);
200     }
201
202     /* Fix the name, if it is a sprintf'd name.  */
203     if (sect->name == try_again) {
204       newname = (char *) bfd_zalloc(abfd, strlen (sect->name));
205       if (newname == NULL) {
206         bfd_set_error (bfd_error_no_memory);
207         return 0;
208       }
209       strcpy (newname, sect->name);
210       sect->name = newname;
211     }
212
213     /* Now set the section's attributes.  */
214     bfd_set_section_flags (abfd, sect, flags);
215     sect->_raw_size = ((ext->e_size[0] << 8)    /* Assumed big-endian */
216                       | ext->e_size[1] << 8)
217                       | ext->e_size[2];
218     sect->_cooked_size = sect->_raw_size;
219     sect->vma = bfd_h_get_32 (abfd, ext->e_virtbase);
220     sect->filepos = bfd_h_get_32 (abfd, ext->e_filebase);
221     /* FIXME XXX alignment? */
222
223     /* Set relocation information for first section of each type.  */
224     if (trynum == 0) switch (ext->e_type[0]) {
225     case N_TEXT:
226       sect->rel_filepos = N_TRELOFF (*execp);
227       sect->reloc_count = execp->a_trsize;
228       break;
229
230     case N_DATA:
231       sect->rel_filepos = N_DRELOFF (*execp);
232       sect->reloc_count = execp->a_drsize;
233       break;
234     }
235   }
236 no_more_sections:  
237
238   adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
239   adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
240   adata(abfd).page_size = 1; /* Not applicable. */
241   adata(abfd).segment_size = 1; /* Not applicable. */
242   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
243
244   return abfd->xvec;
245 }
246
247 struct bout_data_struct {
248     struct aoutdata a;
249     struct internal_exec e;
250 };
251
252 static boolean
253 aout_adobe_mkobject (abfd)
254      bfd *abfd;
255 {
256   struct bout_data_struct *rawptr;
257
258   rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
259   if (rawptr == NULL) {
260       bfd_set_error (bfd_error_no_memory);
261       return false;
262     }
263
264   abfd->tdata.bout_data = rawptr;
265   exec_hdr (abfd) = &rawptr->e;
266
267   adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
268   adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
269   adata(abfd).page_size = 1; /* Not applicable. */
270   adata(abfd).segment_size = 1; /* Not applicable. */
271   adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
272
273   return true;
274 }
275
276
277 static boolean
278 aout_adobe_write_object_contents (abfd)
279      bfd *abfd;
280 {
281   struct external_exec swapped_hdr;
282   static struct external_segdesc sentinel[1];   /* Initialized to zero */
283   asection *sect;
284
285   exec_hdr (abfd)->a_info = ZMAGIC;
286
287   /* Calculate text size as total of text sections, etc. */
288
289   exec_hdr (abfd)->a_text = 0;
290   exec_hdr (abfd)->a_data = 0;
291   exec_hdr (abfd)->a_bss  = 0;
292   exec_hdr (abfd)->a_trsize = 0;
293   exec_hdr (abfd)->a_drsize = 0;
294
295   for (sect = abfd->sections; sect; sect = sect->next) {
296     if (sect->flags & SEC_CODE) {
297       exec_hdr (abfd)->a_text += sect->_raw_size;
298       exec_hdr (abfd)->a_trsize += sect->reloc_count *
299                                    sizeof (struct reloc_std_external);
300     } else if (sect->flags & SEC_DATA)  {
301       exec_hdr (abfd)->a_data += sect->_raw_size;
302       exec_hdr (abfd)->a_drsize += sect->reloc_count *
303                                    sizeof (struct reloc_std_external);
304     } else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD)) {
305       exec_hdr (abfd)->a_bss  += sect->_raw_size;
306     }
307   }
308
309   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
310                                 * sizeof (struct external_nlist);
311   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
312
313   aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
314
315   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
316       || (bfd_write ((PTR) &swapped_hdr, 1, EXEC_BYTES_SIZE, abfd)
317           != EXEC_BYTES_SIZE))
318     return false;
319
320   /* Now write out the section information.  Text first, data next, rest
321      afterward.  */
322
323   for (sect = abfd->sections; sect; sect = sect->next) {
324     if (sect->flags & SEC_CODE) {
325       aout_adobe_write_section (abfd, sect);
326     }
327   }
328   for (sect = abfd->sections; sect; sect = sect->next) {
329     if (sect->flags & SEC_DATA) {
330       aout_adobe_write_section (abfd, sect);
331     }
332   }
333   for (sect = abfd->sections; sect; sect = sect->next) {
334     if (!(sect->flags & (SEC_CODE|SEC_DATA))) {
335       aout_adobe_write_section (abfd, sect);
336     }
337   }
338
339   /* Write final `sentinel` section header (with type of 0).  */
340   if (bfd_write ((PTR) sentinel, 1, sizeof (*sentinel), abfd)
341       != sizeof (*sentinel))
342     return false;
343
344   /* Now write out reloc info, followed by syms and strings */
345   if (bfd_get_symcount (abfd) != 0) 
346     {
347       if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET)
348           != 0)
349         return false;
350
351       if (! aout_32_write_syms (abfd))
352         return false;
353
354       if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*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_CODE)     {
360           if (!aout_32_squirt_out_relocs (abfd, sect))
361             return false;
362         }
363       }
364
365       if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*exec_hdr(abfd))), SEEK_SET)
366           != 0)
367         return false;
368
369       for (sect = abfd->sections; sect; sect = sect->next) {
370         if (sect->flags & SEC_DATA)     {
371           if (!aout_32_squirt_out_relocs (abfd, sect))
372             return false;
373         }
374       }
375     }
376   return true;
377 }
378
379 static void
380 aout_adobe_write_section (abfd, sect)
381      bfd *abfd;
382      sec_ptr sect;
383 {
384   /* FIXME XXX */
385 }
386 \f
387 static boolean
388 aout_adobe_set_section_contents (abfd, section, location, offset, count)
389      bfd *abfd;
390      sec_ptr section;
391      unsigned char *location;
392      file_ptr offset;
393       int count;
394 {
395   file_ptr section_start;
396   sec_ptr sect;
397
398   if (abfd->output_has_begun == false) { /* set by bfd.c handler */
399
400     /* Assign file offsets to sections.  Text sections are first, and
401        are contiguous.  Then data sections.  Everything else at the end.  */
402
403     section_start = N_TXTOFF (ignore<-->me);
404
405     for (sect = abfd->sections; sect; sect = sect->next) {
406       if (sect->flags & SEC_CODE)       {
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_DATA)       {
415         sect->filepos = section_start;
416         /* FIXME:  Round to alignment */
417         section_start += sect->_raw_size;
418       }
419     }
420
421     for (sect = abfd->sections; sect; sect = sect->next) {
422       if (sect->flags & SEC_HAS_CONTENTS &&
423           !(sect->flags & (SEC_CODE|SEC_DATA))) {
424         sect->filepos = section_start;
425         /* FIXME:  Round to alignment */
426         section_start += sect->_raw_size;
427       }
428     }
429   }
430
431   /* regardless, once we know what we're doing, we might as well get going */
432   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
433     return false;
434
435   if (count != 0) {
436     return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;
437   }
438   return true;
439 }
440
441 static boolean
442 aout_adobe_set_arch_mach (abfd, arch, machine)
443      bfd *abfd;
444      enum bfd_architecture arch;
445      unsigned long machine;
446 {
447   bfd_default_set_arch_mach(abfd, arch, machine);
448
449   if (arch == bfd_arch_unknown) /* Unknown machine arch is OK */
450     return true;
451
452   return false;
453 }
454
455 static int 
456 aout_adobe_sizeof_headers (ignore_abfd, ignore)
457      bfd *ignore_abfd;
458      boolean ignore;
459 {
460   return sizeof(struct internal_exec);
461 }
462
463
464
465
466 /* Build the transfer vector for Adobe A.Out files.  */
467
468 /* We don't have core files.  */
469 #define aout_32_core_file_failing_command _bfd_dummy_core_file_failing_command
470 #define aout_32_core_file_failing_signal _bfd_dummy_core_file_failing_signal
471 #define aout_32_core_file_matches_executable_p  \
472                                 _bfd_dummy_core_file_matches_executable_p
473
474 /* We use BSD-Unix generic archive files.  */
475 #define aout_32_openr_next_archived_file        bfd_generic_openr_next_archived_file
476 #define aout_32_generic_stat_arch_elt   bfd_generic_stat_arch_elt
477 #define aout_32_slurp_armap             bfd_slurp_bsd_armap
478 #define aout_32_slurp_extended_name_table       bfd_true
479 #define aout_32_write_armap             bsd_write_armap
480 #define aout_32_truncate_arname         bfd_bsd_truncate_arname
481
482 /* We override these routines from the usual a.out file routines.  */
483 #define aout_32_set_section_contents    aout_adobe_set_section_contents
484 #define aout_32_set_arch_mach           aout_adobe_set_arch_mach
485 #define aout_32_sizeof_headers          aout_adobe_sizeof_headers
486
487 #define aout_32_bfd_debug_info_start            bfd_void
488 #define aout_32_bfd_debug_info_end              bfd_void
489 #define aout_32_bfd_debug_info_accumulate       (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
490
491 #define aout_32_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
492 #define aout_32_bfd_relax_section                   bfd_generic_relax_section
493 #define aout_32_bfd_reloc_type_lookup \
494   ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
495 #define aout_32_bfd_make_debug_symbol \
496   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
497 #define aout_32_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
498 #define aout_32_bfd_link_add_symbols _bfd_generic_link_add_symbols
499 #define aout_32_bfd_final_link _bfd_generic_final_link
500 #define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
501
502 bfd_target a_out_adobe_vec =
503 {
504   "a.out.adobe",                /* name */
505   bfd_target_aout_flavour,
506   true,                         /* data byte order is unknown (big assumed) */
507   true,                         /* hdr byte order is big */
508   (HAS_RELOC | EXEC_P |         /* object flags */
509    HAS_LINENO | HAS_DEBUG |
510    HAS_SYMS | HAS_LOCALS | WP_TEXT ),
511   /* section flags */
512   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
513   '_',                          /*  symbol leading char */
514   ' ',                          /* ar_pad_char */
515   16,                           /* ar_max_namelen */
516   2,                            /* minumum alignment power */
517
518   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
519      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
520      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
521   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
522      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
523      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
524  {_bfd_dummy_target, aout_adobe_object_p, /* bfd_check_format */
525    bfd_generic_archive_p, _bfd_dummy_target},
526  {bfd_false, aout_adobe_mkobject, /* bfd_set_format */
527    _bfd_generic_mkarchive, bfd_false},
528  {bfd_false, aout_adobe_write_object_contents, /* bfd_write_contents */
529    _bfd_write_archive_contents, bfd_false},
530
531   JUMP_TABLE(aout_32),
532   (PTR) 0
533 };