/src/binutils-gdb/bfd/simple.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* simple.c -- BFD simple client routines |
2 | | Copyright (C) 2002-2025 Free Software Foundation, Inc. |
3 | | Contributed by MontaVista Software, Inc. |
4 | | |
5 | | This file is part of BFD, the Binary File Descriptor library. |
6 | | |
7 | | This program is free software; you can redistribute it and/or modify |
8 | | it under the terms of the GNU General Public License as published by |
9 | | the Free Software Foundation; either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | This program is distributed in the hope that it will be useful, |
13 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | GNU General Public License for more details. |
16 | | |
17 | | You should have received a copy of the GNU General Public License |
18 | | along with this program; if not, write to the Free Software |
19 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
20 | | MA 02110-1301, USA. */ |
21 | | |
22 | | #include "sysdep.h" |
23 | | #include "bfd.h" |
24 | | #include "libbfd.h" |
25 | | #include "bfdlink.h" |
26 | | #include "genlink.h" |
27 | | |
28 | | static void |
29 | | simple_dummy_add_to_set (struct bfd_link_info * info ATTRIBUTE_UNUSED, |
30 | | struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED, |
31 | | bfd_reloc_code_real_type reloc ATTRIBUTE_UNUSED, |
32 | | bfd *abfd ATTRIBUTE_UNUSED, |
33 | | asection *sec ATTRIBUTE_UNUSED, |
34 | | bfd_vma value ATTRIBUTE_UNUSED) |
35 | 0 | { |
36 | 0 | } |
37 | | |
38 | | static void |
39 | | simple_dummy_constructor (struct bfd_link_info * info ATTRIBUTE_UNUSED, |
40 | | bool constructor ATTRIBUTE_UNUSED, |
41 | | const char *name ATTRIBUTE_UNUSED, |
42 | | bfd *abfd ATTRIBUTE_UNUSED, |
43 | | asection *sec ATTRIBUTE_UNUSED, |
44 | | bfd_vma value ATTRIBUTE_UNUSED) |
45 | 0 | { |
46 | 0 | } |
47 | | |
48 | | static void |
49 | | simple_dummy_multiple_common (struct bfd_link_info * info ATTRIBUTE_UNUSED, |
50 | | struct bfd_link_hash_entry * entry ATTRIBUTE_UNUSED, |
51 | | bfd * abfd ATTRIBUTE_UNUSED, |
52 | | enum bfd_link_hash_type type ATTRIBUTE_UNUSED, |
53 | | bfd_vma size ATTRIBUTE_UNUSED) |
54 | 0 | { |
55 | 0 | } |
56 | | |
57 | | static void |
58 | | simple_dummy_warning (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, |
59 | | const char *warning ATTRIBUTE_UNUSED, |
60 | | const char *symbol ATTRIBUTE_UNUSED, |
61 | | bfd *abfd ATTRIBUTE_UNUSED, |
62 | | asection *section ATTRIBUTE_UNUSED, |
63 | | bfd_vma address ATTRIBUTE_UNUSED) |
64 | 0 | { |
65 | 0 | } |
66 | | |
67 | | static void |
68 | | simple_dummy_undefined_symbol (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, |
69 | | const char *name ATTRIBUTE_UNUSED, |
70 | | bfd *abfd ATTRIBUTE_UNUSED, |
71 | | asection *section ATTRIBUTE_UNUSED, |
72 | | bfd_vma address ATTRIBUTE_UNUSED, |
73 | | bool fatal ATTRIBUTE_UNUSED) |
74 | 2.86k | { |
75 | 2.86k | } |
76 | | |
77 | | static void |
78 | | simple_dummy_reloc_overflow (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, |
79 | | struct bfd_link_hash_entry *entry ATTRIBUTE_UNUSED, |
80 | | const char *name ATTRIBUTE_UNUSED, |
81 | | const char *reloc_name ATTRIBUTE_UNUSED, |
82 | | bfd_vma addend ATTRIBUTE_UNUSED, |
83 | | bfd *abfd ATTRIBUTE_UNUSED, |
84 | | asection *section ATTRIBUTE_UNUSED, |
85 | | bfd_vma address ATTRIBUTE_UNUSED) |
86 | 2.70k | { |
87 | 2.70k | } |
88 | | |
89 | | static void |
90 | | simple_dummy_reloc_dangerous (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, |
91 | | const char *message ATTRIBUTE_UNUSED, |
92 | | bfd *abfd ATTRIBUTE_UNUSED, |
93 | | asection *section ATTRIBUTE_UNUSED, |
94 | | bfd_vma address ATTRIBUTE_UNUSED) |
95 | 1.75k | { |
96 | 1.75k | } |
97 | | |
98 | | static void |
99 | | simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, |
100 | | const char *name ATTRIBUTE_UNUSED, |
101 | | bfd *abfd ATTRIBUTE_UNUSED, |
102 | | asection *section ATTRIBUTE_UNUSED, |
103 | | bfd_vma address ATTRIBUTE_UNUSED) |
104 | 0 | { |
105 | 0 | } |
106 | | |
107 | | static void |
108 | | simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, |
109 | | struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED, |
110 | | bfd *nbfd ATTRIBUTE_UNUSED, |
111 | | asection *nsec ATTRIBUTE_UNUSED, |
112 | | bfd_vma nval ATTRIBUTE_UNUSED) |
113 | 0 | { |
114 | 0 | } |
115 | | |
116 | | static void |
117 | | simple_dummy_einfo (const char *fmt ATTRIBUTE_UNUSED, ...) |
118 | 1.36k | { |
119 | 1.36k | } |
120 | | |
121 | | struct saved_output_info |
122 | | { |
123 | | bfd_vma offset; |
124 | | asection *section; |
125 | | }; |
126 | | |
127 | | struct saved_offsets |
128 | | { |
129 | | unsigned int section_count; |
130 | | struct saved_output_info *sections; |
131 | | }; |
132 | | |
133 | | /* The sections in ABFD may already have output sections and offsets |
134 | | set if we are here during linking. |
135 | | |
136 | | DWARF-2 specifies offsets into debug sections in many cases and |
137 | | bfd_simple_get_relocated_section_contents is called to relocate |
138 | | debug info for a single relocatable object file. So we want |
139 | | offsets relative to that object file's sections, not offsets in the |
140 | | output file. For that reason, reset a debug section->output_offset |
141 | | to zero. |
142 | | |
143 | | If not called during linking then set section->output_section to |
144 | | point back to the input section, because output_section must not be |
145 | | NULL when calling the relocation routines. |
146 | | |
147 | | Save the original output offset and section to restore later. */ |
148 | | |
149 | | static void |
150 | | simple_save_output_info (bfd *abfd ATTRIBUTE_UNUSED, |
151 | | asection *section, |
152 | | void *ptr) |
153 | 414k | { |
154 | 414k | struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr; |
155 | 414k | struct saved_output_info *output_info; |
156 | | |
157 | 414k | output_info = &saved_offsets->sections[section->index]; |
158 | 414k | output_info->offset = section->output_offset; |
159 | 414k | output_info->section = section->output_section; |
160 | 414k | if ((section->flags & SEC_DEBUGGING) != 0 |
161 | 414k | || section->output_section == NULL) |
162 | 414k | { |
163 | 414k | section->output_offset = 0; |
164 | 414k | section->output_section = section; |
165 | 414k | } |
166 | 414k | } |
167 | | |
168 | | static void |
169 | | simple_restore_output_info (bfd *abfd ATTRIBUTE_UNUSED, |
170 | | asection *section, |
171 | | void *ptr) |
172 | 414k | { |
173 | 414k | struct saved_offsets *saved_offsets = (struct saved_offsets *) ptr; |
174 | 414k | struct saved_output_info *output_info; |
175 | | |
176 | 414k | if (section->index >= saved_offsets->section_count) |
177 | 0 | return; |
178 | | |
179 | 414k | output_info = &saved_offsets->sections[section->index]; |
180 | 414k | section->output_offset = output_info->offset; |
181 | 414k | section->output_section = output_info->section; |
182 | 414k | } |
183 | | |
184 | | /* |
185 | | FUNCTION |
186 | | bfd_simple_relocate_secton |
187 | | |
188 | | SYNOPSIS |
189 | | bfd_byte *bfd_simple_get_relocated_section_contents |
190 | | (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); |
191 | | |
192 | | DESCRIPTION |
193 | | Returns the relocated contents of section @var{sec}. The symbols in |
194 | | @var{symbol_table} will be used, or the symbols from @var{abfd} if |
195 | | @var{symbol_table} is NULL. The output offsets for debug sections will |
196 | | be temporarily reset to 0. The result will be stored at @var{outbuf} |
197 | | or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}. |
198 | | |
199 | | Returns @code{NULL} on a fatal error; ignores errors applying |
200 | | particular relocations. |
201 | | */ |
202 | | |
203 | | bfd_byte * |
204 | | bfd_simple_get_relocated_section_contents (bfd *abfd, |
205 | | asection *sec, |
206 | | bfd_byte *outbuf, |
207 | | asymbol **symbol_table) |
208 | 17.6k | { |
209 | 17.6k | struct bfd_link_info link_info; |
210 | 17.6k | struct bfd_link_order link_order; |
211 | 17.6k | struct bfd_link_callbacks callbacks; |
212 | 17.6k | bfd_byte *contents; |
213 | 17.6k | struct saved_offsets saved_offsets; |
214 | 17.6k | bfd *link_next; |
215 | | |
216 | | /* Don't apply relocation on executable and shared library. See |
217 | | PR 4756. */ |
218 | 17.6k | if ((abfd->flags & (HAS_RELOC | EXEC_P | DYNAMIC)) != HAS_RELOC |
219 | 17.6k | || ! (sec->flags & SEC_RELOC)) |
220 | 12.0k | { |
221 | 12.0k | if (!bfd_get_full_section_contents (abfd, sec, &outbuf)) |
222 | 169 | return NULL; |
223 | 11.8k | return outbuf; |
224 | 12.0k | } |
225 | | |
226 | | /* In order to use bfd_get_relocated_section_contents, we need |
227 | | to forge some data structures that it expects. */ |
228 | | |
229 | | /* Fill in the bare minimum number of fields for our purposes. */ |
230 | 5.62k | memset (&link_info, 0, sizeof (link_info)); |
231 | 5.62k | link_info.output_bfd = abfd; |
232 | 5.62k | link_info.input_bfds = abfd; |
233 | 5.62k | link_info.input_bfds_tail = &abfd->link.next; |
234 | | |
235 | 5.62k | link_next = abfd->link.next; |
236 | 5.62k | abfd->link.next = NULL; |
237 | 5.62k | link_info.hash = _bfd_generic_link_hash_table_create (abfd); |
238 | 5.62k | link_info.callbacks = &callbacks; |
239 | | /* Make sure that any fields not initialised below do not |
240 | | result in a potential indirection via a random address. */ |
241 | 5.62k | memset (&callbacks, 0, sizeof callbacks); |
242 | 5.62k | callbacks.warning = simple_dummy_warning; |
243 | 5.62k | callbacks.undefined_symbol = simple_dummy_undefined_symbol; |
244 | 5.62k | callbacks.reloc_overflow = simple_dummy_reloc_overflow; |
245 | 5.62k | callbacks.reloc_dangerous = simple_dummy_reloc_dangerous; |
246 | 5.62k | callbacks.unattached_reloc = simple_dummy_unattached_reloc; |
247 | 5.62k | callbacks.multiple_definition = simple_dummy_multiple_definition; |
248 | 5.62k | callbacks.einfo = simple_dummy_einfo; |
249 | 5.62k | callbacks.multiple_common = simple_dummy_multiple_common; |
250 | 5.62k | callbacks.constructor = simple_dummy_constructor; |
251 | 5.62k | callbacks.add_to_set = simple_dummy_add_to_set; |
252 | | |
253 | 5.62k | memset (&link_order, 0, sizeof (link_order)); |
254 | 5.62k | link_order.next = NULL; |
255 | 5.62k | link_order.type = bfd_indirect_link_order; |
256 | 5.62k | link_order.offset = 0; |
257 | 5.62k | link_order.size = sec->size; |
258 | 5.62k | link_order.u.indirect.section = sec; |
259 | | |
260 | 5.62k | contents = NULL; |
261 | | |
262 | 5.62k | saved_offsets.section_count = abfd->section_count; |
263 | 5.62k | saved_offsets.sections = malloc (sizeof (*saved_offsets.sections) |
264 | 5.62k | * saved_offsets.section_count); |
265 | 5.62k | if (saved_offsets.sections == NULL) |
266 | 0 | goto out1; |
267 | 5.62k | bfd_map_over_sections (abfd, simple_save_output_info, &saved_offsets); |
268 | | |
269 | 5.62k | if (symbol_table == NULL) |
270 | 1.81k | { |
271 | 1.81k | if (!bfd_generic_link_read_symbols (abfd)) |
272 | 560 | goto out2; |
273 | 1.25k | symbol_table = _bfd_generic_link_get_symbols (abfd); |
274 | 1.25k | } |
275 | | |
276 | 5.06k | contents = bfd_get_relocated_section_contents (abfd, |
277 | 5.06k | &link_info, |
278 | 5.06k | &link_order, |
279 | 5.06k | outbuf, |
280 | 5.06k | false, |
281 | 5.06k | symbol_table); |
282 | 5.62k | out2: |
283 | 5.62k | bfd_map_over_sections (abfd, simple_restore_output_info, &saved_offsets); |
284 | 5.62k | free (saved_offsets.sections); |
285 | 5.62k | out1: |
286 | 5.62k | _bfd_generic_link_hash_table_free (abfd); |
287 | 5.62k | abfd->link.next = link_next; |
288 | 5.62k | return contents; |
289 | 5.62k | } |