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