simple.c revision 218822
1/* simple.c -- BFD simple client routines
2   Copyright 2002, 2003, 2004, 2005, 2007
3   Free Software Foundation, Inc.
4   Contributed by MontaVista Software, Inc.
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
21
22#include "sysdep.h"
23#include "bfd.h"
24#include "libbfd.h"
25#include "bfdlink.h"
26
27static bfd_boolean
28simple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
29		      const char *warning ATTRIBUTE_UNUSED,
30		      const char *symbol ATTRIBUTE_UNUSED,
31		      bfd *abfd ATTRIBUTE_UNUSED,
32		      asection *section ATTRIBUTE_UNUSED,
33		      bfd_vma address ATTRIBUTE_UNUSED)
34{
35  return TRUE;
36}
37
38static bfd_boolean
39simple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
40			       const char *name ATTRIBUTE_UNUSED,
41			       bfd *abfd ATTRIBUTE_UNUSED,
42			       asection *section ATTRIBUTE_UNUSED,
43			       bfd_vma address ATTRIBUTE_UNUSED,
44			       bfd_boolean fatal ATTRIBUTE_UNUSED)
45{
46  return TRUE;
47}
48
49static bfd_boolean
50simple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
51			     struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
52			     const char *name ATTRIBUTE_UNUSED,
53			     const char *reloc_name ATTRIBUTE_UNUSED,
54			     bfd_vma addend ATTRIBUTE_UNUSED,
55			     bfd *abfd ATTRIBUTE_UNUSED,
56			     asection *section ATTRIBUTE_UNUSED,
57			     bfd_vma address ATTRIBUTE_UNUSED)
58{
59  return TRUE;
60}
61
62static bfd_boolean
63simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
64			      const char *message ATTRIBUTE_UNUSED,
65			      bfd *abfd ATTRIBUTE_UNUSED,
66			      asection *section ATTRIBUTE_UNUSED,
67			      bfd_vma address ATTRIBUTE_UNUSED)
68{
69  return TRUE;
70}
71
72static bfd_boolean
73simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
74			       const char *name ATTRIBUTE_UNUSED,
75			       bfd *abfd ATTRIBUTE_UNUSED,
76			       asection *section ATTRIBUTE_UNUSED,
77			       bfd_vma address ATTRIBUTE_UNUSED)
78{
79  return TRUE;
80}
81
82static bfd_boolean
83simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
84				  const char *name ATTRIBUTE_UNUSED,
85				  bfd *obfd ATTRIBUTE_UNUSED,
86				  asection *osec ATTRIBUTE_UNUSED,
87				  bfd_vma oval ATTRIBUTE_UNUSED,
88				  bfd *nbfd ATTRIBUTE_UNUSED,
89				  asection *nsec ATTRIBUTE_UNUSED,
90				  bfd_vma nval ATTRIBUTE_UNUSED)
91{
92  return TRUE;
93}
94
95static void
96simple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...)
97{
98}
99
100struct saved_output_info
101{
102  bfd_vma offset;
103  asection *section;
104};
105
106static void
107simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
108			 asection *section,
109			 void *ptr)
110{
111  struct saved_output_info *output_info = ptr;
112  output_info[section->index].offset = section->output_offset;
113  output_info[section->index].section = section->output_section;
114  if ((section->flags & SEC_DEBUGGING) != 0
115      || section->output_section == NULL)
116    {
117      section->output_offset = 0;
118      section->output_section = section;
119    }
120}
121
122static void
123simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
124			    asection *section,
125			    void *ptr)
126{
127  struct saved_output_info *output_info = ptr;
128  section->output_offset = output_info[section->index].offset;
129  section->output_section = output_info[section->index].section;
130}
131
132/*
133FUNCTION
134	bfd_simple_relocate_secton
135
136SYNOPSIS
137	bfd_byte *bfd_simple_get_relocated_section_contents
138	  (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
139
140DESCRIPTION
141	Returns the relocated contents of section @var{sec}.  The symbols in
142	@var{symbol_table} will be used, or the symbols from @var{abfd} if
143	@var{symbol_table} is NULL.  The output offsets for debug sections will
144	be temporarily reset to 0.  The result will be stored at @var{outbuf}
145	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
146
147	Returns @code{NULL} on a fatal error; ignores errors applying
148	particular relocations.
149*/
150
151bfd_byte *
152bfd_simple_get_relocated_section_contents (bfd *abfd,
153					   asection *sec,
154					   bfd_byte *outbuf,
155					   asymbol **symbol_table)
156{
157  struct bfd_link_info link_info;
158  struct bfd_link_order link_order;
159  struct bfd_link_callbacks callbacks;
160  bfd_byte *contents, *data;
161  int storage_needed;
162  void *saved_offsets;
163
164  if (! (sec->flags & SEC_RELOC))
165    {
166      bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
167      bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
168
169      if (outbuf == NULL)
170	contents = bfd_malloc (amt);
171      else
172	contents = outbuf;
173
174      if (contents)
175	bfd_get_section_contents (abfd, sec, contents, 0, size);
176
177      return contents;
178    }
179
180  /* In order to use bfd_get_relocated_section_contents, we need
181     to forge some data structures that it expects.  */
182
183  /* Fill in the bare minimum number of fields for our purposes.  */
184  memset (&link_info, 0, sizeof (link_info));
185  link_info.input_bfds = abfd;
186  link_info.input_bfds_tail = &abfd->link_next;
187
188  link_info.hash = _bfd_generic_link_hash_table_create (abfd);
189  link_info.callbacks = &callbacks;
190  callbacks.warning = simple_dummy_warning;
191  callbacks.undefined_symbol = simple_dummy_undefined_symbol;
192  callbacks.reloc_overflow = simple_dummy_reloc_overflow;
193  callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
194  callbacks.unattached_reloc = simple_dummy_unattached_reloc;
195  callbacks.multiple_definition = simple_dummy_multiple_definition;
196  callbacks.einfo = simple_dummy_einfo;
197
198  memset (&link_order, 0, sizeof (link_order));
199  link_order.next = NULL;
200  link_order.type = bfd_indirect_link_order;
201  link_order.offset = 0;
202  link_order.size = sec->size;
203  link_order.u.indirect.section = sec;
204
205  data = NULL;
206  if (outbuf == NULL)
207    {
208      data = bfd_malloc (sec->size);
209      if (data == NULL)
210	return NULL;
211      outbuf = data;
212    }
213
214  /* The sections in ABFD may already have output sections and offsets set.
215     Because this function is primarily for debug sections, and GCC uses the
216     knowledge that debug sections will generally have VMA 0 when emitting
217     relocations between DWARF-2 sections (which are supposed to be
218     section-relative offsets anyway), we need to reset the output offsets
219     to zero.  We also need to arrange for section->output_section->vma plus
220     section->output_offset to equal section->vma, which we do by setting
221     section->output_section to point back to section.  Save the original
222     output offset and output section to restore later.  */
223  saved_offsets = malloc (sizeof (struct saved_output_info)
224			  * abfd->section_count);
225  if (saved_offsets == NULL)
226    {
227      if (data)
228	free (data);
229      return NULL;
230    }
231  bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets);
232
233  if (symbol_table == NULL)
234    {
235      _bfd_generic_link_add_symbols (abfd, &link_info);
236
237      storage_needed = bfd_get_symtab_upper_bound (abfd);
238      symbol_table = bfd_malloc (storage_needed);
239      bfd_canonicalize_symtab (abfd, symbol_table);
240    }
241  else
242    storage_needed = 0;
243
244  contents = bfd_get_relocated_section_contents (abfd,
245						 &link_info,
246						 &link_order,
247						 outbuf,
248						 0,
249						 symbol_table);
250  if (contents == NULL && data != NULL)
251    free (data);
252
253  bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
254  free (saved_offsets);
255
256  _bfd_generic_link_hash_table_free (link_info.hash);
257  return contents;
258}
259