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