Back to index

cell-binutils  2.17cvs20070401
aout-adobe.c
Go to the documentation of this file.
00001 /* BFD back-end for a.out.adobe binaries.
00002    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
00003    2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005    Written by Cygnus Support.  Based on bout.c.
00006 
00007    This file is part of BFD, the Binary File Descriptor library.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "libbfd.h"
00026 #include "aout/adobe.h"
00027 #include "aout/stab_gnu.h"
00028 #include "libaout.h"        /* BFD a.out internal data structures.  */
00029 
00030 /* Forward decl.  */
00031 extern const bfd_target a_out_adobe_vec;
00032 
00033 /* Swaps the information in an executable header taken from a raw byte
00034    stream memory image, into the internal exec_header structure.  */
00035 
00036 static void
00037 aout_adobe_swap_exec_header_in (bfd *abfd,
00038                             struct external_exec *bytes,
00039                             struct internal_exec *execp)
00040 {
00041   /* Now fill in fields in the execp, from the bytes in the raw data.  */
00042   execp->a_info   = H_GET_32 (abfd, bytes->e_info);
00043   execp->a_text   = GET_WORD (abfd, bytes->e_text);
00044   execp->a_data   = GET_WORD (abfd, bytes->e_data);
00045   execp->a_bss    = GET_WORD (abfd, bytes->e_bss);
00046   execp->a_syms   = GET_WORD (abfd, bytes->e_syms);
00047   execp->a_entry  = GET_WORD (abfd, bytes->e_entry);
00048   execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
00049   execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
00050 }
00051 
00052 /* Swaps the information in an internal exec header structure into the
00053    supplied buffer ready for writing to disk.  */
00054 
00055 static void
00056 aout_adobe_swap_exec_header_out (bfd *abfd,
00057                              struct internal_exec *execp,
00058                              struct external_exec *bytes)
00059 {
00060   /* Now fill in fields in the raw data, from the fields in the exec
00061      struct.  */
00062   H_PUT_32 (abfd, execp->a_info  , bytes->e_info);
00063   PUT_WORD (abfd, execp->a_text  , bytes->e_text);
00064   PUT_WORD (abfd, execp->a_data  , bytes->e_data);
00065   PUT_WORD (abfd, execp->a_bss   , bytes->e_bss);
00066   PUT_WORD (abfd, execp->a_syms  , bytes->e_syms);
00067   PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
00068   PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
00069   PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
00070 }
00071 
00072 /* Finish up the opening of a b.out file for reading.  Fill in all the
00073    fields that are not handled by common code.  */
00074 
00075 static const bfd_target *
00076 aout_adobe_callback (bfd *abfd)
00077 {
00078   struct internal_exec *execp = exec_hdr (abfd);
00079   asection *sect;
00080   struct external_segdesc ext[1];
00081   char *section_name;
00082   char try_again[30];       /* Name and number.  */
00083   char *newname;
00084   int trynum;
00085   flagword flags;
00086 
00087   /* Architecture and machine type -- unknown in this format.  */
00088   bfd_set_arch_mach (abfd, bfd_arch_unknown, 0L);
00089 
00090   /* The positions of the string table and symbol table.  */
00091   obj_str_filepos (abfd) = N_STROFF (*execp);
00092   obj_sym_filepos (abfd) = N_SYMOFF (*execp);
00093 
00094   /* Suck up the section information from the file, one section at a time.  */
00095   for (;;)
00096     {
00097       bfd_size_type amt = sizeof (*ext);
00098       if (bfd_bread ( ext, amt, abfd) != amt)
00099        {
00100          if (bfd_get_error () != bfd_error_system_call)
00101            bfd_set_error (bfd_error_wrong_format);
00102 
00103          return NULL;
00104        }
00105       switch (ext->e_type[0])
00106        {
00107        case N_TEXT:
00108          section_name = ".text";
00109          flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
00110          break;
00111 
00112        case N_DATA:
00113          section_name = ".data";
00114          flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
00115          break;
00116 
00117        case N_BSS:
00118          section_name = ".bss";
00119          flags = SEC_DATA | SEC_HAS_CONTENTS;
00120          break;
00121 
00122        case 0:
00123          goto no_more_sections;
00124 
00125        default:
00126          (*_bfd_error_handler)
00127            (_("%B: Unknown section type in a.out.adobe file: %x\n"),
00128             abfd, ext->e_type[0]);
00129          goto no_more_sections;
00130        }
00131 
00132       /* First one is called ".text" or whatever; subsequent ones are
00133         ".text1", ".text2", ...  */
00134       bfd_set_error (bfd_error_no_error);
00135       sect = bfd_make_section_with_flags (abfd, section_name, flags);
00136       trynum = 0;
00137 
00138       while (!sect)
00139        {
00140          if (bfd_get_error () != bfd_error_no_error)
00141            /* Some other error -- slide into the sunset.  */
00142            return NULL;
00143          sprintf (try_again, "%s%d", section_name, ++trynum);
00144          sect = bfd_make_section_with_flags (abfd, try_again, flags);
00145        }
00146 
00147       /* Fix the name, if it is a sprintf'd name.  */
00148       if (sect->name == try_again)
00149        {
00150          amt = strlen (sect->name);
00151          newname = bfd_zalloc (abfd, amt);
00152          if (newname == NULL)
00153            return NULL;
00154          strcpy (newname, sect->name);
00155          sect->name = newname;
00156        }
00157 
00158       /* Assumed big-endian.  */
00159       sect->size = ((ext->e_size[0] << 8)
00160                   | ext->e_size[1] << 8
00161                   | ext->e_size[2]);
00162       sect->vma = H_GET_32 (abfd, ext->e_virtbase);
00163       sect->filepos = H_GET_32 (abfd, ext->e_filebase);
00164       /* FIXME XXX alignment?  */
00165 
00166       /* Set relocation information for first section of each type.  */
00167       if (trynum == 0)
00168        switch (ext->e_type[0])
00169          {
00170          case N_TEXT:
00171            sect->rel_filepos = N_TRELOFF (*execp);
00172            sect->reloc_count = execp->a_trsize;
00173            break;
00174 
00175          case N_DATA:
00176            sect->rel_filepos = N_DRELOFF (*execp);
00177            sect->reloc_count = execp->a_drsize;
00178            break;
00179 
00180          default:
00181            break;
00182          }
00183     }
00184  no_more_sections:
00185 
00186   adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
00187   adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
00188   adata (abfd).page_size = 1; /* Not applicable.  */
00189   adata (abfd).segment_size = 1; /* Not applicable.  */
00190   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
00191 
00192   return abfd->xvec;
00193 }
00194 
00195 static const bfd_target *
00196 aout_adobe_object_p (bfd *abfd)
00197 {
00198   struct internal_exec anexec;
00199   struct external_exec exec_bytes;
00200   char *targ;
00201   bfd_size_type amt = EXEC_BYTES_SIZE;
00202 
00203   if (bfd_bread (& exec_bytes, amt, abfd) != amt)
00204     {
00205       if (bfd_get_error () != bfd_error_system_call)
00206        bfd_set_error (bfd_error_wrong_format);
00207       return NULL;
00208     }
00209 
00210   anexec.a_info = H_GET_32 (abfd, exec_bytes.e_info);
00211 
00212   /* Normally we just compare for the magic number.
00213      However, a bunch of Adobe tools aren't fixed up yet; they generate
00214      files using ZMAGIC(!).
00215      If the environment variable GNUTARGET is set to "a.out.adobe", we will
00216      take just about any a.out file as an Adobe a.out file.  FIXME!  */
00217 
00218   if (N_BADMAG (anexec))
00219     {
00220       targ = getenv ("GNUTARGET");
00221       if (targ && !strcmp (targ, a_out_adobe_vec.name))
00222        /* Just continue anyway, if specifically set to this format.  */
00223        ;
00224       else
00225        {
00226          bfd_set_error (bfd_error_wrong_format);
00227          return NULL;
00228        }
00229     }
00230 
00231   aout_adobe_swap_exec_header_in (abfd, &exec_bytes, &anexec);
00232   return aout_32_some_aout_object_p (abfd, &anexec, aout_adobe_callback);
00233 }
00234 
00235 struct bout_data_struct
00236 {
00237   struct aoutdata a;
00238   struct internal_exec e;
00239 };
00240 
00241 static bfd_boolean
00242 aout_adobe_mkobject (bfd *abfd)
00243 {
00244   struct bout_data_struct *rawptr;
00245   bfd_size_type amt = sizeof (struct bout_data_struct);
00246 
00247   rawptr = bfd_zalloc (abfd, amt);
00248   if (rawptr == NULL)
00249     return FALSE;
00250 
00251   abfd->tdata.bout_data = rawptr;
00252   exec_hdr (abfd) = &rawptr->e;
00253 
00254   adata (abfd).reloc_entry_size = sizeof (struct reloc_std_external);
00255   adata (abfd).symbol_entry_size = sizeof (struct external_nlist);
00256   adata (abfd).page_size = 1; /* Not applicable.  */
00257   adata (abfd).segment_size = 1; /* Not applicable.  */
00258   adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
00259 
00260   return TRUE;
00261 }
00262 
00263 static void
00264 aout_adobe_write_section (bfd *abfd ATTRIBUTE_UNUSED,
00265                        sec_ptr sect ATTRIBUTE_UNUSED)
00266 {
00267   /* FIXME XXX.  */
00268 }
00269 
00270 static bfd_boolean
00271 aout_adobe_write_object_contents (bfd *abfd)
00272 {
00273   struct external_exec swapped_hdr;
00274   static struct external_segdesc sentinel[1];    /* Initialized to zero.  */
00275   asection *sect;
00276   bfd_size_type amt;
00277 
00278   exec_hdr (abfd)->a_info = ZMAGIC;
00279 
00280   /* Calculate text size as total of text sections, etc.  */
00281   exec_hdr (abfd)->a_text = 0;
00282   exec_hdr (abfd)->a_data = 0;
00283   exec_hdr (abfd)->a_bss  = 0;
00284   exec_hdr (abfd)->a_trsize = 0;
00285   exec_hdr (abfd)->a_drsize = 0;
00286 
00287   for (sect = abfd->sections; sect; sect = sect->next)
00288     {
00289       if (sect->flags & SEC_CODE)
00290        {
00291          exec_hdr (abfd)->a_text += sect->size;
00292          exec_hdr (abfd)->a_trsize += sect->reloc_count *
00293            sizeof (struct reloc_std_external);
00294        }
00295       else if (sect->flags & SEC_DATA)
00296        {
00297          exec_hdr (abfd)->a_data += sect->size;
00298          exec_hdr (abfd)->a_drsize += sect->reloc_count *
00299            sizeof (struct reloc_std_external);
00300        }
00301       else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD))
00302        exec_hdr (abfd)->a_bss += sect->size;
00303     }
00304 
00305   exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
00306     * sizeof (struct external_nlist);
00307   exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
00308 
00309   aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
00310 
00311   amt = EXEC_BYTES_SIZE;
00312   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
00313       || bfd_bwrite (& swapped_hdr, amt, abfd) != amt)
00314     return FALSE;
00315 
00316   /* Now write out the section information.  Text first, data next, rest
00317      afterward.  */
00318   for (sect = abfd->sections; sect; sect = sect->next)
00319     if (sect->flags & SEC_CODE)
00320       aout_adobe_write_section (abfd, sect);
00321 
00322   for (sect = abfd->sections; sect; sect = sect->next)
00323     if (sect->flags & SEC_DATA)
00324       aout_adobe_write_section (abfd, sect);
00325 
00326   for (sect = abfd->sections; sect; sect = sect->next)
00327     if (!(sect->flags & (SEC_CODE | SEC_DATA)))
00328       aout_adobe_write_section (abfd, sect);
00329 
00330   /* Write final `sentinel` section header (with type of 0).  */
00331   amt = sizeof (*sentinel);
00332   if (bfd_bwrite (sentinel, amt, abfd) != amt)
00333     return FALSE;
00334 
00335   /* Now write out reloc info, followed by syms and strings.  */
00336   if (bfd_get_symcount (abfd) != 0)
00337     {
00338       if (bfd_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
00339          != 0)
00340        return FALSE;
00341 
00342       if (! aout_32_write_syms (abfd))
00343        return FALSE;
00344 
00345       if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*exec_hdr (abfd))), SEEK_SET)
00346          != 0)
00347        return FALSE;
00348 
00349       for (sect = abfd->sections; sect; sect = sect->next)
00350        if (sect->flags & SEC_CODE)
00351          if (!aout_32_squirt_out_relocs (abfd, sect))
00352            return FALSE;
00353 
00354       if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*exec_hdr (abfd))), SEEK_SET)
00355          != 0)
00356        return FALSE;
00357 
00358       for (sect = abfd->sections; sect; sect = sect->next)
00359        if (sect->flags & SEC_DATA)
00360          if (!aout_32_squirt_out_relocs (abfd, sect))
00361            return FALSE;
00362     }
00363 
00364   return TRUE;
00365 }
00366 
00367 static bfd_boolean
00368 aout_adobe_set_section_contents (bfd *abfd,
00369                              asection *section,
00370                              const void * location,
00371                              file_ptr offset,
00372                              bfd_size_type count)
00373 {
00374   file_ptr section_start;
00375   sec_ptr sect;
00376 
00377   /* Set by bfd.c handler.  */
00378   if (! abfd->output_has_begun)
00379     {
00380       /* Assign file offsets to sections.  Text sections are first, and
00381         are contiguous.  Then data sections.  Everything else at the end.  */
00382       section_start = N_TXTOFF (ignore<-->me);
00383 
00384       for (sect = abfd->sections; sect; sect = sect->next)
00385        {
00386          if (sect->flags & SEC_CODE)
00387            {
00388              sect->filepos = section_start;
00389              /* FIXME:  Round to alignment.  */
00390              section_start += sect->size;
00391            }
00392        }
00393 
00394       for (sect = abfd->sections; sect; sect = sect->next)
00395        {
00396          if (sect->flags & SEC_DATA)
00397            {
00398              sect->filepos = section_start;
00399              /* FIXME:  Round to alignment.  */
00400              section_start += sect->size;
00401            }
00402        }
00403 
00404       for (sect = abfd->sections; sect; sect = sect->next)
00405        {
00406          if (sect->flags & SEC_HAS_CONTENTS &&
00407              !(sect->flags & (SEC_CODE | SEC_DATA)))
00408            {
00409              sect->filepos = section_start;
00410              /* FIXME:  Round to alignment.  */
00411              section_start += sect->size;
00412            }
00413        }
00414     }
00415 
00416   /* Regardless, once we know what we're doing, we might as well get
00417      going.  */
00418   if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
00419     return FALSE;
00420 
00421   if (count == 0)
00422     return TRUE;
00423 
00424   return bfd_bwrite (location, count, abfd) == count;
00425 }
00426 
00427 static bfd_boolean
00428 aout_adobe_set_arch_mach (bfd *abfd,
00429                        enum bfd_architecture arch,
00430                        unsigned long machine)
00431 {
00432   if (! bfd_default_set_arch_mach (abfd, arch, machine))
00433     return FALSE;
00434 
00435   if (arch == bfd_arch_unknown
00436       || arch == bfd_arch_m68k)
00437     return TRUE;
00438 
00439   return FALSE;
00440 }
00441 
00442 static int
00443 aout_adobe_sizeof_headers (bfd *ignore_abfd ATTRIBUTE_UNUSED,
00444                         struct bfd_link_info *info ATTRIBUTE_UNUSED)
00445 {
00446   return sizeof (struct internal_exec);
00447 }
00448 
00449 /* Build the transfer vector for Adobe A.Out files.  */
00450 
00451 #define aout_32_bfd_make_debug_symbol ((asymbol *(*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
00452 #define aout_32_bfd_reloc_type_lookup ((reloc_howto_type *(*) (bfd *, bfd_reloc_code_real_type)) bfd_nullvoidptr)
00453 #define aout_32_bfd_reloc_name_lookup ((reloc_howto_type *(*) (bfd *, const char *)) bfd_nullvoidptr)
00454 #define aout_32_close_and_cleanup                   aout_32_bfd_free_cached_info
00455 #define       aout_32_set_arch_mach                          aout_adobe_set_arch_mach
00456 #define       aout_32_set_section_contents                   aout_adobe_set_section_contents
00457 #define       aout_32_sizeof_headers                         aout_adobe_sizeof_headers
00458 #define aout_32_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
00459 #define aout_32_get_section_contents_in_window      _bfd_generic_get_section_contents_in_window
00460 #define aout_32_bfd_relax_section                   bfd_generic_relax_section
00461 #define aout_32_bfd_gc_sections                     bfd_generic_gc_sections
00462 #define aout_32_bfd_merge_sections             bfd_generic_merge_sections
00463 #define aout_32_bfd_is_group_section                  bfd_generic_is_group_section
00464 #define aout_32_bfd_discard_group              bfd_generic_discard_group
00465 #define aout_32_section_already_linked              _bfd_generic_section_already_linked
00466 #define aout_32_bfd_link_hash_table_create          _bfd_generic_link_hash_table_create
00467 #define aout_32_bfd_link_hash_table_free            _bfd_generic_link_hash_table_free
00468 #define aout_32_bfd_link_add_symbols                  _bfd_generic_link_add_symbols
00469 #define aout_32_bfd_link_just_syms             _bfd_generic_link_just_syms
00470 #define aout_32_bfd_final_link                        _bfd_generic_final_link
00471 #define aout_32_bfd_link_split_section                _bfd_generic_link_split_section
00472 
00473 const bfd_target a_out_adobe_vec =
00474 {
00475   "a.out.adobe",            /* Name.  */
00476   bfd_target_aout_flavour,
00477   BFD_ENDIAN_BIG,           /* Data byte order is unknown (big assumed).  */
00478   BFD_ENDIAN_BIG,           /* Header byte order is big.  */
00479   (HAS_RELOC | EXEC_P |            /* Object flags.  */
00480    HAS_LINENO | HAS_DEBUG |
00481    HAS_SYMS | HAS_LOCALS | WP_TEXT ),
00482   /* section flags */
00483   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
00484   '_',                      /* Symbol leading char.  */
00485   ' ',                      /* AR_pad_char.  */
00486   16,                       /* AR_max_namelen.  */
00487 
00488   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00489   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00490   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* Data.  */
00491   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00492   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00493   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* Headers.  */
00494 
00495   {_bfd_dummy_target, aout_adobe_object_p,       /* bfd_check_format.  */
00496    bfd_generic_archive_p, _bfd_dummy_target},
00497   {bfd_false, aout_adobe_mkobject,        /* bfd_set_format.  */
00498    _bfd_generic_mkarchive, bfd_false},
00499   {bfd_false, aout_adobe_write_object_contents,/* bfd_write_contents.  */
00500    _bfd_write_archive_contents, bfd_false},
00501 
00502   BFD_JUMP_TABLE_GENERIC (aout_32),
00503   BFD_JUMP_TABLE_COPY (_bfd_generic),
00504   BFD_JUMP_TABLE_CORE (_bfd_nocore),
00505   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
00506   BFD_JUMP_TABLE_SYMBOLS (aout_32),
00507   BFD_JUMP_TABLE_RELOCS (aout_32),
00508   BFD_JUMP_TABLE_WRITE (aout_32),
00509   BFD_JUMP_TABLE_LINK (aout_32),
00510   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00511 
00512   NULL,
00513 
00514   NULL
00515 };