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