1 /* BFD back-end for a.out.adobe binaries.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
3    2002, 2003
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., 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.  */
33 extern const bfd_target a_out_adobe_vec;
34 
35 static const bfd_target *aout_adobe_callback
36   PARAMS ((bfd *));
37 extern bfd_boolean aout_32_slurp_symbol_table
38   PARAMS ((bfd *abfd));
39 extern bfd_boolean aout_32_write_syms
40   PARAMS ((bfd *));
41 static void aout_adobe_write_section
42   PARAMS ((bfd *abfd, sec_ptr sect));
43 static const bfd_target * aout_adobe_object_p
44   PARAMS ((bfd *));
45 static bfd_boolean aout_adobe_mkobject
46   PARAMS ((bfd *));
47 static bfd_boolean aout_adobe_write_object_contents
48   PARAMS ((bfd *));
49 static bfd_boolean aout_adobe_set_section_contents
50   PARAMS ((bfd *, asection *, const PTR, file_ptr, bfd_size_type));
51 static bfd_boolean aout_adobe_set_arch_mach
52   PARAMS ((bfd *, enum bfd_architecture, unsigned long));
53 static 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 
59 void aout_adobe_swap_exec_header_in
60   PARAMS ((bfd *, struct external_exec *, struct internal_exec *));
61 
62 void
aout_adobe_swap_exec_header_in(abfd,raw_bytes,execp)63 aout_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 
84 void aout_adobe_swap_exec_header_out
85   PARAMS ((bfd *, struct internal_exec *, struct external_exec *));
86 
87 void
aout_adobe_swap_exec_header_out(abfd,execp,raw_bytes)88 aout_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 
107 static const bfd_target *
aout_adobe_object_p(abfd)108 aout_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 
151 static const bfd_target *
aout_adobe_callback(abfd)152 aout_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 	    (_("%s: Unknown section type in a.out.adobe file: %x\n"),
205 	     bfd_archive_filename (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->_raw_size = ((ext->e_size[0] << 8)
239 			 | ext->e_size[1] << 8
240 			 | ext->e_size[2]);
241       sect->_cooked_size = sect->_raw_size;
242       sect->vma = H_GET_32 (abfd, ext->e_virtbase);
243       sect->filepos = H_GET_32 (abfd, ext->e_filebase);
244       /* FIXME XXX alignment?  */
245 
246       /* Set relocation information for first section of each type.  */
247       if (trynum == 0)
248 	switch (ext->e_type[0])
249 	  {
250 	  case N_TEXT:
251 	    sect->rel_filepos = N_TRELOFF (*execp);
252 	    sect->reloc_count = execp->a_trsize;
253 	    break;
254 
255 	  case N_DATA:
256 	    sect->rel_filepos = N_DRELOFF (*execp);
257 	    sect->reloc_count = execp->a_drsize;
258 	    break;
259 
260 	  default:
261 	    break;
262 	  }
263     }
264  no_more_sections:
265 
266   adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
267   adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
268   adata (abfd).page_size = 1; /* Not applicable.  */
269   adata (abfd).segment_size = 1; /* Not applicable.  */
270   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
271 
272   return abfd->xvec;
273 }
274 
275 struct bout_data_struct
276   {
277     struct aoutdata a;
278     struct internal_exec e;
279   };
280 
281 static bfd_boolean
aout_adobe_mkobject(abfd)282 aout_adobe_mkobject (abfd)
283      bfd *abfd;
284 {
285   struct bout_data_struct *rawptr;
286   bfd_size_type amt = sizeof (struct bout_data_struct);
287 
288   rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, amt);
289   if (rawptr == NULL)
290     return FALSE;
291 
292   abfd->tdata.bout_data = rawptr;
293   exec_hdr (abfd) = &rawptr->e;
294 
295   adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
296   adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
297   adata (abfd).page_size = 1; /* Not applicable.  */
298   adata (abfd).segment_size = 1; /* Not applicable.  */
299   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
300 
301   return TRUE;
302 }
303 
304 static bfd_boolean
aout_adobe_write_object_contents(abfd)305 aout_adobe_write_object_contents (abfd)
306      bfd *abfd;
307 {
308   struct external_exec swapped_hdr;
309   static struct external_segdesc sentinel[1];	/* Initialized to zero.  */
310   asection *sect;
311   bfd_size_type amt;
312 
313   exec_hdr (abfd)->a_info = ZMAGIC;
314 
315   /* Calculate text size as total of text sections, etc.  */
316 
317   exec_hdr (abfd)->a_text = 0;
318   exec_hdr (abfd)->a_data = 0;
319   exec_hdr (abfd)->a_bss  = 0;
320   exec_hdr (abfd)->a_trsize = 0;
321   exec_hdr (abfd)->a_drsize = 0;
322 
323   for (sect = abfd->sections; sect; sect = sect->next)
324     {
325       if (sect->flags & SEC_CODE)
326 	{
327 	  exec_hdr (abfd)->a_text += sect->_raw_size;
328 	  exec_hdr (abfd)->a_trsize += sect->reloc_count *
329 	    sizeof (struct reloc_std_external);
330 	}
331       else if (sect->flags & SEC_DATA)
332 	{
333 	  exec_hdr (abfd)->a_data += sect->_raw_size;
334 	  exec_hdr (abfd)->a_drsize += sect->reloc_count *
335 	    sizeof (struct reloc_std_external);
336 	}
337       else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD))
338 	{
339 	  exec_hdr (abfd)->a_bss += sect->_raw_size;
340 	}
341     }
342 
343   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
344     * sizeof (struct external_nlist);
345   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
346 
347   aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
348 
349   amt = EXEC_BYTES_SIZE;
350   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
351       || bfd_bwrite ((PTR) &swapped_hdr, amt, abfd) != amt)
352     return FALSE;
353 
354   /* Now write out the section information.  Text first, data next, rest
355      afterward.  */
356 
357   for (sect = abfd->sections; sect; sect = sect->next)
358     if (sect->flags & SEC_CODE)
359       aout_adobe_write_section (abfd, sect);
360 
361   for (sect = abfd->sections; sect; sect = sect->next)
362     if (sect->flags & SEC_DATA)
363       aout_adobe_write_section (abfd, sect);
364 
365   for (sect = abfd->sections; sect; sect = sect->next)
366     if (!(sect->flags & (SEC_CODE | SEC_DATA)))
367       aout_adobe_write_section (abfd, sect);
368 
369   /* Write final `sentinel` section header (with type of 0).  */
370   amt = sizeof (*sentinel);
371   if (bfd_bwrite ((PTR) sentinel, amt, abfd) != amt)
372     return FALSE;
373 
374   /* Now write out reloc info, followed by syms and strings.  */
375   if (bfd_get_symcount (abfd) != 0)
376     {
377       if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
378 	  != 0)
379 	return FALSE;
380 
381       if (! aout_32_write_syms (abfd))
382 	return FALSE;
383 
384       if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*exec_hdr (abfd))), SEEK_SET)
385 	  != 0)
386 	return FALSE;
387 
388       for (sect = abfd->sections; sect; sect = sect->next)
389 	if (sect->flags & SEC_CODE)
390 	  if (!aout_32_squirt_out_relocs (abfd, sect))
391 	    return FALSE;
392 
393       if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*exec_hdr (abfd))), SEEK_SET)
394 	  != 0)
395 	return FALSE;
396 
397       for (sect = abfd->sections; sect; sect = sect->next)
398 	if (sect->flags & SEC_DATA)
399 	  if (!aout_32_squirt_out_relocs (abfd, sect))
400 	    return FALSE;
401     }
402 
403   return TRUE;
404 }
405 
406 static void
aout_adobe_write_section(abfd,sect)407 aout_adobe_write_section (abfd, sect)
408      bfd *abfd ATTRIBUTE_UNUSED;
409      sec_ptr sect ATTRIBUTE_UNUSED;
410 {
411   /* FIXME XXX */
412 }
413 
414 static bfd_boolean
aout_adobe_set_section_contents(abfd,section,location,offset,count)415 aout_adobe_set_section_contents (abfd, section, location, offset, count)
416      bfd *abfd;
417      asection *section;
418      const PTR location;
419      file_ptr offset;
420      bfd_size_type count;
421 {
422   file_ptr section_start;
423   sec_ptr sect;
424 
425   /* Set by bfd.c handler.  */
426   if (! abfd->output_has_begun)
427     {
428       /* Assign file offsets to sections.  Text sections are first, and
429 	 are contiguous.  Then data sections.  Everything else at the end.  */
430       section_start = N_TXTOFF (ignore<-->me);
431 
432       for (sect = abfd->sections; sect; sect = sect->next)
433 	{
434 	  if (sect->flags & SEC_CODE)
435 	    {
436 	      sect->filepos = section_start;
437 	      /* FIXME:  Round to alignment.  */
438 	      section_start += sect->_raw_size;
439 	    }
440 	}
441 
442       for (sect = abfd->sections; sect; sect = sect->next)
443 	{
444 	  if (sect->flags & SEC_DATA)
445 	    {
446 	      sect->filepos = section_start;
447 	      /* FIXME:  Round to alignment.  */
448 	      section_start += sect->_raw_size;
449 	    }
450 	}
451 
452       for (sect = abfd->sections; sect; sect = sect->next)
453 	{
454 	  if (sect->flags & SEC_HAS_CONTENTS &&
455 	      !(sect->flags & (SEC_CODE | SEC_DATA)))
456 	    {
457 	      sect->filepos = section_start;
458 	      /* FIXME:  Round to alignment.  */
459 	      section_start += sect->_raw_size;
460 	    }
461 	}
462     }
463 
464   /* Regardless, once we know what we're doing, we might as well get
465      going.  */
466   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
467     return FALSE;
468 
469   if (count == 0)
470     return TRUE;
471 
472   return bfd_bwrite ((PTR) location, count, abfd) == count;
473 }
474 
475 static bfd_boolean
aout_adobe_set_arch_mach(abfd,arch,machine)476 aout_adobe_set_arch_mach (abfd, arch, machine)
477      bfd *abfd;
478      enum bfd_architecture arch;
479      unsigned long machine;
480 {
481   if (! bfd_default_set_arch_mach (abfd, arch, machine))
482     return FALSE;
483 
484   if (arch == bfd_arch_unknown
485       || arch == bfd_arch_m68k)
486     return TRUE;
487 
488   return FALSE;
489 }
490 
491 static int
aout_adobe_sizeof_headers(ignore_abfd,ignore)492 aout_adobe_sizeof_headers (ignore_abfd, ignore)
493      bfd *ignore_abfd ATTRIBUTE_UNUSED;
494      bfd_boolean ignore ATTRIBUTE_UNUSED;
495 {
496   return sizeof (struct internal_exec);
497 }
498 
499 /* Build the transfer vector for Adobe A.Out files.  */
500 
501 #define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
502 
503 #define aout_32_bfd_make_debug_symbol \
504   ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
505 
506 #define aout_32_bfd_reloc_type_lookup \
507   ((reloc_howto_type *(*) \
508     PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
509 
510 #define	aout_32_set_arch_mach		aout_adobe_set_arch_mach
511 #define	aout_32_set_section_contents	aout_adobe_set_section_contents
512 
513 #define	aout_32_sizeof_headers		aout_adobe_sizeof_headers
514 #define aout_32_bfd_get_relocated_section_contents \
515   bfd_generic_get_relocated_section_contents
516 #define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
517 #define aout_32_bfd_relax_section       bfd_generic_relax_section
518 #define aout_32_bfd_gc_sections         bfd_generic_gc_sections
519 #define aout_32_bfd_merge_sections	bfd_generic_merge_sections
520 #define aout_32_bfd_discard_group	bfd_generic_discard_group
521 #define aout_32_bfd_link_hash_table_create \
522   _bfd_generic_link_hash_table_create
523 #define aout_32_bfd_link_hash_table_free \
524   _bfd_generic_link_hash_table_free
525 #define aout_32_bfd_link_add_symbols	_bfd_generic_link_add_symbols
526 #define aout_32_bfd_link_just_syms	_bfd_generic_link_just_syms
527 #define aout_32_bfd_final_link		_bfd_generic_final_link
528 #define aout_32_bfd_link_split_section	_bfd_generic_link_split_section
529 
530 const bfd_target a_out_adobe_vec =
531   {
532     "a.out.adobe",		/* name */
533     bfd_target_aout_flavour,
534     BFD_ENDIAN_BIG,		/* data byte order is unknown (big assumed) */
535     BFD_ENDIAN_BIG,		/* hdr byte order is big */
536     (HAS_RELOC | EXEC_P |	/* object flags */
537      HAS_LINENO | HAS_DEBUG |
538      HAS_SYMS | HAS_LOCALS | WP_TEXT ),
539     /* section flags */
540     (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
541     '_',				/*  symbol leading char */
542     ' ',				/* ar_pad_char */
543     16,					/* ar_max_namelen */
544 
545     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
546     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
547     bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
548     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
549     bfd_getb32, bfd_getb_signed_32, bfd_putb32,
550     bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
551     {_bfd_dummy_target, aout_adobe_object_p,	/* bfd_check_format */
552      bfd_generic_archive_p, _bfd_dummy_target},
553     {bfd_false, aout_adobe_mkobject,		/* bfd_set_format */
554      _bfd_generic_mkarchive, bfd_false},
555     {bfd_false, aout_adobe_write_object_contents,/* bfd_write_contents */
556      _bfd_write_archive_contents, bfd_false},
557 
558     BFD_JUMP_TABLE_GENERIC (aout_32),
559     BFD_JUMP_TABLE_COPY (_bfd_generic),
560     BFD_JUMP_TABLE_CORE (_bfd_nocore),
561     BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
562     BFD_JUMP_TABLE_SYMBOLS (aout_32),
563     BFD_JUMP_TABLE_RELOCS (aout_32),
564     BFD_JUMP_TABLE_WRITE (aout_32),
565     BFD_JUMP_TABLE_LINK (aout_32),
566     BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
567 
568     NULL,
569 
570     (PTR) 0
571   };
572