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