1130561Sobrien/* simple.c -- BFD simple client routines
2218822Sdim   Copyright 2002, 2003, 2004, 2005, 2007
3130561Sobrien   Free Software Foundation, Inc.
4130561Sobrien   Contributed by MontaVista Software, Inc.
5130561Sobrien
6130561Sobrien   This file is part of BFD, the Binary File Descriptor library.
7130561Sobrien
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.
12130561Sobrien
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.
17130561Sobrien
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.  */
21130561Sobrien
22218822Sdim#include "sysdep.h"
23130561Sobrien#include "bfd.h"
24130561Sobrien#include "libbfd.h"
25130561Sobrien#include "bfdlink.h"
26130561Sobrien
27130561Sobrienstatic bfd_boolean
28130561Sobriensimple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
29130561Sobrien		      const char *warning ATTRIBUTE_UNUSED,
30130561Sobrien		      const char *symbol ATTRIBUTE_UNUSED,
31130561Sobrien		      bfd *abfd ATTRIBUTE_UNUSED,
32130561Sobrien		      asection *section ATTRIBUTE_UNUSED,
33130561Sobrien		      bfd_vma address ATTRIBUTE_UNUSED)
34130561Sobrien{
35130561Sobrien  return TRUE;
36130561Sobrien}
37130561Sobrien
38130561Sobrienstatic bfd_boolean
39130561Sobriensimple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
40130561Sobrien			       const char *name ATTRIBUTE_UNUSED,
41130561Sobrien			       bfd *abfd ATTRIBUTE_UNUSED,
42130561Sobrien			       asection *section ATTRIBUTE_UNUSED,
43130561Sobrien			       bfd_vma address ATTRIBUTE_UNUSED,
44130561Sobrien			       bfd_boolean fatal ATTRIBUTE_UNUSED)
45130561Sobrien{
46130561Sobrien  return TRUE;
47130561Sobrien}
48130561Sobrien
49130561Sobrienstatic bfd_boolean
50130561Sobriensimple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
51218822Sdim			     struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
52130561Sobrien			     const char *name ATTRIBUTE_UNUSED,
53130561Sobrien			     const char *reloc_name ATTRIBUTE_UNUSED,
54130561Sobrien			     bfd_vma addend ATTRIBUTE_UNUSED,
55130561Sobrien			     bfd *abfd ATTRIBUTE_UNUSED,
56130561Sobrien			     asection *section ATTRIBUTE_UNUSED,
57130561Sobrien			     bfd_vma address ATTRIBUTE_UNUSED)
58130561Sobrien{
59130561Sobrien  return TRUE;
60130561Sobrien}
61130561Sobrien
62130561Sobrienstatic bfd_boolean
63130561Sobriensimple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
64130561Sobrien			      const char *message ATTRIBUTE_UNUSED,
65130561Sobrien			      bfd *abfd ATTRIBUTE_UNUSED,
66130561Sobrien			      asection *section ATTRIBUTE_UNUSED,
67130561Sobrien			      bfd_vma address ATTRIBUTE_UNUSED)
68130561Sobrien{
69130561Sobrien  return TRUE;
70130561Sobrien}
71130561Sobrien
72130561Sobrienstatic bfd_boolean
73130561Sobriensimple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
74130561Sobrien			       const char *name ATTRIBUTE_UNUSED,
75130561Sobrien			       bfd *abfd ATTRIBUTE_UNUSED,
76130561Sobrien			       asection *section ATTRIBUTE_UNUSED,
77130561Sobrien			       bfd_vma address ATTRIBUTE_UNUSED)
78130561Sobrien{
79130561Sobrien  return TRUE;
80130561Sobrien}
81130561Sobrien
82218822Sdimstatic bfd_boolean
83218822Sdimsimple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
84218822Sdim				  const char *name ATTRIBUTE_UNUSED,
85218822Sdim				  bfd *obfd ATTRIBUTE_UNUSED,
86218822Sdim				  asection *osec ATTRIBUTE_UNUSED,
87218822Sdim				  bfd_vma oval ATTRIBUTE_UNUSED,
88218822Sdim				  bfd *nbfd ATTRIBUTE_UNUSED,
89218822Sdim				  asection *nsec ATTRIBUTE_UNUSED,
90218822Sdim				  bfd_vma nval ATTRIBUTE_UNUSED)
91218822Sdim{
92218822Sdim  return TRUE;
93218822Sdim}
94218822Sdim
95218822Sdimstatic void
96218822Sdimsimple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...)
97218822Sdim{
98218822Sdim}
99218822Sdim
100130561Sobrienstruct saved_output_info
101130561Sobrien{
102130561Sobrien  bfd_vma offset;
103130561Sobrien  asection *section;
104130561Sobrien};
105130561Sobrien
106130561Sobrienstatic void
107130561Sobriensimple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
108130561Sobrien			 asection *section,
109130561Sobrien			 void *ptr)
110130561Sobrien{
111130561Sobrien  struct saved_output_info *output_info = ptr;
112130561Sobrien  output_info[section->index].offset = section->output_offset;
113130561Sobrien  output_info[section->index].section = section->output_section;
114218822Sdim  if ((section->flags & SEC_DEBUGGING) != 0
115218822Sdim      || section->output_section == NULL)
116218822Sdim    {
117218822Sdim      section->output_offset = 0;
118218822Sdim      section->output_section = section;
119218822Sdim    }
120130561Sobrien}
121130561Sobrien
122130561Sobrienstatic void
123130561Sobriensimple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
124130561Sobrien			    asection *section,
125130561Sobrien			    void *ptr)
126130561Sobrien{
127130561Sobrien  struct saved_output_info *output_info = ptr;
128130561Sobrien  section->output_offset = output_info[section->index].offset;
129130561Sobrien  section->output_section = output_info[section->index].section;
130130561Sobrien}
131130561Sobrien
132130561Sobrien/*
133130561SobrienFUNCTION
134130561Sobrien	bfd_simple_relocate_secton
135130561Sobrien
136130561SobrienSYNOPSIS
137130561Sobrien	bfd_byte *bfd_simple_get_relocated_section_contents
138130561Sobrien	  (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
139130561Sobrien
140130561SobrienDESCRIPTION
141130561Sobrien	Returns the relocated contents of section @var{sec}.  The symbols in
142130561Sobrien	@var{symbol_table} will be used, or the symbols from @var{abfd} if
143218822Sdim	@var{symbol_table} is NULL.  The output offsets for debug sections will
144130561Sobrien	be temporarily reset to 0.  The result will be stored at @var{outbuf}
145130561Sobrien	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
146130561Sobrien
147130561Sobrien	Returns @code{NULL} on a fatal error; ignores errors applying
148130561Sobrien	particular relocations.
149130561Sobrien*/
150130561Sobrien
151130561Sobrienbfd_byte *
152130561Sobrienbfd_simple_get_relocated_section_contents (bfd *abfd,
153130561Sobrien					   asection *sec,
154130561Sobrien					   bfd_byte *outbuf,
155130561Sobrien					   asymbol **symbol_table)
156130561Sobrien{
157130561Sobrien  struct bfd_link_info link_info;
158130561Sobrien  struct bfd_link_order link_order;
159130561Sobrien  struct bfd_link_callbacks callbacks;
160130561Sobrien  bfd_byte *contents, *data;
161130561Sobrien  int storage_needed;
162130561Sobrien  void *saved_offsets;
163130561Sobrien
164130561Sobrien  if (! (sec->flags & SEC_RELOC))
165130561Sobrien    {
166218822Sdim      bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
167218822Sdim      bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
168130561Sobrien
169130561Sobrien      if (outbuf == NULL)
170218822Sdim	contents = bfd_malloc (amt);
171130561Sobrien      else
172130561Sobrien	contents = outbuf;
173130561Sobrien
174130561Sobrien      if (contents)
175130561Sobrien	bfd_get_section_contents (abfd, sec, contents, 0, size);
176130561Sobrien
177130561Sobrien      return contents;
178130561Sobrien    }
179130561Sobrien
180130561Sobrien  /* In order to use bfd_get_relocated_section_contents, we need
181130561Sobrien     to forge some data structures that it expects.  */
182130561Sobrien
183130561Sobrien  /* Fill in the bare minimum number of fields for our purposes.  */
184130561Sobrien  memset (&link_info, 0, sizeof (link_info));
185130561Sobrien  link_info.input_bfds = abfd;
186218822Sdim  link_info.input_bfds_tail = &abfd->link_next;
187130561Sobrien
188130561Sobrien  link_info.hash = _bfd_generic_link_hash_table_create (abfd);
189130561Sobrien  link_info.callbacks = &callbacks;
190130561Sobrien  callbacks.warning = simple_dummy_warning;
191130561Sobrien  callbacks.undefined_symbol = simple_dummy_undefined_symbol;
192130561Sobrien  callbacks.reloc_overflow = simple_dummy_reloc_overflow;
193130561Sobrien  callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
194130561Sobrien  callbacks.unattached_reloc = simple_dummy_unattached_reloc;
195218822Sdim  callbacks.multiple_definition = simple_dummy_multiple_definition;
196218822Sdim  callbacks.einfo = simple_dummy_einfo;
197130561Sobrien
198130561Sobrien  memset (&link_order, 0, sizeof (link_order));
199130561Sobrien  link_order.next = NULL;
200130561Sobrien  link_order.type = bfd_indirect_link_order;
201130561Sobrien  link_order.offset = 0;
202218822Sdim  link_order.size = sec->size;
203130561Sobrien  link_order.u.indirect.section = sec;
204130561Sobrien
205130561Sobrien  data = NULL;
206130561Sobrien  if (outbuf == NULL)
207130561Sobrien    {
208218822Sdim      data = bfd_malloc (sec->size);
209130561Sobrien      if (data == NULL)
210130561Sobrien	return NULL;
211130561Sobrien      outbuf = data;
212130561Sobrien    }
213130561Sobrien
214130561Sobrien  /* The sections in ABFD may already have output sections and offsets set.
215130561Sobrien     Because this function is primarily for debug sections, and GCC uses the
216130561Sobrien     knowledge that debug sections will generally have VMA 0 when emitting
217130561Sobrien     relocations between DWARF-2 sections (which are supposed to be
218130561Sobrien     section-relative offsets anyway), we need to reset the output offsets
219130561Sobrien     to zero.  We also need to arrange for section->output_section->vma plus
220130561Sobrien     section->output_offset to equal section->vma, which we do by setting
221130561Sobrien     section->output_section to point back to section.  Save the original
222130561Sobrien     output offset and output section to restore later.  */
223130561Sobrien  saved_offsets = malloc (sizeof (struct saved_output_info)
224130561Sobrien			  * abfd->section_count);
225130561Sobrien  if (saved_offsets == NULL)
226130561Sobrien    {
227130561Sobrien      if (data)
228130561Sobrien	free (data);
229130561Sobrien      return NULL;
230130561Sobrien    }
231130561Sobrien  bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets);
232130561Sobrien
233130561Sobrien  if (symbol_table == NULL)
234130561Sobrien    {
235130561Sobrien      _bfd_generic_link_add_symbols (abfd, &link_info);
236130561Sobrien
237130561Sobrien      storage_needed = bfd_get_symtab_upper_bound (abfd);
238130561Sobrien      symbol_table = bfd_malloc (storage_needed);
239130561Sobrien      bfd_canonicalize_symtab (abfd, symbol_table);
240130561Sobrien    }
241130561Sobrien  else
242130561Sobrien    storage_needed = 0;
243130561Sobrien
244130561Sobrien  contents = bfd_get_relocated_section_contents (abfd,
245130561Sobrien						 &link_info,
246130561Sobrien						 &link_order,
247130561Sobrien						 outbuf,
248130561Sobrien						 0,
249130561Sobrien						 symbol_table);
250130561Sobrien  if (contents == NULL && data != NULL)
251130561Sobrien    free (data);
252130561Sobrien
253130561Sobrien  bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
254130561Sobrien  free (saved_offsets);
255130561Sobrien
256130561Sobrien  _bfd_generic_link_hash_table_free (link_info.hash);
257130561Sobrien  return contents;
258130561Sobrien}
259