Back to index

cell-binutils  2.17cvs20070401
binary.c
Go to the documentation of this file.
00001 /* BFD back-end for binary objects.
00002    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
00003    2004, 2005, 2006, 2007 Free Software Foundation, Inc.
00004    Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>
00005 
00006    This file is part of BFD, the Binary File Descriptor library.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /* This is a BFD backend which may be used to write binary objects.
00023    It may only be used for output, not input.  The intention is that
00024    this may be used as an output format for objcopy in order to
00025    generate raw binary data.
00026 
00027    This is very simple.  The only complication is that the real data
00028    will start at some address X, and in some cases we will not want to
00029    include X zeroes just to get to that point.  Since the start
00030    address is not meaningful for this object file format, we use it
00031    instead to indicate the number of zeroes to skip at the start of
00032    the file.  objcopy cooperates by specially setting the start
00033    address to zero by default.  */
00034 
00035 #include "bfd.h"
00036 #include "sysdep.h"
00037 #include "safe-ctype.h"
00038 #include "libbfd.h"
00039 
00040 /* Any bfd we create by reading a binary file has three symbols:
00041    a start symbol, an end symbol, and an absolute length symbol.  */
00042 #define BIN_SYMS 3
00043 
00044 /* Set by external programs - specifies the BFD architecture and
00045    machine number to be uses when creating binary BFDs.  */
00046 enum bfd_architecture  bfd_external_binary_architecture = bfd_arch_unknown;
00047 unsigned long          bfd_external_machine = 0;
00048 
00049 /* Create a binary object.  Invoked via bfd_set_format.  */
00050 
00051 static bfd_boolean
00052 binary_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
00053 {
00054   return TRUE;
00055 }
00056 
00057 /* Any file may be considered to be a binary file, provided the target
00058    was not defaulted.  That is, it must be explicitly specified as
00059    being binary.  */
00060 
00061 static const bfd_target *
00062 binary_object_p (bfd *abfd)
00063 {
00064   struct stat statbuf;
00065   asection *sec;
00066   flagword flags;
00067 
00068   if (abfd->target_defaulted)
00069     {
00070       bfd_set_error (bfd_error_wrong_format);
00071       return NULL;
00072     }
00073 
00074   abfd->symcount = BIN_SYMS;
00075 
00076   /* Find the file size.  */
00077   if (bfd_stat (abfd, &statbuf) < 0)
00078     {
00079       bfd_set_error (bfd_error_system_call);
00080       return NULL;
00081     }
00082 
00083   /* One data section.  */
00084   flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS;
00085   sec = bfd_make_section_with_flags (abfd, ".data", flags);
00086   if (sec == NULL)
00087     return NULL;
00088   sec->vma = 0;
00089   sec->size = statbuf.st_size;
00090   sec->filepos = 0;
00091 
00092   abfd->tdata.any = (void *) sec;
00093 
00094   if (bfd_get_arch_info (abfd) != NULL)
00095     {
00096       if ((bfd_get_arch_info (abfd)->arch == bfd_arch_unknown)
00097           && (bfd_external_binary_architecture != bfd_arch_unknown))
00098         bfd_set_arch_info (abfd, bfd_lookup_arch
00099                         (bfd_external_binary_architecture, bfd_external_machine));
00100     }
00101 
00102   return abfd->xvec;
00103 }
00104 
00105 #define binary_close_and_cleanup     _bfd_generic_close_and_cleanup
00106 #define binary_bfd_free_cached_info  _bfd_generic_bfd_free_cached_info
00107 #define binary_new_section_hook      _bfd_generic_new_section_hook
00108 
00109 /* Get contents of the only section.  */
00110 
00111 static bfd_boolean
00112 binary_get_section_contents (bfd *abfd,
00113                           asection *section ATTRIBUTE_UNUSED,
00114                           void * location,
00115                           file_ptr offset,
00116                           bfd_size_type count)
00117 {
00118   if (bfd_seek (abfd, offset, SEEK_SET) != 0
00119       || bfd_bread (location, count, abfd) != count)
00120     return FALSE;
00121   return TRUE;
00122 }
00123 
00124 /* Return the amount of memory needed to read the symbol table.  */
00125 
00126 static long
00127 binary_get_symtab_upper_bound (bfd *abfd ATTRIBUTE_UNUSED)
00128 {
00129   return (BIN_SYMS + 1) * sizeof (asymbol *);
00130 }
00131 
00132 /* Create a symbol name based on the bfd's filename.  */
00133 
00134 static char *
00135 mangle_name (bfd *abfd, char *suffix)
00136 {
00137   bfd_size_type size;
00138   char *buf;
00139   char *p;
00140 
00141   size = (strlen (bfd_get_filename (abfd))
00142          + strlen (suffix)
00143          + sizeof "_binary__");
00144 
00145   buf = bfd_alloc (abfd, size);
00146   if (buf == NULL)
00147     return "";
00148 
00149   sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix);
00150 
00151   /* Change any non-alphanumeric characters to underscores.  */
00152   for (p = buf; *p; p++)
00153     if (! ISALNUM (*p))
00154       *p = '_';
00155 
00156   return buf;
00157 }
00158 
00159 /* Return the symbol table.  */
00160 
00161 static long
00162 binary_canonicalize_symtab (bfd *abfd, asymbol **alocation)
00163 {
00164   asection *sec = (asection *) abfd->tdata.any;
00165   asymbol *syms;
00166   unsigned int i;
00167   bfd_size_type amt = BIN_SYMS * sizeof (asymbol);
00168 
00169   syms = bfd_alloc (abfd, amt);
00170   if (syms == NULL)
00171     return 0;
00172 
00173   /* Start symbol.  */
00174   syms[0].the_bfd = abfd;
00175   syms[0].name = mangle_name (abfd, "start");
00176   syms[0].value = 0;
00177   syms[0].flags = BSF_GLOBAL;
00178   syms[0].section = sec;
00179   syms[0].udata.p = NULL;
00180 
00181   /* End symbol.  */
00182   syms[1].the_bfd = abfd;
00183   syms[1].name = mangle_name (abfd, "end");
00184   syms[1].value = sec->size;
00185   syms[1].flags = BSF_GLOBAL;
00186   syms[1].section = sec;
00187   syms[1].udata.p = NULL;
00188 
00189   /* Size symbol.  */
00190   syms[2].the_bfd = abfd;
00191   syms[2].name = mangle_name (abfd, "size");
00192   syms[2].value = sec->size;
00193   syms[2].flags = BSF_GLOBAL;
00194   syms[2].section = bfd_abs_section_ptr;
00195   syms[2].udata.p = NULL;
00196 
00197   for (i = 0; i < BIN_SYMS; i++)
00198     *alocation++ = syms++;
00199   *alocation = NULL;
00200 
00201   return BIN_SYMS;
00202 }
00203 
00204 #define binary_make_empty_symbol  _bfd_generic_make_empty_symbol
00205 #define binary_print_symbol       _bfd_nosymbols_print_symbol
00206 
00207 /* Get information about a symbol.  */
00208 
00209 static void
00210 binary_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED,
00211                      asymbol *symbol,
00212                      symbol_info *ret)
00213 {
00214   bfd_symbol_info (symbol, ret);
00215 }
00216 
00217 #define binary_bfd_is_local_label_name      bfd_generic_is_local_label_name
00218 #define binary_get_lineno                  _bfd_nosymbols_get_lineno
00219 #define binary_find_nearest_line           _bfd_nosymbols_find_nearest_line
00220 #define binary_find_inliner_info           _bfd_nosymbols_find_inliner_info
00221 #define binary_bfd_make_debug_symbol       _bfd_nosymbols_bfd_make_debug_symbol
00222 #define binary_read_minisymbols            _bfd_generic_read_minisymbols
00223 #define binary_minisymbol_to_symbol        _bfd_generic_minisymbol_to_symbol
00224 #define binary_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
00225 
00226 /* Set the architecture of a binary file.  */
00227 #define binary_set_arch_mach _bfd_generic_set_arch_mach
00228 
00229 /* Write section contents of a binary file.  */
00230 
00231 static bfd_boolean
00232 binary_set_section_contents (bfd *abfd,
00233                           asection *sec,
00234                           const void * data,
00235                           file_ptr offset,
00236                           bfd_size_type size)
00237 {
00238   if (size == 0)
00239     return TRUE;
00240 
00241   if (! abfd->output_has_begun)
00242     {
00243       bfd_boolean found_low;
00244       bfd_vma low;
00245       asection *s;
00246 
00247       /* The lowest section LMA sets the virtual address of the start
00248          of the file.  We use this to set the file position of all the
00249          sections.  */
00250       found_low = FALSE;
00251       low = 0;
00252       for (s = abfd->sections; s != NULL; s = s->next)
00253        if (((s->flags
00254              & (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_NEVER_LOAD))
00255             == (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC))
00256            && (s->size > 0)
00257            && (! found_low || s->lma < low))
00258          {
00259            low = s->lma;
00260            found_low = TRUE;
00261          }
00262 
00263       for (s = abfd->sections; s != NULL; s = s->next)
00264        {
00265          s->filepos = s->lma - low;
00266 
00267          /* Skip following warning check for sections that will not
00268             occupy file space.  */
00269          if ((s->flags
00270               & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_NEVER_LOAD))
00271              != (SEC_HAS_CONTENTS | SEC_ALLOC)
00272              || (s->size == 0))
00273            continue;
00274 
00275          /* If attempting to generate a binary file from a bfd with
00276             LMA's all over the place, huge (sparse?) binary files may
00277             result.  This condition attempts to detect this situation
00278             and print a warning.  Better heuristics would be nice to
00279             have.  */
00280 
00281          if (s->filepos < 0)
00282            (*_bfd_error_handler)
00283              (_("Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx."),
00284               bfd_get_section_name (abfd, s),
00285               (unsigned long) s->filepos);
00286        }
00287 
00288       abfd->output_has_begun = TRUE;
00289     }
00290 
00291   /* We don't want to output anything for a section that is neither
00292      loaded nor allocated.  The contents of such a section are not
00293      meaningful in the binary format.  */
00294   if ((sec->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
00295     return TRUE;
00296   if ((sec->flags & SEC_NEVER_LOAD) != 0)
00297     return TRUE;
00298 
00299   return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
00300 }
00301 
00302 /* No space is required for header information.  */
00303 
00304 static int
00305 binary_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
00306                      struct bfd_link_info *info ATTRIBUTE_UNUSED)
00307 {
00308   return 0;
00309 }
00310 
00311 #define binary_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
00312 #define binary_bfd_relax_section                   bfd_generic_relax_section
00313 #define binary_bfd_gc_sections                     bfd_generic_gc_sections
00314 #define binary_bfd_merge_sections                  bfd_generic_merge_sections
00315 #define binary_bfd_is_group_section                bfd_generic_is_group_section
00316 #define binary_bfd_discard_group                   bfd_generic_discard_group
00317 #define binary_section_already_linked             _bfd_generic_section_already_linked
00318 #define binary_bfd_link_hash_table_create         _bfd_generic_link_hash_table_create
00319 #define binary_bfd_link_hash_table_free           _bfd_generic_link_hash_table_free
00320 #define binary_bfd_link_just_syms                 _bfd_generic_link_just_syms
00321 #define binary_bfd_link_add_symbols               _bfd_generic_link_add_symbols
00322 #define binary_bfd_final_link                     _bfd_generic_final_link
00323 #define binary_bfd_link_split_section             _bfd_generic_link_split_section
00324 #define binary_get_section_contents_in_window     _bfd_generic_get_section_contents_in_window
00325 
00326 const bfd_target binary_vec =
00327 {
00328   "binary",                 /* name */
00329   bfd_target_unknown_flavour,      /* flavour */
00330   BFD_ENDIAN_UNKNOWN,              /* byteorder */
00331   BFD_ENDIAN_UNKNOWN,              /* header_byteorder */
00332   EXEC_P,                   /* object_flags */
00333   (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
00334    | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
00335   0,                        /* symbol_leading_char */
00336   ' ',                      /* ar_pad_char */
00337   16,                       /* ar_max_namelen */
00338   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00339   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00340   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* data */
00341   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00342   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00343   bfd_getb16, bfd_getb_signed_16, bfd_putb16,    /* hdrs */
00344   {                         /* bfd_check_format */
00345     _bfd_dummy_target,
00346     binary_object_p,
00347     _bfd_dummy_target,
00348     _bfd_dummy_target,
00349   },
00350   {                         /* bfd_set_format */
00351     bfd_false,
00352     binary_mkobject,
00353     bfd_false,
00354     bfd_false,
00355   },
00356   {                         /* bfd_write_contents */
00357     bfd_false,
00358     bfd_true,
00359     bfd_false,
00360     bfd_false,
00361   },
00362 
00363   BFD_JUMP_TABLE_GENERIC (binary),
00364   BFD_JUMP_TABLE_COPY (_bfd_generic),
00365   BFD_JUMP_TABLE_CORE (_bfd_nocore),
00366   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
00367   BFD_JUMP_TABLE_SYMBOLS (binary),
00368   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
00369   BFD_JUMP_TABLE_WRITE (binary),
00370   BFD_JUMP_TABLE_LINK (binary),
00371   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00372 
00373   NULL,
00374 
00375   NULL
00376 };