1/* simple.c -- BFD simple client routines
2   Copyright (C) 2002-2017 Free Software Foundation, Inc.
3   Contributed by MontaVista Software, Inc.
4
5   This file is part of BFD, the Binary File Descriptor library.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20   MA 02110-1301, USA.  */
21
22#include "sysdep.h"
23#include "bfd.h"
24#include "libbfd.h"
25#include "bfdlink.h"
26
27static void
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}
36
37static void
38simple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
39			       const char *name ATTRIBUTE_UNUSED,
40			       bfd *abfd ATTRIBUTE_UNUSED,
41			       asection *section ATTRIBUTE_UNUSED,
42			       bfd_vma address ATTRIBUTE_UNUSED,
43			       bfd_boolean fatal ATTRIBUTE_UNUSED)
44{
45}
46
47static void
48simple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
49			     struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED,
50			     const char *name ATTRIBUTE_UNUSED,
51			     const char *reloc_name ATTRIBUTE_UNUSED,
52			     bfd_vma addend ATTRIBUTE_UNUSED,
53			     bfd *abfd ATTRIBUTE_UNUSED,
54			     asection *section ATTRIBUTE_UNUSED,
55			     bfd_vma address ATTRIBUTE_UNUSED)
56{
57}
58
59static void
60simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
61			      const char *message ATTRIBUTE_UNUSED,
62			      bfd *abfd ATTRIBUTE_UNUSED,
63			      asection *section ATTRIBUTE_UNUSED,
64			      bfd_vma address ATTRIBUTE_UNUSED)
65{
66}
67
68static void
69simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
70			       const char *name ATTRIBUTE_UNUSED,
71			       bfd *abfd ATTRIBUTE_UNUSED,
72			       asection *section ATTRIBUTE_UNUSED,
73			       bfd_vma address ATTRIBUTE_UNUSED)
74{
75}
76
77static void
78simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
79				  struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
80				  bfd *nbfd ATTRIBUTE_UNUSED,
81				  asection *nsec ATTRIBUTE_UNUSED,
82				  bfd_vma nval ATTRIBUTE_UNUSED)
83{
84}
85
86static void
87simple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...)
88{
89}
90
91struct saved_output_info
92{
93  bfd_vma offset;
94  asection *section;
95};
96
97struct saved_offsets
98{
99  unsigned int section_count;
100  struct saved_output_info *sections;
101};
102
103/* The sections in ABFD may already have output sections and offsets
104   set if we are here during linking.
105
106   DWARF-2 specifies offsets into debug sections in many cases and
107   bfd_simple_get_relocated_section_contents is called to relocate
108   debug info for a single relocatable object file.  So we want
109   offsets relative to that object file's sections, not offsets in the
110   output file.  For that reason, reset a debug section->output_offset
111   to zero.
112
113   If not called during linking then set section->output_section to
114   point back to the input section, because output_section must not be
115   NULL when calling the relocation routines.
116
117   Save the original output offset and section to restore later.  */
118
119static void
120simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED,
121			 asection *section,
122			 void *ptr)
123{
124  struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
125  struct saved_output_info *output_info;
126
127  output_info = &saved_offsets->sections[section->index];
128  output_info->offset = section->output_offset;
129  output_info->section = section->output_section;
130  if ((section->flags & SEC_DEBUGGING) != 0
131      || section->output_section == NULL)
132    {
133      section->output_offset = 0;
134      section->output_section = section;
135    }
136}
137
138static void
139simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
140			    asection *section,
141			    void *ptr)
142{
143  struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr;
144  struct saved_output_info *output_info;
145
146  if (section->index >= saved_offsets->section_count)
147    return;
148
149  output_info = &saved_offsets->sections[section->index];
150  section->output_offset = output_info->offset;
151  section->output_section = output_info->section;
152}
153
154/*
155FUNCTION
156	bfd_simple_relocate_secton
157
158SYNOPSIS
159	bfd_byte *bfd_simple_get_relocated_section_contents
160	  (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
161
162DESCRIPTION
163	Returns the relocated contents of section @var{sec}.  The symbols in
164	@var{symbol_table} will be used, or the symbols from @var{abfd} if
165	@var{symbol_table} is NULL.  The output offsets for debug sections will
166	be temporarily reset to 0.  The result will be stored at @var{outbuf}
167	or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
168
169	Returns @code{NULL} on a fatal error; ignores errors applying
170	particular relocations.
171*/
172
173bfd_byte *
174bfd_simple_get_relocated_section_contents (bfd *abfd,
175					   asection *sec,
176					   bfd_byte *outbuf,
177					   asymbol **symbol_table)
178{
179  struct bfd_link_info link_info;
180  struct bfd_link_order link_order;
181  struct bfd_link_callbacks callbacks;
182  bfd_byte *contents, *data;
183  int storage_needed;
184  struct saved_offsets saved_offsets;
185  bfd *link_next;
186
187  /* Don't apply relocation on executable and shared library.  See
188     PR 4756.  */
189  if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC
190      || ! (sec->flags & SEC_RELOC))
191    {
192      contents = outbuf;
193      if (!bfd_get_full_section_contents (abfd, sec, &contents))
194	return NULL;
195      return contents;
196    }
197
198  /* In order to use bfd_get_relocated_section_contents, we need
199     to forge some data structures that it expects.  */
200
201  /* Fill in the bare minimum number of fields for our purposes.  */
202  memset (&link_info, 0, sizeof (link_info));
203  link_info.output_bfd = abfd;
204  link_info.input_bfds = abfd;
205  link_info.input_bfds_tail = &abfd->link.next;
206
207  link_next = abfd->link.next;
208  abfd->link.next = NULL;
209  link_info.hash = _bfd_generic_link_hash_table_create (abfd);
210  link_info.callbacks = &callbacks;
211  callbacks.warning = simple_dummy_warning;
212  callbacks.undefined_symbol = simple_dummy_undefined_symbol;
213  callbacks.reloc_overflow = simple_dummy_reloc_overflow;
214  callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
215  callbacks.unattached_reloc = simple_dummy_unattached_reloc;
216  callbacks.multiple_definition = simple_dummy_multiple_definition;
217  callbacks.einfo = simple_dummy_einfo;
218
219  memset (&link_order, 0, sizeof (link_order));
220  link_order.next = NULL;
221  link_order.type = bfd_indirect_link_order;
222  link_order.offset = 0;
223  link_order.size = sec->size;
224  link_order.u.indirect.section = sec;
225
226  data = NULL;
227  if (outbuf == NULL)
228    {
229      bfd_size_type amt = sec->rawsize > sec->size ? sec->rawsize : sec->size;
230      data = (bfd_byte *) bfd_malloc (amt);
231      if (data == NULL)
232	{
233	  _bfd_generic_link_hash_table_free (abfd);
234	  abfd->link.next = link_next;
235	  return NULL;
236	}
237      outbuf = data;
238    }
239
240  saved_offsets.section_count = abfd->section_count;
241  saved_offsets.sections = malloc (sizeof (*saved_offsets.sections)
242				   * saved_offsets.section_count);
243  if (saved_offsets.sections == NULL)
244    {
245      if (data)
246	free (data);
247      _bfd_generic_link_hash_table_free (abfd);
248      abfd->link.next = link_next;
249      return NULL;
250    }
251  bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets);
252
253  if (symbol_table == NULL)
254    {
255      _bfd_generic_link_add_symbols (abfd, &link_info);
256
257      storage_needed = bfd_get_symtab_upper_bound (abfd);
258      symbol_table = (asymbol **) bfd_malloc (storage_needed);
259      bfd_canonicalize_symtab (abfd, symbol_table);
260    }
261  else
262    storage_needed = 0;
263
264  contents = bfd_get_relocated_section_contents (abfd,
265						 &link_info,
266						 &link_order,
267						 outbuf,
268						 0,
269						 symbol_table);
270  if (contents == NULL && data != NULL)
271    free (data);
272
273  bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets);
274  free (saved_offsets.sections);
275
276  _bfd_generic_link_hash_table_free (abfd);
277  abfd->link.next = link_next;
278  return contents;
279}
280