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