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