xref: /openbsd-src/gnu/usr.bin/binutils-2.17/bfd/simple.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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