]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/aout-adobe.c
2000-11-27 Kazu Hirata <kazu@hxi.com>
[thirdparty/binutils-gdb.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 };