/src/binutils-gdb/bfd/elf-sframe.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* .sframe section processing. |
2 | | Copyright (C) 2022-2023 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of BFD, the Binary File Descriptor library. |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; if not, write to the Free Software |
18 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | | MA 02110-1301, USA. */ |
20 | | |
21 | | #include "sysdep.h" |
22 | | #include "bfd.h" |
23 | | #include "libbfd.h" |
24 | | #include "elf-bfd.h" |
25 | | #include "sframe-api.h" |
26 | | |
27 | | /* Return TRUE if the function has been marked for deletion during the linking |
28 | | process. */ |
29 | | |
30 | | static bool |
31 | | sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info, |
32 | | unsigned int func_idx) |
33 | 0 | { |
34 | 0 | if (func_idx < sfd_info->sfd_fde_count) |
35 | 0 | return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p; |
36 | | |
37 | 0 | return false; |
38 | 0 | } |
39 | | |
40 | | /* Mark the function in the decoder info for deletion. */ |
41 | | |
42 | | static void |
43 | | sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info, |
44 | | unsigned int func_idx) |
45 | 0 | { |
46 | 0 | if (func_idx < sfd_info->sfd_fde_count) |
47 | 0 | sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p = true; |
48 | 0 | } |
49 | | |
50 | | /* Get the relocation offset from the decoder info for the given function. */ |
51 | | |
52 | | static unsigned int |
53 | | sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info, |
54 | | unsigned int func_idx) |
55 | 0 | { |
56 | 0 | BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); |
57 | 0 | unsigned int func_r_offset |
58 | 0 | = sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset; |
59 | | /* There must have been a reloc. */ |
60 | 0 | BFD_ASSERT (func_r_offset); |
61 | 0 | return func_r_offset; |
62 | 0 | } |
63 | | |
64 | | /* Bookkeep the function relocation offset in the decoder info. */ |
65 | | |
66 | | static void |
67 | | sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info, |
68 | | unsigned int func_idx, |
69 | | unsigned int r_offset) |
70 | 0 | { |
71 | 0 | if (func_idx < sfd_info->sfd_fde_count) |
72 | 0 | sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset = r_offset; |
73 | 0 | } |
74 | | |
75 | | /* Get the relocation index in the elf_reloc_cookie for the function. */ |
76 | | |
77 | | static unsigned int |
78 | | sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info, |
79 | | unsigned int func_idx) |
80 | 0 | { |
81 | 0 | BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); |
82 | 0 | return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index; |
83 | 0 | } |
84 | | |
85 | | /* Bookkeep the relocation index in the elf_reloc_cookie for the function. */ |
86 | | |
87 | | static void |
88 | | sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info, |
89 | | unsigned int func_idx, |
90 | | unsigned int reloc_index) |
91 | 0 | { |
92 | 0 | if (func_idx < sfd_info->sfd_fde_count) |
93 | 0 | sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index; |
94 | 0 | } |
95 | | |
96 | | /* Initialize the set of additional information in CFD_INFO, |
97 | | needed for linking SEC. Returns TRUE if setup is done successfully. */ |
98 | | |
99 | | static bool |
100 | | sframe_decoder_init_func_bfdinfo (asection *sec, |
101 | | struct sframe_dec_info *sfd_info, |
102 | | struct elf_reloc_cookie *cookie) |
103 | 0 | { |
104 | 0 | unsigned int fde_count; |
105 | 0 | unsigned int func_bfdinfo_size, i; |
106 | |
|
107 | 0 | fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); |
108 | 0 | sfd_info->sfd_fde_count = fde_count; |
109 | | |
110 | | /* Allocate and clear the memory. */ |
111 | 0 | func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count; |
112 | 0 | sfd_info->sfd_func_bfdinfo |
113 | 0 | = (struct sframe_func_bfdinfo*) bfd_malloc (func_bfdinfo_size); |
114 | 0 | if (sfd_info->sfd_func_bfdinfo == NULL) |
115 | 0 | return false; |
116 | 0 | memset (sfd_info->sfd_func_bfdinfo, 0, func_bfdinfo_size); |
117 | | |
118 | | /* For linker generated .sframe sections, we have no relocs. Skip. */ |
119 | 0 | if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL) |
120 | 0 | return true; |
121 | | |
122 | 0 | for (i = 0; i < fde_count; i++) |
123 | 0 | { |
124 | 0 | cookie->rel = cookie->rels + i; |
125 | 0 | BFD_ASSERT (cookie->rel < cookie->relend); |
126 | | /* Bookkeep the relocation offset and relocation index of each function |
127 | | for later use. */ |
128 | 0 | sframe_decoder_set_func_r_offset (sfd_info, i, cookie->rel->r_offset); |
129 | 0 | sframe_decoder_set_func_reloc_index (sfd_info, i, |
130 | 0 | (cookie->rel - cookie->rels)); |
131 | |
|
132 | 0 | cookie->rel++; |
133 | 0 | } |
134 | 0 | BFD_ASSERT (cookie->rel == cookie->relend); |
135 | |
|
136 | 0 | return true; |
137 | 0 | } |
138 | | |
139 | | /* Read the value from CONTENTS at the specified OFFSET for the given ABFD. */ |
140 | | |
141 | | static bfd_vma |
142 | | sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset, |
143 | | unsigned int width) |
144 | 0 | { |
145 | 0 | BFD_ASSERT (contents && offset); |
146 | | /* Supporting the usecase of reading only the 4-byte relocated |
147 | | value (signed offset for func start addr) for now. */ |
148 | 0 | BFD_ASSERT (width == 4); |
149 | | /* FIXME endianness ?? */ |
150 | 0 | unsigned char *buf = contents + offset; |
151 | 0 | bfd_vma value = bfd_get_signed_32 (abfd, buf); |
152 | 0 | return value; |
153 | 0 | } |
154 | | |
155 | | /* Return true if there is at least one non-empty .sframe section in |
156 | | input files. Can only be called after ld has mapped input to |
157 | | output sections, and before sections are stripped. */ |
158 | | |
159 | | bool |
160 | | _bfd_elf_sframe_present (struct bfd_link_info *info) |
161 | 0 | { |
162 | 0 | asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe"); |
163 | |
|
164 | 0 | if (sframe == NULL) |
165 | 0 | return false; |
166 | | |
167 | | /* Count only sections which have at least a single FDE. */ |
168 | 0 | for (sframe = sframe->map_head.s; sframe != NULL; sframe = sframe->map_head.s) |
169 | | /* Note that this may become an approximate check in the future when |
170 | | some ABI/arch begin to use the sfh_auxhdr_len. When sfh_auxhdr_len has |
171 | | non-zero value, it will need to be accounted for in the calculation of |
172 | | the SFrame header size. */ |
173 | 0 | if (sframe->size > sizeof (sframe_header)) |
174 | 0 | return true; |
175 | 0 | return false; |
176 | 0 | } |
177 | | |
178 | | /* Try to parse .sframe section SEC, which belongs to ABFD. Store the |
179 | | information in the section's sec_info field on success. COOKIE |
180 | | describes the relocations in SEC. |
181 | | |
182 | | Returns TRUE if success, FALSE if any error or failure. */ |
183 | | |
184 | | bool |
185 | | _bfd_elf_parse_sframe (bfd *abfd, |
186 | | struct bfd_link_info *info ATTRIBUTE_UNUSED, |
187 | | asection *sec, struct elf_reloc_cookie *cookie) |
188 | 0 | { |
189 | 0 | bfd_byte *sfbuf = NULL; |
190 | 0 | struct sframe_dec_info *sfd_info; |
191 | 0 | sframe_decoder_ctx *sfd_ctx; |
192 | 0 | bfd_size_type sf_size; |
193 | 0 | int decerr = 0; |
194 | |
|
195 | 0 | if (sec->size == 0 |
196 | 0 | || (sec->flags & SEC_HAS_CONTENTS) == 0 |
197 | 0 | || sec->sec_info_type != SEC_INFO_TYPE_NONE) |
198 | 0 | { |
199 | | /* This file does not contain .sframe information. */ |
200 | 0 | return false; |
201 | 0 | } |
202 | | |
203 | 0 | if (bfd_is_abs_section (sec->output_section)) |
204 | 0 | { |
205 | | /* At least one of the sections is being discarded from the |
206 | | link, so we should just ignore them. */ |
207 | 0 | return false; |
208 | 0 | } |
209 | | |
210 | | /* Read the SFrame stack trace information from abfd. */ |
211 | 0 | if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf)) |
212 | 0 | goto fail_no_free; |
213 | | |
214 | | /* Decode the buffer and keep decoded contents for later use. |
215 | | Relocations are performed later, but are such that the section's |
216 | | size is unaffected. */ |
217 | 0 | sfd_info = bfd_malloc (sizeof (struct sframe_dec_info)); |
218 | 0 | sf_size = sec->size; |
219 | |
|
220 | 0 | sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr); |
221 | 0 | sfd_ctx = sfd_info->sfd_ctx; |
222 | 0 | if (!sfd_ctx) |
223 | | /* Free'ing up any memory held by decoder context is done by |
224 | | sframe_decode in case of error. */ |
225 | 0 | goto fail_no_free; |
226 | | |
227 | 0 | if (!sframe_decoder_init_func_bfdinfo (sec, sfd_info, cookie)) |
228 | 0 | { |
229 | 0 | sframe_decoder_free (&sfd_ctx); |
230 | 0 | goto fail_no_free; |
231 | 0 | } |
232 | | |
233 | 0 | elf_section_data (sec)->sec_info = sfd_info; |
234 | 0 | sec->sec_info_type = SEC_INFO_TYPE_SFRAME; |
235 | |
|
236 | 0 | goto success; |
237 | | |
238 | 0 | fail_no_free: |
239 | 0 | _bfd_error_handler |
240 | 0 | (_("error in %pB(%pA); no .sframe will be created"), |
241 | 0 | abfd, sec); |
242 | 0 | return false; |
243 | 0 | success: |
244 | 0 | free (sfbuf); |
245 | 0 | return true; |
246 | 0 | } |
247 | | |
248 | | /* This function is called for each input file before the .sframe section |
249 | | is relocated. It marks the SFrame FDE for the discarded functions for |
250 | | deletion. |
251 | | |
252 | | The function returns TRUE iff any entries have been deleted. */ |
253 | | |
254 | | bool |
255 | | _bfd_elf_discard_section_sframe |
256 | | (asection *sec, |
257 | | bool (*reloc_symbol_deleted_p) (bfd_vma, void *), |
258 | | struct elf_reloc_cookie *cookie) |
259 | 0 | { |
260 | 0 | bool changed; |
261 | 0 | bool keep; |
262 | 0 | unsigned int i; |
263 | 0 | unsigned int func_desc_offset; |
264 | 0 | unsigned int num_fidx; |
265 | 0 | struct sframe_dec_info *sfd_info; |
266 | |
|
267 | 0 | changed = false; |
268 | | /* FIXME - if relocatable link and changed = true, how does the final |
269 | | .rela.sframe get updated ?. */ |
270 | 0 | keep = false; |
271 | |
|
272 | 0 | sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info; |
273 | | |
274 | | /* Skip checking for the linker created .sframe sections |
275 | | (for PLT sections). */ |
276 | 0 | if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL) |
277 | 0 | { |
278 | 0 | num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); |
279 | 0 | for (i = 0; i < num_fidx; i++) |
280 | 0 | { |
281 | 0 | func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i); |
282 | |
|
283 | 0 | cookie->rel = cookie->rels |
284 | 0 | + sframe_decoder_get_func_reloc_index (sfd_info, i); |
285 | 0 | keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie); |
286 | |
|
287 | 0 | if (!keep) |
288 | 0 | { |
289 | 0 | sframe_decoder_mark_func_deleted (sfd_info, i); |
290 | 0 | changed = true; |
291 | 0 | } |
292 | 0 | } |
293 | 0 | } |
294 | 0 | return changed; |
295 | 0 | } |
296 | | |
297 | | /* Update the reference to the output .sframe section in the output ELF |
298 | | BFD ABFD. Returns true if no error. */ |
299 | | |
300 | | bool |
301 | | _bfd_elf_set_section_sframe (bfd *abfd, |
302 | | struct bfd_link_info *info) |
303 | 0 | { |
304 | 0 | asection *cfsec; |
305 | |
|
306 | 0 | cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe"); |
307 | 0 | if (!cfsec) |
308 | 0 | return false; |
309 | | |
310 | 0 | elf_sframe (abfd) = cfsec; |
311 | |
|
312 | 0 | return true; |
313 | 0 | } |
314 | | |
315 | | /* Merge .sframe section SEC. This is called with the relocated |
316 | | CONTENTS. */ |
317 | | |
318 | | bool |
319 | | _bfd_elf_merge_section_sframe (bfd *abfd, |
320 | | struct bfd_link_info *info, |
321 | | asection *sec, |
322 | | bfd_byte *contents) |
323 | 0 | { |
324 | 0 | struct sframe_dec_info *sfd_info; |
325 | 0 | struct sframe_enc_info *sfe_info; |
326 | 0 | sframe_decoder_ctx *sfd_ctx; |
327 | 0 | sframe_encoder_ctx *sfe_ctx; |
328 | 0 | uint8_t sfd_ctx_abi_arch; |
329 | 0 | int8_t sfd_ctx_fixed_fp_offset; |
330 | 0 | int8_t sfd_ctx_fixed_ra_offset; |
331 | 0 | uint8_t dctx_version; |
332 | 0 | uint8_t ectx_version; |
333 | 0 | int encerr = 0; |
334 | |
|
335 | 0 | struct elf_link_hash_table *htab; |
336 | 0 | asection *cfsec; |
337 | | |
338 | | /* Sanity check - handle SFrame sections only. */ |
339 | 0 | if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME) |
340 | 0 | return false; |
341 | | |
342 | 0 | sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info; |
343 | 0 | sfd_ctx = sfd_info->sfd_ctx; |
344 | |
|
345 | 0 | htab = elf_hash_table (info); |
346 | 0 | sfe_info = &(htab->sfe_info); |
347 | 0 | sfe_ctx = sfe_info->sfe_ctx; |
348 | | |
349 | | /* All input bfds are expected to have a valid SFrame section. Even if |
350 | | the SFrame section is empty with only a header, there must be a valid |
351 | | SFrame decoder context by now. The SFrame encoder context, however, |
352 | | will get set later here, if this is the first call to the function. */ |
353 | 0 | if (sfd_ctx == NULL || sfe_info == NULL) |
354 | 0 | return false; |
355 | | |
356 | 0 | if (htab->sfe_info.sfe_ctx == NULL) |
357 | 0 | { |
358 | 0 | sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx); |
359 | 0 | sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx); |
360 | 0 | sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx); |
361 | | |
362 | | /* Valid values are non-zero. */ |
363 | 0 | if (!sfd_ctx_abi_arch) |
364 | 0 | return false; |
365 | | |
366 | 0 | htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_2, |
367 | 0 | 0, /* SFrame flags. */ |
368 | 0 | sfd_ctx_abi_arch, |
369 | 0 | sfd_ctx_fixed_fp_offset, |
370 | 0 | sfd_ctx_fixed_ra_offset, |
371 | 0 | &encerr); |
372 | | /* Handle errors from sframe_encode. */ |
373 | 0 | if (htab->sfe_info.sfe_ctx == NULL) |
374 | 0 | return false; |
375 | 0 | } |
376 | 0 | sfe_ctx = sfe_info->sfe_ctx; |
377 | |
|
378 | 0 | if (sfe_info->sframe_section == NULL) |
379 | 0 | { |
380 | | /* Make sure things are set for an eventual write. |
381 | | Size of the output section is not known until |
382 | | _bfd_elf_write_section_sframe is ready with the buffer |
383 | | to write out. */ |
384 | 0 | cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe"); |
385 | 0 | if (cfsec) |
386 | 0 | { |
387 | 0 | sfe_info->sframe_section = cfsec; |
388 | | // elf_sframe (abfd) = cfsec; |
389 | 0 | } |
390 | 0 | else |
391 | 0 | return false; |
392 | 0 | } |
393 | | |
394 | | /* Check that all .sframe sections being linked have the same |
395 | | ABI/arch. */ |
396 | 0 | if (sframe_decoder_get_abi_arch (sfd_ctx) |
397 | 0 | != sframe_encoder_get_abi_arch (sfe_ctx)) |
398 | 0 | { |
399 | 0 | _bfd_error_handler |
400 | 0 | (_("input SFrame sections with different abi prevent .sframe" |
401 | 0 | " generation")); |
402 | 0 | return false; |
403 | 0 | } |
404 | | |
405 | | /* Check that all .sframe sections being linked have the same version. */ |
406 | 0 | dctx_version = sframe_decoder_get_version (sfd_ctx); |
407 | 0 | ectx_version = sframe_encoder_get_version (sfe_ctx); |
408 | 0 | if (dctx_version != SFRAME_VERSION_2 || dctx_version != ectx_version) |
409 | 0 | { |
410 | 0 | _bfd_error_handler |
411 | 0 | (_("input SFrame sections with different format versions prevent" |
412 | 0 | " .sframe generation")); |
413 | 0 | return false; |
414 | 0 | } |
415 | | |
416 | | |
417 | | /* Iterate over the function descriptor entries and the FREs of the |
418 | | function from the decoder context. Add each of them to the encoder |
419 | | context, if suitable. */ |
420 | 0 | uint32_t i = 0, j = 0, cur_fidx = 0; |
421 | |
|
422 | 0 | uint32_t num_fidx = sframe_decoder_get_num_fidx (sfd_ctx); |
423 | 0 | uint32_t num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx); |
424 | |
|
425 | 0 | for (i = 0; i < num_fidx; i++) |
426 | 0 | { |
427 | 0 | unsigned int num_fres = 0; |
428 | 0 | int32_t func_start_addr; |
429 | 0 | bfd_vma address; |
430 | 0 | uint32_t func_size = 0; |
431 | 0 | unsigned char func_info = 0; |
432 | 0 | unsigned int r_offset = 0; |
433 | 0 | bool pltn_reloc_by_hand = false; |
434 | 0 | unsigned int pltn_r_offset = 0; |
435 | 0 | uint8_t rep_block_size = 0; |
436 | |
|
437 | 0 | if (!sframe_decoder_get_funcdesc_v2 (sfd_ctx, i, &num_fres, &func_size, |
438 | 0 | &func_start_addr, &func_info, |
439 | 0 | &rep_block_size)) |
440 | 0 | { |
441 | | /* If function belongs to a deleted section, skip editing the |
442 | | function descriptor entry. */ |
443 | 0 | if (sframe_decoder_func_deleted_p(sfd_info, i)) |
444 | 0 | continue; |
445 | | |
446 | | /* Don't edit function descriptor entries for relocatable link. */ |
447 | 0 | if (!bfd_link_relocatable (info)) |
448 | 0 | { |
449 | 0 | if (!(sec->flags & SEC_LINKER_CREATED)) |
450 | 0 | { |
451 | | /* Get relocated contents by reading the value of the |
452 | | relocated function start address at the beginning of the |
453 | | function descriptor entry. */ |
454 | 0 | r_offset = sframe_decoder_get_func_r_offset (sfd_info, i); |
455 | 0 | } |
456 | 0 | else |
457 | 0 | { |
458 | | /* Expected to land here when SFrame stack trace info is |
459 | | created dynamically for the .plt* sections. These |
460 | | sections are expected to have upto two SFrame FDE entries. |
461 | | Although the code should work for > 2, leaving this |
462 | | assert here for safety. */ |
463 | 0 | BFD_ASSERT (num_fidx <= 2); |
464 | | /* For the first entry, we know the offset of the SFrame FDE's |
465 | | sfde_func_start_address. Side note: see how the value |
466 | | of PLT_SFRAME_FDE_START_OFFSET is also set to the |
467 | | same. */ |
468 | 0 | r_offset = sframe_decoder_get_hdr_size (sfd_ctx); |
469 | | /* For any further SFrame FDEs, the generator has already put |
470 | | in an offset in place of sfde_func_start_address of the |
471 | | corresponding FDE. We will use it by hand to relocate. */ |
472 | 0 | if (i > 0) |
473 | 0 | { |
474 | 0 | pltn_r_offset |
475 | 0 | = r_offset + (i * sizeof (sframe_func_desc_entry)); |
476 | 0 | pltn_reloc_by_hand = true; |
477 | 0 | } |
478 | 0 | } |
479 | | |
480 | | /* Get the SFrame FDE function start address after relocation. */ |
481 | 0 | address = sframe_read_value (abfd, contents, r_offset, 4); |
482 | 0 | if (pltn_reloc_by_hand) |
483 | 0 | address += sframe_read_value (abfd, contents, |
484 | 0 | pltn_r_offset, 4); |
485 | 0 | address += (sec->output_offset + r_offset); |
486 | | |
487 | | /* FIXME For testing only. Cleanup later. */ |
488 | | // address += (sec->output_section->vma); |
489 | |
|
490 | 0 | func_start_addr = address; |
491 | 0 | } |
492 | | |
493 | | /* Update the encoder context with updated content. */ |
494 | 0 | int err = sframe_encoder_add_funcdesc_v2 (sfe_ctx, func_start_addr, |
495 | 0 | func_size, func_info, |
496 | 0 | rep_block_size, num_fres); |
497 | 0 | cur_fidx++; |
498 | 0 | BFD_ASSERT (!err); |
499 | 0 | } |
500 | | |
501 | 0 | for (j = 0; j < num_fres; j++) |
502 | 0 | { |
503 | 0 | sframe_frame_row_entry fre; |
504 | 0 | if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre)) |
505 | 0 | { |
506 | 0 | int err = sframe_encoder_add_fre (sfe_ctx, |
507 | 0 | cur_fidx-1+num_enc_fidx, |
508 | 0 | &fre); |
509 | 0 | BFD_ASSERT (!err); |
510 | 0 | } |
511 | 0 | } |
512 | 0 | } |
513 | | /* Free the SFrame decoder context. */ |
514 | 0 | sframe_decoder_free (&sfd_ctx); |
515 | |
|
516 | 0 | return true; |
517 | 0 | } |
518 | | |
519 | | /* Write out the .sframe section. This must be called after |
520 | | _bfd_elf_merge_section_sframe has been called on all input |
521 | | .sframe sections. */ |
522 | | |
523 | | bool |
524 | | _bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info) |
525 | 0 | { |
526 | 0 | bool retval = true; |
527 | |
|
528 | 0 | struct elf_link_hash_table *htab; |
529 | 0 | struct sframe_enc_info *sfe_info; |
530 | 0 | sframe_encoder_ctx *sfe_ctx; |
531 | 0 | asection *sec; |
532 | 0 | void *contents; |
533 | 0 | size_t sec_size; |
534 | 0 | int err = 0; |
535 | |
|
536 | 0 | htab = elf_hash_table (info); |
537 | 0 | sfe_info = &htab->sfe_info; |
538 | 0 | sec = sfe_info->sframe_section; |
539 | 0 | sfe_ctx = sfe_info->sfe_ctx; |
540 | |
|
541 | 0 | if (sec == NULL) |
542 | 0 | return true; |
543 | | |
544 | 0 | contents = sframe_encoder_write (sfe_ctx, &sec_size, &err); |
545 | 0 | sec->size = (bfd_size_type) sec_size; |
546 | |
|
547 | 0 | if (!bfd_set_section_contents (abfd, sec->output_section, contents, |
548 | 0 | (file_ptr) sec->output_offset, |
549 | 0 | sec->size)) |
550 | 0 | retval = false; |
551 | 0 | else if (!bfd_link_relocatable (info)) |
552 | 0 | { |
553 | 0 | Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr; |
554 | 0 | hdr->sh_size = sec->size; |
555 | 0 | } |
556 | | /* For relocatable links, do not update the section size as the section |
557 | | contents have not been relocated. */ |
558 | |
|
559 | 0 | sframe_encoder_free (&sfe_ctx); |
560 | |
|
561 | 0 | return retval; |
562 | 0 | } |