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