1/* simple.c -- BFD simple client routines
2   Copyright 2002, 2003, 2004
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22#include "bfd.h"
23#include "sysdep.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			     const char *name ATTRIBUTE_UNUSED,
52			     const char *reloc_name ATTRIBUTE_UNUSED,
53			     bfd_vma addend ATTRIBUTE_UNUSED,
54			     bfd *abfd ATTRIBUTE_UNUSED,
55			     asection *section ATTRIBUTE_UNUSED,
56			     bfd_vma address ATTRIBUTE_UNUSED)
57{
58  return TRUE;
59}
60
61static bfd_boolean
62simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
63			      const char *message ATTRIBUTE_UNUSED,
64			      bfd *abfd ATTRIBUTE_UNUSED,
65			      asection *section ATTRIBUTE_UNUSED,
66			      bfd_vma address ATTRIBUTE_UNUSED)
67{
68  return TRUE;
69}
70
71static bfd_boolean
72simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
73			       const char *name ATTRIBUTE_UNUSED,
74			       bfd *abfd ATTRIBUTE_UNUSED,
75			       asection *section ATTRIBUTE_UNUSED,
76			       bfd_vma address ATTRIBUTE_UNUSED)
77{
78  return TRUE;
79}
80
81struct saved_output_info
82{
83  bfd_vma offset;
84  asection *section;
85};
86
87static void
88simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
89			 asection *section,
90			 void *ptr)
91{
92  struct saved_output_info *output_info = ptr;
93  output_info[section->index].offset = section->output_offset;
94  output_info[section->index].section = section->output_section;
95  if ((section->flags & SEC_DEBUGGING) != 0
96      || section->output_section == NULL)
97    {
98      section->output_offset = 0;
99      section->output_section = section;
100    }
101}
102
103static void
104simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
105			    asection *section,
106			    void *ptr)
107{
108  struct saved_output_info *output_info = ptr;
109  section->output_offset = output_info[section->index].offset;
110  section->output_section = output_info[section->index].section;
111}
112
113/*
114FUNCTION
115	bfd_simple_relocate_secton
116
117SYNOPSIS
118	bfd_byte *bfd_simple_get_relocated_section_contents
119	  (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
120
121DESCRIPTION
122	Returns the relocated contents of section @var{sec}.  The symbols in
123	@var{symbol_table} will be used, or the symbols from @var{abfd} if
124	@var{symbol_table} is NULL.  The output offsets for debug sections will
125	be temporarily reset to 0.  The result will be stored at @var{outbuf}
126	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
127
128	Returns @code{NULL} on a fatal error; ignores errors applying
129	particular relocations.
130*/
131
132bfd_byte *
133bfd_simple_get_relocated_section_contents (bfd *abfd,
134					   asection *sec,
135					   bfd_byte *outbuf,
136					   asymbol **symbol_table)
137{
138  struct bfd_link_info link_info;
139  struct bfd_link_order link_order;
140  struct bfd_link_callbacks callbacks;
141  bfd_byte *contents, *data;
142  int storage_needed;
143  void *saved_offsets;
144
145  if (! (sec->flags & SEC_RELOC))
146    {
147      bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
148      bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size;
149
150      if (outbuf == NULL)
151	contents = bfd_malloc (amt);
152      else
153	contents = outbuf;
154
155      if (contents)
156	bfd_get_section_contents (abfd, sec, contents, 0, size);
157
158      return contents;
159    }
160
161  /* In order to use bfd_get_relocated_section_contents, we need
162     to forge some data structures that it expects.  */
163
164  /* Fill in the bare minimum number of fields for our purposes.  */
165  memset (&link_info, 0, sizeof (link_info));
166  link_info.input_bfds = abfd;
167
168  link_info.hash = _bfd_generic_link_hash_table_create (abfd);
169  link_info.callbacks = &callbacks;
170  callbacks.warning = simple_dummy_warning;
171  callbacks.undefined_symbol = simple_dummy_undefined_symbol;
172  callbacks.reloc_overflow = simple_dummy_reloc_overflow;
173  callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
174  callbacks.unattached_reloc = simple_dummy_unattached_reloc;
175
176  memset (&link_order, 0, sizeof (link_order));
177  link_order.next = NULL;
178  link_order.type = bfd_indirect_link_order;
179  link_order.offset = 0;
180  link_order.size = sec->size;
181  link_order.u.indirect.section = sec;
182
183  data = NULL;
184  if (outbuf == NULL)
185    {
186      data = bfd_malloc (sec->size);
187      if (data == NULL)
188	return NULL;
189      outbuf = data;
190    }
191
192  /* The sections in ABFD may already have output sections and offsets set.
193     Because this function is primarily for debug sections, and GCC uses the
194     knowledge that debug sections will generally have VMA 0 when emitting
195     relocations between DWARF-2 sections (which are supposed to be
196     section-relative offsets anyway), we need to reset the output offsets
197     to zero.  We also need to arrange for section->output_section->vma plus
198     section->output_offset to equal section->vma, which we do by setting
199     section->output_section to point back to section.  Save the original
200     output offset and output section to restore later.  */
201  saved_offsets = malloc (sizeof (struct saved_output_info)
202			  * abfd->section_count);
203  if (saved_offsets == NULL)
204    {
205      if (data)
206	free (data);
207      return NULL;
208    }
209  bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets);
210
211  if (symbol_table == NULL)
212    {
213      _bfd_generic_link_add_symbols (abfd, &link_info);
214
215      storage_needed = bfd_get_symtab_upper_bound (abfd);
216      symbol_table = bfd_malloc (storage_needed);
217      bfd_canonicalize_symtab (abfd, symbol_table);
218    }
219  else
220    storage_needed = 0;
221
222  contents = bfd_get_relocated_section_contents (abfd,
223						 &link_info,
224						 &link_order,
225						 outbuf,
226						 0,
227						 symbol_table);
228  if (contents == NULL && data != NULL)
229    free (data);
230
231#if 0
232  /* NOTE: cagney/2003-04-05: This free, which was introduced on
233     2003-03-31 to stop a memory leak, caused a memory corruption
234     between GDB and BFD.  The problem, which is stabs specific, can
235     be identified by a bunch of failures in relocate.exp vis:
236
237       gdb.base/relocate.exp: get address of static_bar
238
239     Details of the problem can be found on the binutils@ mailing
240     list, see the discussion thread: "gdb.mi/mi-cli.exp failures".  */
241  if (storage_needed != 0)
242    free (symbol_table);
243#endif
244
245  bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
246  free (saved_offsets);
247
248  _bfd_generic_link_hash_table_free (link_info.hash);
249
250  return contents;
251}
252