OSDN Git Service

* simple.c (bfd_simple_get_relocated_section_contents): Move
[pf3gnuchains/pf3gnuchains3x.git] / bfd / simple.c
1 /* simple.c -- BFD simple client routines
2    Copyright 2002, 2003
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   section->output_offset = 0;
96   section->output_section = section;
97 }
98
99 static void
100 simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED,
101                             asection *section,
102                             void *ptr)
103 {
104   struct saved_output_info *output_info = ptr;
105   section->output_offset = output_info[section->index].offset;
106   section->output_section = output_info[section->index].section;
107 }
108
109 /*
110 FUNCTION
111         bfd_simple_relocate_secton
112
113 SYNOPSIS
114         bfd_byte *bfd_simple_get_relocated_section_contents
115           (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
116
117 DESCRIPTION
118         Returns the relocated contents of section @var{sec}.  The symbols in
119         @var{symbol_table} will be used, or the symbols from @var{abfd} if
120         @var{symbol_table} is NULL.  The output offsets for all sections will
121         be temporarily reset to 0.  The result will be stored at @var{outbuf}
122         or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
123
124         Generally all sections in @var{abfd} should have their
125         @code{output_section} pointing back to the original section.
126
127         Returns @code{NULL} on a fatal error; ignores errors applying
128         particular relocations.
129 */
130
131 bfd_byte *
132 bfd_simple_get_relocated_section_contents (bfd *abfd,
133                                            asection *sec,
134                                            bfd_byte *outbuf,
135                                            asymbol **symbol_table)
136 {
137   struct bfd_link_info link_info;
138   struct bfd_link_order link_order;
139   struct bfd_link_callbacks callbacks;
140   bfd_byte *contents, *data;
141   int storage_needed;
142   void *saved_offsets;
143   bfd_boolean saved_reloc_done = sec->reloc_done;
144
145 #undef RETURN
146 #define RETURN(x)                               \
147   do                                            \
148     {                                           \
149       sec->reloc_done = saved_reloc_done;       \
150       return (x);                               \
151     }                                           \
152   while (0)
153
154   /* Foul hack to prevent bfd_section_size aborts.  The reloc_done flag
155      only controls that macro (and the related size macros), selecting
156      between _raw_size and _cooked_size.  We may be called with relocation
157      done or not, so we need to save the done-flag and mark the section as
158      not relocated.
159
160      Debug sections won't change size while we're only relocating.  There
161      may be trouble here someday if it tries to run relaxation
162      unexpectedly, so make sure.  */
163   BFD_ASSERT (sec->_raw_size == sec->_cooked_size);
164   sec->reloc_done = 0;
165
166   if (! (sec->flags & SEC_RELOC))
167     {
168       bfd_size_type size = bfd_section_size (abfd, sec);
169
170       if (outbuf == NULL)
171         contents = bfd_malloc (size);
172       else
173         contents = outbuf;
174
175       if (contents)
176         bfd_get_section_contents (abfd, sec, contents, 0, size);
177
178       RETURN (contents);
179     }
180
181   /* In order to use bfd_get_relocated_section_contents, we need
182      to forge some data structures that it expects.  */
183
184   /* Fill in the bare minimum number of fields for our purposes.  */
185   memset (&link_info, 0, sizeof (link_info));
186   link_info.input_bfds = abfd;
187
188   link_info.hash = bfd_link_hash_table_create (abfd);
189   link_info.callbacks = &callbacks;
190   callbacks.warning = simple_dummy_warning;
191   callbacks.undefined_symbol = simple_dummy_undefined_symbol;
192   callbacks.reloc_overflow = simple_dummy_reloc_overflow;
193   callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
194   callbacks.unattached_reloc = simple_dummy_unattached_reloc;
195
196   memset (&link_order, 0, sizeof (link_order));
197   link_order.next = NULL;
198   link_order.type = bfd_indirect_link_order;
199   link_order.offset = 0;
200   link_order.size = bfd_section_size (abfd, sec);
201   link_order.u.indirect.section = sec;
202
203   data = NULL;
204   if (outbuf == NULL)
205     {
206       data = bfd_malloc (bfd_section_size (abfd, sec));
207       if (data == NULL)
208         RETURN (NULL);
209       outbuf = data;
210     }
211
212   /* The sections in ABFD may already have output sections and offsets set.
213      Because this function is primarily for debug sections, and GCC uses the
214      knowledge that debug sections will generally have VMA 0 when emiting
215      relocations between DWARF-2 sections (which are supposed to be
216      section-relative offsets anyway), we need to reset the output offsets
217      to zero.  We also need to arrange for section->output_section->vma plus
218      section->output_offset to equal section->vma, which we do by setting
219      section->output_section to point back to section.  Save the original
220      output offset and output section to restore later.  */
221   saved_offsets = malloc (sizeof (struct saved_output_info)
222                           * abfd->section_count);
223   if (saved_offsets == NULL)
224     {
225       if (data)
226         free (data);
227       RETURN (NULL);
228     }
229   bfd_map_over_sections (abfd, simple_save_output_info, saved_offsets);
230
231   if (symbol_table == NULL)
232     {
233       _bfd_generic_link_add_symbols (abfd, &link_info);
234
235       storage_needed = bfd_get_symtab_upper_bound (abfd);
236       symbol_table = bfd_malloc (storage_needed);
237       bfd_canonicalize_symtab (abfd, symbol_table);
238     }
239   else
240     storage_needed = 0;
241
242   contents = bfd_get_relocated_section_contents (abfd,
243                                                  &link_info,
244                                                  &link_order,
245                                                  outbuf,
246                                                  0,
247                                                  symbol_table);
248   if (contents == NULL && data != NULL)
249     free (data);
250
251 #if 0
252   /* NOTE: cagney/2003-04-05: This free, which was introduced on
253      2003-03-31 to stop a memory leak, caused a memory corruption
254      between GDB and BFD.  The problem, which is stabs specific, can
255      be identified by a bunch of failures in relocate.exp vis:
256
257        gdb.base/relocate.exp: get address of static_bar
258
259      Details of the problem can be found on the binutils@ mailing
260      list, see the discussion thread: "gdb.mi/mi-cli.exp failures".  */
261   if (storage_needed != 0)
262     free (symbol_table);
263 #endif
264
265   bfd_map_over_sections (abfd, simple_restore_output_info, saved_offsets);
266   free (saved_offsets);
267
268   bfd_link_hash_table_free (abfd, link_info.hash);
269
270   RETURN (contents);
271 }