1/* BFD back-end for binary objects.
2   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3   2004 Free Software Foundation, Inc.
4   Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>
5
6   This file is part of BFD, the Binary File Descriptor library.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22/* This is a BFD backend which may be used to write binary objects.
23   It may only be used for output, not input.  The intention is that
24   this may be used as an output format for objcopy in order to
25   generate raw binary data.
26
27   This is very simple.  The only complication is that the real data
28   will start at some address X, and in some cases we will not want to
29   include X zeroes just to get to that point.  Since the start
30   address is not meaningful for this object file format, we use it
31   instead to indicate the number of zeroes to skip at the start of
32   the file.  objcopy cooperates by specially setting the start
33   address to zero by default.  */
34
35#include "bfd.h"
36#include "sysdep.h"
37#include "safe-ctype.h"
38#include "libbfd.h"
39
40/* Any bfd we create by reading a binary file has three symbols:
41   a start symbol, an end symbol, and an absolute length symbol.  */
42#define BIN_SYMS 3
43
44static bfd_boolean binary_mkobject PARAMS ((bfd *));
45static const bfd_target *binary_object_p PARAMS ((bfd *));
46static bfd_boolean binary_get_section_contents
47  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
48static long binary_get_symtab_upper_bound PARAMS ((bfd *));
49static char *mangle_name PARAMS ((bfd *, char *));
50static long binary_canonicalize_symtab PARAMS ((bfd *, asymbol **));
51static void binary_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
52static bfd_boolean binary_set_section_contents
53  PARAMS ((bfd *, asection *, const PTR, file_ptr, bfd_size_type));
54static int binary_sizeof_headers PARAMS ((bfd *, bfd_boolean));
55
56/* Set by external programs - specifies the BFD architecture and
57   machine number to be uses when creating binary BFDs.  */
58enum bfd_architecture  bfd_external_binary_architecture = bfd_arch_unknown;
59unsigned long          bfd_external_machine = 0;
60
61/* Create a binary object.  Invoked via bfd_set_format.  */
62
63static bfd_boolean
64binary_mkobject (abfd)
65     bfd *abfd ATTRIBUTE_UNUSED;
66{
67  return TRUE;
68}
69
70/* Any file may be considered to be a binary file, provided the target
71   was not defaulted.  That is, it must be explicitly specified as
72   being binary.  */
73
74static const bfd_target *
75binary_object_p (abfd)
76     bfd *abfd;
77{
78  struct stat statbuf;
79  asection *sec;
80
81  if (abfd->target_defaulted)
82    {
83      bfd_set_error (bfd_error_wrong_format);
84      return NULL;
85    }
86
87  abfd->symcount = BIN_SYMS;
88
89  /* Find the file size.  */
90  if (bfd_stat (abfd, &statbuf) < 0)
91    {
92      bfd_set_error (bfd_error_system_call);
93      return NULL;
94    }
95
96  /* One data section.  */
97  sec = bfd_make_section (abfd, ".data");
98  if (sec == NULL)
99    return NULL;
100  sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS;
101  sec->vma = 0;
102  sec->size = statbuf.st_size;
103  sec->filepos = 0;
104
105  abfd->tdata.any = (PTR) sec;
106
107  if (bfd_get_arch_info (abfd) != NULL)
108    {
109      if ((bfd_get_arch_info (abfd)->arch == bfd_arch_unknown)
110          && (bfd_external_binary_architecture != bfd_arch_unknown))
111        bfd_set_arch_info (abfd, bfd_lookup_arch
112			   (bfd_external_binary_architecture, bfd_external_machine));
113    }
114
115  return abfd->xvec;
116}
117
118#define binary_close_and_cleanup _bfd_generic_close_and_cleanup
119#define binary_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
120#define binary_new_section_hook _bfd_generic_new_section_hook
121
122/* Get contents of the only section.  */
123
124static bfd_boolean
125binary_get_section_contents (abfd, section, location, offset, count)
126     bfd *abfd;
127     asection *section ATTRIBUTE_UNUSED;
128     PTR location;
129     file_ptr offset;
130     bfd_size_type count;
131{
132  if (bfd_seek (abfd, offset, SEEK_SET) != 0
133      || bfd_bread (location, count, abfd) != count)
134    return FALSE;
135  return TRUE;
136}
137
138/* Return the amount of memory needed to read the symbol table.  */
139
140static long
141binary_get_symtab_upper_bound (abfd)
142     bfd *abfd ATTRIBUTE_UNUSED;
143{
144  return (BIN_SYMS + 1) * sizeof (asymbol *);
145}
146
147/* Create a symbol name based on the bfd's filename.  */
148
149static char *
150mangle_name (abfd, suffix)
151     bfd *abfd;
152     char *suffix;
153{
154  bfd_size_type size;
155  char *buf;
156  char *p;
157
158  size = (strlen (bfd_get_filename (abfd))
159	  + strlen (suffix)
160	  + sizeof "_binary__");
161
162  buf = (char *) bfd_alloc (abfd, size);
163  if (buf == NULL)
164    return "";
165
166  sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix);
167
168  /* Change any non-alphanumeric characters to underscores.  */
169  for (p = buf; *p; p++)
170    if (! ISALNUM (*p))
171      *p = '_';
172
173  return buf;
174}
175
176/* Return the symbol table.  */
177
178static long
179binary_canonicalize_symtab (abfd, alocation)
180     bfd *abfd;
181     asymbol **alocation;
182{
183  asection *sec = (asection *) abfd->tdata.any;
184  asymbol *syms;
185  unsigned int i;
186  bfd_size_type amt = BIN_SYMS * sizeof (asymbol);
187
188  syms = (asymbol *) bfd_alloc (abfd, amt);
189  if (syms == NULL)
190    return 0;
191
192  /* Start symbol.  */
193  syms[0].the_bfd = abfd;
194  syms[0].name = mangle_name (abfd, "start");
195  syms[0].value = 0;
196  syms[0].flags = BSF_GLOBAL;
197  syms[0].section = sec;
198  syms[0].udata.p = NULL;
199
200  /* End symbol.  */
201  syms[1].the_bfd = abfd;
202  syms[1].name = mangle_name (abfd, "end");
203  syms[1].value = sec->size;
204  syms[1].flags = BSF_GLOBAL;
205  syms[1].section = sec;
206  syms[1].udata.p = NULL;
207
208  /* Size symbol.  */
209  syms[2].the_bfd = abfd;
210  syms[2].name = mangle_name (abfd, "size");
211  syms[2].value = sec->size;
212  syms[2].flags = BSF_GLOBAL;
213  syms[2].section = bfd_abs_section_ptr;
214  syms[2].udata.p = NULL;
215
216  for (i = 0; i < BIN_SYMS; i++)
217    *alocation++ = syms++;
218  *alocation = NULL;
219
220  return BIN_SYMS;
221}
222
223#define binary_make_empty_symbol _bfd_generic_make_empty_symbol
224#define binary_print_symbol _bfd_nosymbols_print_symbol
225
226/* Get information about a symbol.  */
227
228static void
229binary_get_symbol_info (ignore_abfd, symbol, ret)
230     bfd *ignore_abfd ATTRIBUTE_UNUSED;
231     asymbol *symbol;
232     symbol_info *ret;
233{
234  bfd_symbol_info (symbol, ret);
235}
236
237#define binary_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
238#define binary_bfd_is_local_label_name bfd_generic_is_local_label_name
239#define binary_get_lineno _bfd_nosymbols_get_lineno
240#define binary_find_nearest_line _bfd_nosymbols_find_nearest_line
241#define binary_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
242#define binary_read_minisymbols _bfd_generic_read_minisymbols
243#define binary_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
244
245#define binary_get_reloc_upper_bound \
246  ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
247#define binary_canonicalize_reloc \
248  ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
249#define binary_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
250
251/* Set the architecture of a binary file.  */
252#define binary_set_arch_mach _bfd_generic_set_arch_mach
253
254/* Write section contents of a binary file.  */
255
256static bfd_boolean
257binary_set_section_contents (abfd, sec, data, offset, size)
258     bfd *abfd;
259     asection *sec;
260     const PTR data;
261     file_ptr offset;
262     bfd_size_type size;
263{
264  if (size == 0)
265    return TRUE;
266
267  if (! abfd->output_has_begun)
268    {
269      bfd_boolean found_low;
270      bfd_vma low;
271      asection *s;
272
273      /* The lowest section LMA sets the virtual address of the start
274         of the file.  We use this to set the file position of all the
275         sections.  */
276      found_low = FALSE;
277      low = 0;
278      for (s = abfd->sections; s != NULL; s = s->next)
279	if (((s->flags
280	      & (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_NEVER_LOAD))
281	     == (SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC))
282	    && (s->size > 0)
283	    && (! found_low || s->lma < low))
284	  {
285	    low = s->lma;
286	    found_low = TRUE;
287	  }
288
289      for (s = abfd->sections; s != NULL; s = s->next)
290	{
291	  s->filepos = s->lma - low;
292
293	  /* Skip following warning check for sections that will not
294	     occupy file space.  */
295	  if ((s->flags
296	       & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_NEVER_LOAD))
297	      != (SEC_HAS_CONTENTS | SEC_ALLOC)
298	      || (s->size == 0))
299	    continue;
300
301	  /* If attempting to generate a binary file from a bfd with
302	     LMA's all over the place, huge (sparse?) binary files may
303	     result.  This condition attempts to detect this situation
304	     and print a warning.  Better heuristics would be nice to
305	     have.  */
306
307	  if (s->filepos < 0)
308	    (*_bfd_error_handler)
309	      (_("Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx."),
310	       bfd_get_section_name (abfd, s),
311	       (unsigned long) s->filepos);
312	}
313
314      abfd->output_has_begun = TRUE;
315    }
316
317  /* We don't want to output anything for a section that is neither
318     loaded nor allocated.  The contents of such a section are not
319     meaningful in the binary format.  */
320  if ((sec->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
321    return TRUE;
322  if ((sec->flags & SEC_NEVER_LOAD) != 0)
323    return TRUE;
324
325  return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
326}
327
328/* No space is required for header information.  */
329
330static int
331binary_sizeof_headers (abfd, exec)
332     bfd *abfd ATTRIBUTE_UNUSED;
333     bfd_boolean exec ATTRIBUTE_UNUSED;
334{
335  return 0;
336}
337
338#define binary_bfd_get_relocated_section_contents \
339  bfd_generic_get_relocated_section_contents
340#define binary_bfd_relax_section bfd_generic_relax_section
341#define binary_bfd_gc_sections bfd_generic_gc_sections
342#define binary_bfd_merge_sections bfd_generic_merge_sections
343#define binary_bfd_is_group_section bfd_generic_is_group_section
344#define binary_bfd_discard_group bfd_generic_discard_group
345#define binary_section_already_linked \
346  _bfd_generic_section_already_linked
347#define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
348#define binary_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
349#define binary_bfd_link_just_syms _bfd_generic_link_just_syms
350#define binary_bfd_link_add_symbols _bfd_generic_link_add_symbols
351#define binary_bfd_final_link _bfd_generic_final_link
352#define binary_bfd_link_split_section _bfd_generic_link_split_section
353#define binary_get_section_contents_in_window \
354  _bfd_generic_get_section_contents_in_window
355
356const bfd_target binary_vec =
357{
358  "binary",			/* name */
359  bfd_target_unknown_flavour,	/* flavour */
360  BFD_ENDIAN_UNKNOWN,		/* byteorder */
361  BFD_ENDIAN_UNKNOWN,		/* header_byteorder */
362  EXEC_P,			/* object_flags */
363  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
364   | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
365  0,				/* symbol_leading_char */
366  ' ',				/* ar_pad_char */
367  16,				/* ar_max_namelen */
368  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
369  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
370  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
371  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
372  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
373  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
374  {				/* bfd_check_format */
375    _bfd_dummy_target,
376    binary_object_p,		/* bfd_check_format */
377    _bfd_dummy_target,
378    _bfd_dummy_target,
379  },
380  {				/* bfd_set_format */
381    bfd_false,
382    binary_mkobject,
383    bfd_false,
384    bfd_false,
385  },
386  {				/* bfd_write_contents */
387    bfd_false,
388    bfd_true,
389    bfd_false,
390    bfd_false,
391  },
392
393  BFD_JUMP_TABLE_GENERIC (binary),
394  BFD_JUMP_TABLE_COPY (_bfd_generic),
395  BFD_JUMP_TABLE_CORE (_bfd_nocore),
396  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
397  BFD_JUMP_TABLE_SYMBOLS (binary),
398  BFD_JUMP_TABLE_RELOCS (binary),
399  BFD_JUMP_TABLE_WRITE (binary),
400  BFD_JUMP_TABLE_LINK (binary),
401  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
402
403  NULL,
404
405  NULL
406};
407