133965Sjdp/* BFD back-end for binary objects. 2218822Sdim Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 3218822Sdim 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 433965Sjdp Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com> 533965Sjdp 6130561Sobrien This file is part of BFD, the Binary File Descriptor library. 733965Sjdp 8130561Sobrien This program is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2 of the License, or 11130561Sobrien (at your option) any later version. 1233965Sjdp 13130561Sobrien This program is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 1733965Sjdp 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with this program; if not, write to the Free Software 20218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2133965Sjdp 2233965Sjdp/* This is a BFD backend which may be used to write binary objects. 2333965Sjdp It may only be used for output, not input. The intention is that 2433965Sjdp this may be used as an output format for objcopy in order to 2533965Sjdp generate raw binary data. 2633965Sjdp 2733965Sjdp This is very simple. The only complication is that the real data 2833965Sjdp will start at some address X, and in some cases we will not want to 2933965Sjdp include X zeroes just to get to that point. Since the start 3033965Sjdp address is not meaningful for this object file format, we use it 3133965Sjdp instead to indicate the number of zeroes to skip at the start of 3233965Sjdp the file. objcopy cooperates by specially setting the start 3333965Sjdp address to zero by default. */ 3433965Sjdp 35218822Sdim#include "sysdep.h" 3633965Sjdp#include "bfd.h" 3789857Sobrien#include "safe-ctype.h" 3833965Sjdp#include "libbfd.h" 3933965Sjdp 4033965Sjdp/* Any bfd we create by reading a binary file has three symbols: 4133965Sjdp a start symbol, an end symbol, and an absolute length symbol. */ 4233965Sjdp#define BIN_SYMS 3 4333965Sjdp 44130561Sobrien/* Set by external programs - specifies the BFD architecture and 45130561Sobrien machine number to be uses when creating binary BFDs. */ 46130561Sobrienenum bfd_architecture bfd_external_binary_architecture = bfd_arch_unknown; 47130561Sobrienunsigned long bfd_external_machine = 0; 4889857Sobrien 4933965Sjdp/* Create a binary object. Invoked via bfd_set_format. */ 5033965Sjdp 51130561Sobrienstatic bfd_boolean 52218822Sdimbinary_mkobject (bfd *abfd ATTRIBUTE_UNUSED) 5333965Sjdp{ 54130561Sobrien return TRUE; 5533965Sjdp} 5633965Sjdp 5733965Sjdp/* Any file may be considered to be a binary file, provided the target 5833965Sjdp was not defaulted. That is, it must be explicitly specified as 5933965Sjdp being binary. */ 6033965Sjdp 6133965Sjdpstatic const bfd_target * 62218822Sdimbinary_object_p (bfd *abfd) 6333965Sjdp{ 6433965Sjdp struct stat statbuf; 6533965Sjdp asection *sec; 66218822Sdim flagword flags; 6733965Sjdp 6833965Sjdp if (abfd->target_defaulted) 6933965Sjdp { 7033965Sjdp bfd_set_error (bfd_error_wrong_format); 7133965Sjdp return NULL; 7233965Sjdp } 7333965Sjdp 7433965Sjdp abfd->symcount = BIN_SYMS; 7533965Sjdp 7633965Sjdp /* Find the file size. */ 7733965Sjdp if (bfd_stat (abfd, &statbuf) < 0) 7833965Sjdp { 7933965Sjdp bfd_set_error (bfd_error_system_call); 8033965Sjdp return NULL; 8133965Sjdp } 8233965Sjdp 8333965Sjdp /* One data section. */ 84218822Sdim flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS; 85218822Sdim sec = bfd_make_section_with_flags (abfd, ".data", flags); 8633965Sjdp if (sec == NULL) 8733965Sjdp return NULL; 8833965Sjdp sec->vma = 0; 89218822Sdim sec->size = statbuf.st_size; 9033965Sjdp sec->filepos = 0; 9133965Sjdp 92218822Sdim abfd->tdata.any = (void *) sec; 9333965Sjdp 9489857Sobrien if (bfd_get_arch_info (abfd) != NULL) 9589857Sobrien { 9689857Sobrien if ((bfd_get_arch_info (abfd)->arch == bfd_arch_unknown) 9789857Sobrien && (bfd_external_binary_architecture != bfd_arch_unknown)) 98130561Sobrien bfd_set_arch_info (abfd, bfd_lookup_arch 99130561Sobrien (bfd_external_binary_architecture, bfd_external_machine)); 10089857Sobrien } 10189857Sobrien 10233965Sjdp return abfd->xvec; 10333965Sjdp} 10433965Sjdp 105218822Sdim#define binary_close_and_cleanup _bfd_generic_close_and_cleanup 106218822Sdim#define binary_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 107218822Sdim#define binary_new_section_hook _bfd_generic_new_section_hook 10833965Sjdp 10933965Sjdp/* Get contents of the only section. */ 11033965Sjdp 111130561Sobrienstatic bfd_boolean 112218822Sdimbinary_get_section_contents (bfd *abfd, 113218822Sdim asection *section ATTRIBUTE_UNUSED, 114218822Sdim void * location, 115218822Sdim file_ptr offset, 116218822Sdim bfd_size_type count) 11733965Sjdp{ 11833965Sjdp if (bfd_seek (abfd, offset, SEEK_SET) != 0 11989857Sobrien || bfd_bread (location, count, abfd) != count) 120130561Sobrien return FALSE; 121130561Sobrien return TRUE; 12233965Sjdp} 12333965Sjdp 12433965Sjdp/* Return the amount of memory needed to read the symbol table. */ 12533965Sjdp 12633965Sjdpstatic long 127218822Sdimbinary_get_symtab_upper_bound (bfd *abfd ATTRIBUTE_UNUSED) 12833965Sjdp{ 12933965Sjdp return (BIN_SYMS + 1) * sizeof (asymbol *); 13033965Sjdp} 13133965Sjdp 13233965Sjdp/* Create a symbol name based on the bfd's filename. */ 13333965Sjdp 13433965Sjdpstatic char * 135218822Sdimmangle_name (bfd *abfd, char *suffix) 13633965Sjdp{ 13789857Sobrien bfd_size_type size; 13833965Sjdp char *buf; 13933965Sjdp char *p; 14033965Sjdp 14133965Sjdp size = (strlen (bfd_get_filename (abfd)) 14233965Sjdp + strlen (suffix) 14333965Sjdp + sizeof "_binary__"); 14433965Sjdp 145218822Sdim buf = bfd_alloc (abfd, size); 14633965Sjdp if (buf == NULL) 14733965Sjdp return ""; 14833965Sjdp 14933965Sjdp sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix); 15033965Sjdp 15133965Sjdp /* Change any non-alphanumeric characters to underscores. */ 15233965Sjdp for (p = buf; *p; p++) 15389857Sobrien if (! ISALNUM (*p)) 15433965Sjdp *p = '_'; 15533965Sjdp 15633965Sjdp return buf; 15733965Sjdp} 15833965Sjdp 15933965Sjdp/* Return the symbol table. */ 16033965Sjdp 16133965Sjdpstatic long 162218822Sdimbinary_canonicalize_symtab (bfd *abfd, asymbol **alocation) 16333965Sjdp{ 16433965Sjdp asection *sec = (asection *) abfd->tdata.any; 16533965Sjdp asymbol *syms; 16633965Sjdp unsigned int i; 16789857Sobrien bfd_size_type amt = BIN_SYMS * sizeof (asymbol); 16833965Sjdp 169218822Sdim syms = bfd_alloc (abfd, amt); 17033965Sjdp if (syms == NULL) 171130561Sobrien return 0; 17233965Sjdp 17333965Sjdp /* Start symbol. */ 17433965Sjdp syms[0].the_bfd = abfd; 17533965Sjdp syms[0].name = mangle_name (abfd, "start"); 17633965Sjdp syms[0].value = 0; 17733965Sjdp syms[0].flags = BSF_GLOBAL; 17833965Sjdp syms[0].section = sec; 17933965Sjdp syms[0].udata.p = NULL; 18033965Sjdp 18133965Sjdp /* End symbol. */ 18233965Sjdp syms[1].the_bfd = abfd; 18333965Sjdp syms[1].name = mangle_name (abfd, "end"); 184218822Sdim syms[1].value = sec->size; 18533965Sjdp syms[1].flags = BSF_GLOBAL; 18633965Sjdp syms[1].section = sec; 18733965Sjdp syms[1].udata.p = NULL; 18833965Sjdp 18933965Sjdp /* Size symbol. */ 19033965Sjdp syms[2].the_bfd = abfd; 19133965Sjdp syms[2].name = mangle_name (abfd, "size"); 192218822Sdim syms[2].value = sec->size; 19333965Sjdp syms[2].flags = BSF_GLOBAL; 19433965Sjdp syms[2].section = bfd_abs_section_ptr; 19533965Sjdp syms[2].udata.p = NULL; 19633965Sjdp 19733965Sjdp for (i = 0; i < BIN_SYMS; i++) 19833965Sjdp *alocation++ = syms++; 19933965Sjdp *alocation = NULL; 20033965Sjdp 20133965Sjdp return BIN_SYMS; 20233965Sjdp} 20333965Sjdp 204218822Sdim#define binary_make_empty_symbol _bfd_generic_make_empty_symbol 205218822Sdim#define binary_print_symbol _bfd_nosymbols_print_symbol 20633965Sjdp 20733965Sjdp/* Get information about a symbol. */ 20833965Sjdp 20933965Sjdpstatic void 210218822Sdimbinary_get_symbol_info (bfd *ignore_abfd ATTRIBUTE_UNUSED, 211218822Sdim asymbol *symbol, 212218822Sdim symbol_info *ret) 21333965Sjdp{ 21433965Sjdp bfd_symbol_info (symbol, ret); 21533965Sjdp} 21633965Sjdp 217218822Sdim#define binary_bfd_is_local_label_name bfd_generic_is_local_label_name 218218822Sdim#define binary_get_lineno _bfd_nosymbols_get_lineno 219218822Sdim#define binary_find_nearest_line _bfd_nosymbols_find_nearest_line 220218822Sdim#define binary_find_inliner_info _bfd_nosymbols_find_inliner_info 221218822Sdim#define binary_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 222218822Sdim#define binary_read_minisymbols _bfd_generic_read_minisymbols 223218822Sdim#define binary_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 224218822Sdim#define binary_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) 22533965Sjdp 22633965Sjdp/* Set the architecture of a binary file. */ 22733965Sjdp#define binary_set_arch_mach _bfd_generic_set_arch_mach 22833965Sjdp 22933965Sjdp/* Write section contents of a binary file. */ 23033965Sjdp 231130561Sobrienstatic bfd_boolean 232218822Sdimbinary_set_section_contents (bfd *abfd, 233218822Sdim asection *sec, 234218822Sdim const void * data, 235218822Sdim file_ptr offset, 236218822Sdim bfd_size_type size) 23733965Sjdp{ 23877298Sobrien if (size == 0) 239130561Sobrien return TRUE; 24077298Sobrien 24133965Sjdp if (! abfd->output_has_begun) 24233965Sjdp { 243130561Sobrien bfd_boolean found_low; 24433965Sjdp bfd_vma low; 24533965Sjdp asection *s; 24633965Sjdp 24733965Sjdp /* The lowest section LMA sets the virtual address of the start 24833965Sjdp of the file. We use this to set the file position of all the 24933965Sjdp sections. */ 250130561Sobrien found_low = FALSE; 25133965Sjdp low = 0; 25233965Sjdp for (s = abfd->sections; s != NULL; s = s->next) 25360484Sobrien if (((s->flags 25460484Sobrien & (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_NEVER_LOAD)) 25533965Sjdp == (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC)) 256218822Sdim && (s->size > 0) 25733965Sjdp && (! found_low || s->lma < low)) 25833965Sjdp { 25933965Sjdp low = s->lma; 260130561Sobrien found_low = TRUE; 26133965Sjdp } 26233965Sjdp 26333965Sjdp for (s = abfd->sections; s != NULL; s = s->next) 26460484Sobrien { 26560484Sobrien s->filepos = s->lma - low; 26633965Sjdp 26760484Sobrien /* Skip following warning check for sections that will not 26877298Sobrien occupy file space. */ 26960484Sobrien if ((s->flags 27060484Sobrien & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_NEVER_LOAD)) 27177298Sobrien != (SEC_HAS_CONTENTS | SEC_ALLOC) 272218822Sdim || (s->size == 0)) 27360484Sobrien continue; 27460484Sobrien 27560484Sobrien /* If attempting to generate a binary file from a bfd with 27660484Sobrien LMA's all over the place, huge (sparse?) binary files may 27760484Sobrien result. This condition attempts to detect this situation 27860484Sobrien and print a warning. Better heuristics would be nice to 27977298Sobrien have. */ 28060484Sobrien 28160484Sobrien if (s->filepos < 0) 28260484Sobrien (*_bfd_error_handler) 28360484Sobrien (_("Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx."), 28460484Sobrien bfd_get_section_name (abfd, s), 28560484Sobrien (unsigned long) s->filepos); 28660484Sobrien } 28760484Sobrien 288130561Sobrien abfd->output_has_begun = TRUE; 28933965Sjdp } 29033965Sjdp 29160484Sobrien /* We don't want to output anything for a section that is neither 29260484Sobrien loaded nor allocated. The contents of such a section are not 29360484Sobrien meaningful in the binary format. */ 29460484Sobrien if ((sec->flags & (SEC_LOAD | SEC_ALLOC)) == 0) 295130561Sobrien return TRUE; 29660484Sobrien if ((sec->flags & SEC_NEVER_LOAD) != 0) 297130561Sobrien return TRUE; 29860484Sobrien 29933965Sjdp return _bfd_generic_set_section_contents (abfd, sec, data, offset, size); 30033965Sjdp} 30133965Sjdp 30233965Sjdp/* No space is required for header information. */ 30333965Sjdp 30433965Sjdpstatic int 305218822Sdimbinary_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, 306218822Sdim struct bfd_link_info *info ATTRIBUTE_UNUSED) 30733965Sjdp{ 30833965Sjdp return 0; 30933965Sjdp} 31033965Sjdp 311218822Sdim#define binary_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 312218822Sdim#define binary_bfd_relax_section bfd_generic_relax_section 313218822Sdim#define binary_bfd_gc_sections bfd_generic_gc_sections 314218822Sdim#define binary_bfd_merge_sections bfd_generic_merge_sections 315218822Sdim#define binary_bfd_is_group_section bfd_generic_is_group_section 316218822Sdim#define binary_bfd_discard_group bfd_generic_discard_group 317218822Sdim#define binary_section_already_linked _bfd_generic_section_already_linked 318218822Sdim#define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 319218822Sdim#define binary_bfd_link_hash_table_free _bfd_generic_link_hash_table_free 320218822Sdim#define binary_bfd_link_just_syms _bfd_generic_link_just_syms 321218822Sdim#define binary_bfd_link_add_symbols _bfd_generic_link_add_symbols 322218822Sdim#define binary_bfd_final_link _bfd_generic_final_link 323218822Sdim#define binary_bfd_link_split_section _bfd_generic_link_split_section 324218822Sdim#define binary_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 32533965Sjdp 32633965Sjdpconst bfd_target binary_vec = 32733965Sjdp{ 32833965Sjdp "binary", /* name */ 32933965Sjdp bfd_target_unknown_flavour, /* flavour */ 33033965Sjdp BFD_ENDIAN_UNKNOWN, /* byteorder */ 33133965Sjdp BFD_ENDIAN_UNKNOWN, /* header_byteorder */ 33233965Sjdp EXEC_P, /* object_flags */ 33333965Sjdp (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA 33433965Sjdp | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */ 33533965Sjdp 0, /* symbol_leading_char */ 33633965Sjdp ' ', /* ar_pad_char */ 33733965Sjdp 16, /* ar_max_namelen */ 33833965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 33933965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 34033965Sjdp bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ 34133965Sjdp bfd_getb64, bfd_getb_signed_64, bfd_putb64, 34233965Sjdp bfd_getb32, bfd_getb_signed_32, bfd_putb32, 34333965Sjdp bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ 34433965Sjdp { /* bfd_check_format */ 34533965Sjdp _bfd_dummy_target, 346218822Sdim binary_object_p, 34733965Sjdp _bfd_dummy_target, 34833965Sjdp _bfd_dummy_target, 34933965Sjdp }, 35033965Sjdp { /* bfd_set_format */ 35133965Sjdp bfd_false, 35233965Sjdp binary_mkobject, 35333965Sjdp bfd_false, 35433965Sjdp bfd_false, 35533965Sjdp }, 35633965Sjdp { /* bfd_write_contents */ 35733965Sjdp bfd_false, 35833965Sjdp bfd_true, 35933965Sjdp bfd_false, 36033965Sjdp bfd_false, 36133965Sjdp }, 36233965Sjdp 36333965Sjdp BFD_JUMP_TABLE_GENERIC (binary), 36433965Sjdp BFD_JUMP_TABLE_COPY (_bfd_generic), 36533965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 36633965Sjdp BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 36733965Sjdp BFD_JUMP_TABLE_SYMBOLS (binary), 368218822Sdim BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 36933965Sjdp BFD_JUMP_TABLE_WRITE (binary), 37033965Sjdp BFD_JUMP_TABLE_LINK (binary), 37133965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 37233965Sjdp 37360484Sobrien NULL, 37477298Sobrien 37533965Sjdp NULL 37633965Sjdp}; 377