1 1.1 christos /* .sframe section processing. 2 1.1.1.3 christos Copyright (C) 2022-2025 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.1.3 christos #include "sframe-internal.h" 27 1.1 christos 28 1.1 christos /* Return TRUE if the function has been marked for deletion during the linking 29 1.1 christos process. */ 30 1.1 christos 31 1.1 christos static bool 32 1.1 christos sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info, 33 1.1 christos unsigned int func_idx) 34 1.1 christos { 35 1.1 christos if (func_idx < sfd_info->sfd_fde_count) 36 1.1 christos return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p; 37 1.1 christos 38 1.1 christos return false; 39 1.1 christos } 40 1.1 christos 41 1.1 christos /* Mark the function in the decoder info for deletion. */ 42 1.1 christos 43 1.1 christos static void 44 1.1 christos sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info, 45 1.1 christos unsigned int func_idx) 46 1.1 christos { 47 1.1 christos if (func_idx < sfd_info->sfd_fde_count) 48 1.1 christos sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p = true; 49 1.1 christos } 50 1.1 christos 51 1.1 christos /* Get the relocation offset from the decoder info for the given function. */ 52 1.1 christos 53 1.1 christos static unsigned int 54 1.1 christos sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info, 55 1.1 christos unsigned int func_idx) 56 1.1 christos { 57 1.1 christos BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); 58 1.1 christos unsigned int func_r_offset 59 1.1 christos = sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset; 60 1.1 christos /* There must have been a reloc. */ 61 1.1 christos BFD_ASSERT (func_r_offset); 62 1.1 christos return func_r_offset; 63 1.1 christos } 64 1.1 christos 65 1.1 christos /* Bookkeep the function relocation offset in the decoder info. */ 66 1.1 christos 67 1.1 christos static void 68 1.1 christos sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info, 69 1.1 christos unsigned int func_idx, 70 1.1 christos unsigned int r_offset) 71 1.1 christos { 72 1.1 christos if (func_idx < sfd_info->sfd_fde_count) 73 1.1 christos sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset = r_offset; 74 1.1 christos } 75 1.1 christos 76 1.1 christos /* Get the relocation index in the elf_reloc_cookie for the function. */ 77 1.1 christos 78 1.1 christos static unsigned int 79 1.1 christos sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info, 80 1.1 christos unsigned int func_idx) 81 1.1 christos { 82 1.1 christos BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); 83 1.1 christos return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index; 84 1.1 christos } 85 1.1 christos 86 1.1 christos /* Bookkeep the relocation index in the elf_reloc_cookie for the function. */ 87 1.1 christos 88 1.1 christos static void 89 1.1 christos sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info, 90 1.1 christos unsigned int func_idx, 91 1.1 christos unsigned int reloc_index) 92 1.1 christos { 93 1.1 christos if (func_idx < sfd_info->sfd_fde_count) 94 1.1 christos sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index; 95 1.1 christos } 96 1.1 christos 97 1.1 christos /* Initialize the set of additional information in CFD_INFO, 98 1.1 christos needed for linking SEC. Returns TRUE if setup is done successfully. */ 99 1.1 christos 100 1.1 christos static bool 101 1.1.1.3 christos sframe_decoder_init_func_bfdinfo (bfd *abfd, 102 1.1.1.3 christos const asection *sec, 103 1.1 christos struct sframe_dec_info *sfd_info, 104 1.1.1.3 christos const struct elf_reloc_cookie *cookie) 105 1.1 christos { 106 1.1 christos unsigned int fde_count; 107 1.1 christos unsigned int func_bfdinfo_size, i; 108 1.1.1.3 christos const Elf_Internal_Rela *rel; 109 1.1 christos 110 1.1 christos fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); 111 1.1 christos sfd_info->sfd_fde_count = fde_count; 112 1.1 christos 113 1.1 christos /* Allocate and clear the memory. */ 114 1.1 christos func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count; 115 1.1.1.3 christos sfd_info->sfd_func_bfdinfo = bfd_zalloc (abfd, func_bfdinfo_size); 116 1.1 christos if (sfd_info->sfd_func_bfdinfo == NULL) 117 1.1 christos return false; 118 1.1 christos 119 1.1 christos /* For linker generated .sframe sections, we have no relocs. Skip. */ 120 1.1 christos if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL) 121 1.1 christos return true; 122 1.1 christos 123 1.1.1.3 christos rel = cookie->rels; 124 1.1 christos for (i = 0; i < fde_count; i++) 125 1.1 christos { 126 1.1 christos /* Bookkeep the relocation offset and relocation index of each function 127 1.1 christos for later use. */ 128 1.1.1.3 christos sframe_decoder_set_func_r_offset (sfd_info, i, rel->r_offset); 129 1.1.1.3 christos sframe_decoder_set_func_reloc_index (sfd_info, i, i); 130 1.1 christos 131 1.1.1.3 christos rel++; 132 1.1 christos } 133 1.1.1.3 christos 134 1.1.1.3 christos /* If there are more relocation entries, they must be R_*_NONE which 135 1.1.1.3 christos may be generated from relocations against discarded sections by 136 1.1.1.3 christos ld -r. */ 137 1.1.1.3 christos for (; rel < cookie->relend; rel++) 138 1.1.1.3 christos if (rel->r_info != 0) 139 1.1.1.3 christos break; 140 1.1.1.3 christos BFD_ASSERT (rel == cookie->relend); 141 1.1 christos 142 1.1 christos return true; 143 1.1 christos } 144 1.1 christos 145 1.1 christos /* Read the value from CONTENTS at the specified OFFSET for the given ABFD. */ 146 1.1 christos 147 1.1 christos static bfd_vma 148 1.1 christos sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset, 149 1.1 christos unsigned int width) 150 1.1 christos { 151 1.1 christos BFD_ASSERT (contents && offset); 152 1.1 christos /* Supporting the usecase of reading only the 4-byte relocated 153 1.1 christos value (signed offset for func start addr) for now. */ 154 1.1 christos BFD_ASSERT (width == 4); 155 1.1 christos /* FIXME endianness ?? */ 156 1.1 christos unsigned char *buf = contents + offset; 157 1.1 christos bfd_vma value = bfd_get_signed_32 (abfd, buf); 158 1.1 christos return value; 159 1.1 christos } 160 1.1 christos 161 1.1 christos /* Return true if there is at least one non-empty .sframe section in 162 1.1 christos input files. Can only be called after ld has mapped input to 163 1.1 christos output sections, and before sections are stripped. */ 164 1.1 christos 165 1.1 christos bool 166 1.1 christos _bfd_elf_sframe_present (struct bfd_link_info *info) 167 1.1 christos { 168 1.1 christos asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe"); 169 1.1 christos 170 1.1 christos if (sframe == NULL) 171 1.1 christos return false; 172 1.1 christos 173 1.1 christos /* Count only sections which have at least a single FDE. */ 174 1.1 christos for (sframe = sframe->map_head.s; sframe != NULL; sframe = sframe->map_head.s) 175 1.1 christos /* Note that this may become an approximate check in the future when 176 1.1 christos some ABI/arch begin to use the sfh_auxhdr_len. When sfh_auxhdr_len has 177 1.1 christos non-zero value, it will need to be accounted for in the calculation of 178 1.1 christos the SFrame header size. */ 179 1.1 christos if (sframe->size > sizeof (sframe_header)) 180 1.1 christos return true; 181 1.1 christos return false; 182 1.1 christos } 183 1.1 christos 184 1.1 christos /* Try to parse .sframe section SEC, which belongs to ABFD. Store the 185 1.1 christos information in the section's sec_info field on success. COOKIE 186 1.1 christos describes the relocations in SEC. 187 1.1 christos 188 1.1 christos Returns TRUE if success, FALSE if any error or failure. */ 189 1.1 christos 190 1.1 christos bool 191 1.1 christos _bfd_elf_parse_sframe (bfd *abfd, 192 1.1 christos struct bfd_link_info *info ATTRIBUTE_UNUSED, 193 1.1 christos asection *sec, struct elf_reloc_cookie *cookie) 194 1.1 christos { 195 1.1 christos bfd_byte *sfbuf = NULL; 196 1.1 christos struct sframe_dec_info *sfd_info; 197 1.1 christos sframe_decoder_ctx *sfd_ctx; 198 1.1 christos bfd_size_type sf_size; 199 1.1 christos int decerr = 0; 200 1.1 christos 201 1.1.1.3 christos /* Prior versions of assembler and ld were generating SFrame sections with 202 1.1.1.3 christos section type SHT_PROGBITS. Issue an error for lack of support for such 203 1.1.1.3 christos objects now. Even if section size is zero, a valid section type is 204 1.1.1.3 christos expected. */ 205 1.1.1.3 christos if (elf_section_type (sec) != SHT_GNU_SFRAME) 206 1.1.1.3 christos { 207 1.1.1.3 christos _bfd_error_handler 208 1.1.1.3 christos (_("error in %pB(%pA); unexpected SFrame section type"), 209 1.1.1.3 christos abfd, sec); 210 1.1.1.3 christos return false; 211 1.1.1.3 christos } 212 1.1.1.3 christos 213 1.1 christos if (sec->size == 0 214 1.1.1.2 christos || (sec->flags & SEC_HAS_CONTENTS) == 0 215 1.1 christos || sec->sec_info_type != SEC_INFO_TYPE_NONE) 216 1.1 christos { 217 1.1 christos /* This file does not contain .sframe information. */ 218 1.1 christos return false; 219 1.1 christos } 220 1.1 christos 221 1.1 christos if (bfd_is_abs_section (sec->output_section)) 222 1.1 christos { 223 1.1 christos /* At least one of the sections is being discarded from the 224 1.1 christos link, so we should just ignore them. */ 225 1.1 christos return false; 226 1.1 christos } 227 1.1 christos 228 1.1.1.2 christos /* Read the SFrame stack trace information from abfd. */ 229 1.1.1.2 christos if (!_bfd_elf_mmap_section_contents (abfd, sec, &sfbuf)) 230 1.1 christos goto fail_no_free; 231 1.1 christos 232 1.1 christos /* Decode the buffer and keep decoded contents for later use. 233 1.1 christos Relocations are performed later, but are such that the section's 234 1.1 christos size is unaffected. */ 235 1.1.1.3 christos sfd_info = bfd_zalloc (abfd, sizeof (*sfd_info)); 236 1.1 christos sf_size = sec->size; 237 1.1 christos 238 1.1 christos sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr); 239 1.1.1.3 christos sfd_info->sfd_state = SFRAME_SEC_DECODED; 240 1.1 christos sfd_ctx = sfd_info->sfd_ctx; 241 1.1 christos if (!sfd_ctx) 242 1.1 christos /* Free'ing up any memory held by decoder context is done by 243 1.1 christos sframe_decode in case of error. */ 244 1.1 christos goto fail_no_free; 245 1.1 christos 246 1.1.1.3 christos if (!sframe_decoder_init_func_bfdinfo (abfd, sec, sfd_info, cookie)) 247 1.1 christos { 248 1.1 christos sframe_decoder_free (&sfd_ctx); 249 1.1 christos goto fail_no_free; 250 1.1 christos } 251 1.1 christos 252 1.1 christos elf_section_data (sec)->sec_info = sfd_info; 253 1.1 christos sec->sec_info_type = SEC_INFO_TYPE_SFRAME; 254 1.1 christos 255 1.1 christos goto success; 256 1.1 christos 257 1.1 christos fail_no_free: 258 1.1 christos _bfd_error_handler 259 1.1 christos (_("error in %pB(%pA); no .sframe will be created"), 260 1.1 christos abfd, sec); 261 1.1 christos return false; 262 1.1 christos success: 263 1.1.1.2 christos _bfd_elf_munmap_section_contents (sec, sfbuf); 264 1.1 christos return true; 265 1.1 christos } 266 1.1 christos 267 1.1 christos /* This function is called for each input file before the .sframe section 268 1.1 christos is relocated. It marks the SFrame FDE for the discarded functions for 269 1.1 christos deletion. 270 1.1 christos 271 1.1 christos The function returns TRUE iff any entries have been deleted. */ 272 1.1 christos 273 1.1 christos bool 274 1.1 christos _bfd_elf_discard_section_sframe 275 1.1 christos (asection *sec, 276 1.1 christos bool (*reloc_symbol_deleted_p) (bfd_vma, void *), 277 1.1 christos struct elf_reloc_cookie *cookie) 278 1.1 christos { 279 1.1 christos bool changed; 280 1.1 christos bool keep; 281 1.1 christos unsigned int i; 282 1.1 christos unsigned int func_desc_offset; 283 1.1 christos unsigned int num_fidx; 284 1.1 christos struct sframe_dec_info *sfd_info; 285 1.1 christos 286 1.1 christos changed = false; 287 1.1 christos /* FIXME - if relocatable link and changed = true, how does the final 288 1.1 christos .rela.sframe get updated ?. */ 289 1.1 christos keep = false; 290 1.1 christos 291 1.1 christos sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info; 292 1.1 christos 293 1.1 christos /* Skip checking for the linker created .sframe sections 294 1.1 christos (for PLT sections). */ 295 1.1 christos if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL) 296 1.1 christos { 297 1.1 christos num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); 298 1.1 christos for (i = 0; i < num_fidx; i++) 299 1.1 christos { 300 1.1 christos func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i); 301 1.1 christos 302 1.1 christos cookie->rel = cookie->rels 303 1.1 christos + sframe_decoder_get_func_reloc_index (sfd_info, i); 304 1.1 christos keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie); 305 1.1 christos 306 1.1 christos if (!keep) 307 1.1 christos { 308 1.1 christos sframe_decoder_mark_func_deleted (sfd_info, i); 309 1.1 christos changed = true; 310 1.1 christos } 311 1.1 christos } 312 1.1 christos } 313 1.1 christos return changed; 314 1.1 christos } 315 1.1 christos 316 1.1 christos /* Update the reference to the output .sframe section in the output ELF 317 1.1 christos BFD ABFD. Returns true if no error. */ 318 1.1 christos 319 1.1 christos bool 320 1.1.1.3 christos _bfd_elf_set_section_sframe (bfd *abfd, struct bfd_link_info *info) 321 1.1 christos { 322 1.1 christos asection *cfsec; 323 1.1 christos 324 1.1 christos cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe"); 325 1.1 christos if (!cfsec) 326 1.1 christos return false; 327 1.1 christos 328 1.1.1.3 christos elf_section_type (cfsec) = SHT_GNU_SFRAME; 329 1.1 christos elf_sframe (abfd) = cfsec; 330 1.1 christos 331 1.1 christos return true; 332 1.1 christos } 333 1.1 christos 334 1.1 christos /* Merge .sframe section SEC. This is called with the relocated 335 1.1 christos CONTENTS. */ 336 1.1 christos 337 1.1 christos bool 338 1.1 christos _bfd_elf_merge_section_sframe (bfd *abfd, 339 1.1 christos struct bfd_link_info *info, 340 1.1 christos asection *sec, 341 1.1 christos bfd_byte *contents) 342 1.1 christos { 343 1.1 christos struct sframe_dec_info *sfd_info; 344 1.1 christos struct sframe_enc_info *sfe_info; 345 1.1 christos sframe_decoder_ctx *sfd_ctx; 346 1.1 christos sframe_encoder_ctx *sfe_ctx; 347 1.1.1.2 christos uint8_t sfd_ctx_abi_arch; 348 1.1 christos int8_t sfd_ctx_fixed_fp_offset; 349 1.1 christos int8_t sfd_ctx_fixed_ra_offset; 350 1.1.1.2 christos uint8_t dctx_version; 351 1.1.1.2 christos uint8_t ectx_version; 352 1.1.1.3 christos uint8_t dctx_flags; 353 1.1.1.3 christos uint8_t ectx_flags; 354 1.1 christos int encerr = 0; 355 1.1 christos 356 1.1 christos struct elf_link_hash_table *htab; 357 1.1 christos asection *cfsec; 358 1.1 christos 359 1.1 christos /* Sanity check - handle SFrame sections only. */ 360 1.1 christos if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME) 361 1.1 christos return false; 362 1.1 christos 363 1.1 christos sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info; 364 1.1 christos sfd_ctx = sfd_info->sfd_ctx; 365 1.1 christos 366 1.1 christos htab = elf_hash_table (info); 367 1.1 christos sfe_info = &(htab->sfe_info); 368 1.1 christos sfe_ctx = sfe_info->sfe_ctx; 369 1.1 christos 370 1.1 christos /* All input bfds are expected to have a valid SFrame section. Even if 371 1.1 christos the SFrame section is empty with only a header, there must be a valid 372 1.1 christos SFrame decoder context by now. The SFrame encoder context, however, 373 1.1 christos will get set later here, if this is the first call to the function. */ 374 1.1 christos if (sfd_ctx == NULL || sfe_info == NULL) 375 1.1 christos return false; 376 1.1 christos 377 1.1.1.3 christos dctx_flags = sframe_decoder_get_flags (sfd_ctx); 378 1.1.1.3 christos 379 1.1 christos if (htab->sfe_info.sfe_ctx == NULL) 380 1.1 christos { 381 1.1 christos sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx); 382 1.1 christos sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx); 383 1.1 christos sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx); 384 1.1 christos 385 1.1 christos /* Valid values are non-zero. */ 386 1.1 christos if (!sfd_ctx_abi_arch) 387 1.1 christos return false; 388 1.1 christos 389 1.1.1.3 christos /* In-memory FDEs in the encoder object are unsorted during linking and 390 1.1.1.3 christos will be sorted before emission. Reset SFRAME_F_FDE_SORTED to aptly 391 1.1.1.3 christos reflect that (doing so has no other functional value at this time 392 1.1.1.3 christos though). */ 393 1.1.1.3 christos uint8_t tflags = dctx_flags & ~SFRAME_F_FDE_SORTED; 394 1.1.1.3 christos /* ld always generates an output section with 395 1.1.1.3 christos SFRAME_F_FDE_FUNC_START_PCREL flag set. Later using 396 1.1.1.3 christos SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS, it is enforced that the provided 397 1.1.1.3 christos input sections also have this flag set. */ 398 1.1.1.3 christos tflags |= SFRAME_F_FDE_FUNC_START_PCREL; 399 1.1.1.2 christos htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_2, 400 1.1.1.3 christos tflags, /* SFrame flags. */ 401 1.1 christos sfd_ctx_abi_arch, 402 1.1 christos sfd_ctx_fixed_fp_offset, 403 1.1 christos sfd_ctx_fixed_ra_offset, 404 1.1 christos &encerr); 405 1.1 christos /* Handle errors from sframe_encode. */ 406 1.1 christos if (htab->sfe_info.sfe_ctx == NULL) 407 1.1 christos return false; 408 1.1 christos } 409 1.1 christos sfe_ctx = sfe_info->sfe_ctx; 410 1.1 christos 411 1.1 christos if (sfe_info->sframe_section == NULL) 412 1.1 christos { 413 1.1 christos /* Make sure things are set for an eventual write. 414 1.1 christos Size of the output section is not known until 415 1.1 christos _bfd_elf_write_section_sframe is ready with the buffer 416 1.1 christos to write out. */ 417 1.1 christos cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe"); 418 1.1 christos if (cfsec) 419 1.1 christos { 420 1.1 christos sfe_info->sframe_section = cfsec; 421 1.1 christos // elf_sframe (abfd) = cfsec; 422 1.1 christos } 423 1.1 christos else 424 1.1 christos return false; 425 1.1 christos } 426 1.1 christos 427 1.1 christos /* Check that all .sframe sections being linked have the same 428 1.1 christos ABI/arch. */ 429 1.1 christos if (sframe_decoder_get_abi_arch (sfd_ctx) 430 1.1 christos != sframe_encoder_get_abi_arch (sfe_ctx)) 431 1.1 christos { 432 1.1 christos _bfd_error_handler 433 1.1 christos (_("input SFrame sections with different abi prevent .sframe" 434 1.1 christos " generation")); 435 1.1 christos return false; 436 1.1 christos } 437 1.1 christos 438 1.1.1.2 christos /* Check that all .sframe sections being linked have the same version. */ 439 1.1.1.2 christos dctx_version = sframe_decoder_get_version (sfd_ctx); 440 1.1.1.2 christos ectx_version = sframe_encoder_get_version (sfe_ctx); 441 1.1.1.2 christos if (dctx_version != SFRAME_VERSION_2 || dctx_version != ectx_version) 442 1.1.1.2 christos { 443 1.1.1.2 christos _bfd_error_handler 444 1.1.1.2 christos (_("input SFrame sections with different format versions prevent" 445 1.1.1.2 christos " .sframe generation")); 446 1.1.1.2 christos return false; 447 1.1.1.2 christos } 448 1.1.1.2 christos 449 1.1.1.3 christos /* Check that all SFrame sections being linked have the 'data encoding' 450 1.1.1.3 christos related flags set. The implementation does not support updating these 451 1.1.1.3 christos data encodings on the fly; confirm by checking the ectx_flags. */ 452 1.1.1.3 christos ectx_flags = sframe_encoder_get_flags (sfe_ctx); 453 1.1.1.3 christos if ((dctx_flags & ectx_flags & SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS) 454 1.1.1.3 christos != SFRAME_V2_GNU_AS_LD_ENCODING_FLAGS) 455 1.1.1.3 christos { 456 1.1.1.3 christos _bfd_error_handler 457 1.1.1.3 christos (_("SFrame sections with unexpected data encoding prevent" 458 1.1.1.3 christos " .sframe generation")); 459 1.1.1.3 christos return false; 460 1.1.1.3 christos } 461 1.1.1.2 christos 462 1.1 christos /* Iterate over the function descriptor entries and the FREs of the 463 1.1 christos function from the decoder context. Add each of them to the encoder 464 1.1 christos context, if suitable. */ 465 1.1.1.2 christos uint32_t i = 0, j = 0, cur_fidx = 0; 466 1.1 christos 467 1.1.1.2 christos uint32_t num_fidx = sframe_decoder_get_num_fidx (sfd_ctx); 468 1.1.1.2 christos uint32_t num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx); 469 1.1 christos 470 1.1 christos for (i = 0; i < num_fidx; i++) 471 1.1 christos { 472 1.1 christos unsigned int num_fres = 0; 473 1.1.1.2 christos int32_t func_start_addr; 474 1.1 christos bfd_vma address; 475 1.1 christos uint32_t func_size = 0; 476 1.1 christos unsigned char func_info = 0; 477 1.1 christos unsigned int r_offset = 0; 478 1.1 christos bool pltn_reloc_by_hand = false; 479 1.1 christos unsigned int pltn_r_offset = 0; 480 1.1.1.2 christos uint8_t rep_block_size = 0; 481 1.1 christos 482 1.1.1.2 christos if (!sframe_decoder_get_funcdesc_v2 (sfd_ctx, i, &num_fres, &func_size, 483 1.1.1.2 christos &func_start_addr, &func_info, 484 1.1.1.2 christos &rep_block_size)) 485 1.1 christos { 486 1.1 christos /* If function belongs to a deleted section, skip editing the 487 1.1 christos function descriptor entry. */ 488 1.1 christos if (sframe_decoder_func_deleted_p(sfd_info, i)) 489 1.1 christos continue; 490 1.1 christos 491 1.1 christos /* Don't edit function descriptor entries for relocatable link. */ 492 1.1 christos if (!bfd_link_relocatable (info)) 493 1.1 christos { 494 1.1 christos if (!(sec->flags & SEC_LINKER_CREATED)) 495 1.1 christos { 496 1.1 christos /* Get relocated contents by reading the value of the 497 1.1 christos relocated function start address at the beginning of the 498 1.1 christos function descriptor entry. */ 499 1.1 christos r_offset = sframe_decoder_get_func_r_offset (sfd_info, i); 500 1.1 christos } 501 1.1 christos else 502 1.1 christos { 503 1.1.1.2 christos /* Expected to land here when SFrame stack trace info is 504 1.1.1.2 christos created dynamically for the .plt* sections. These 505 1.1.1.2 christos sections are expected to have upto two SFrame FDE entries. 506 1.1.1.2 christos Although the code should work for > 2, leaving this 507 1.1.1.2 christos assert here for safety. */ 508 1.1 christos BFD_ASSERT (num_fidx <= 2); 509 1.1 christos /* For the first entry, we know the offset of the SFrame FDE's 510 1.1 christos sfde_func_start_address. Side note: see how the value 511 1.1 christos of PLT_SFRAME_FDE_START_OFFSET is also set to the 512 1.1 christos same. */ 513 1.1 christos r_offset = sframe_decoder_get_hdr_size (sfd_ctx); 514 1.1 christos /* For any further SFrame FDEs, the generator has already put 515 1.1 christos in an offset in place of sfde_func_start_address of the 516 1.1 christos corresponding FDE. We will use it by hand to relocate. */ 517 1.1 christos if (i > 0) 518 1.1 christos { 519 1.1 christos pltn_r_offset 520 1.1 christos = r_offset + (i * sizeof (sframe_func_desc_entry)); 521 1.1 christos pltn_reloc_by_hand = true; 522 1.1 christos } 523 1.1 christos } 524 1.1 christos 525 1.1 christos /* Get the SFrame FDE function start address after relocation. */ 526 1.1 christos address = sframe_read_value (abfd, contents, r_offset, 4); 527 1.1 christos if (pltn_reloc_by_hand) 528 1.1 christos address += sframe_read_value (abfd, contents, 529 1.1 christos pltn_r_offset, 4); 530 1.1 christos address += (sec->output_offset + r_offset); 531 1.1.1.3 christos /* SFrame FDE function start address is an offset from the 532 1.1.1.3 christos sfde_func_start_address field to the start PC. The 533 1.1.1.3 christos calculation below is the distance of sfde_func_start_address 534 1.1.1.3 christos field from the start of the output SFrame section. */ 535 1.1.1.3 christos uint32_t offsetof_fde_in_sec 536 1.1.1.3 christos = sframe_encoder_get_offsetof_fde_start_addr (sfe_ctx, 537 1.1.1.3 christos cur_fidx + num_enc_fidx, 538 1.1.1.3 christos NULL); 539 1.1.1.3 christos address -= offsetof_fde_in_sec; 540 1.1 christos 541 1.1 christos /* FIXME For testing only. Cleanup later. */ 542 1.1 christos // address += (sec->output_section->vma); 543 1.1 christos 544 1.1.1.2 christos func_start_addr = address; 545 1.1 christos } 546 1.1 christos 547 1.1 christos /* Update the encoder context with updated content. */ 548 1.1.1.2 christos int err = sframe_encoder_add_funcdesc_v2 (sfe_ctx, func_start_addr, 549 1.1.1.2 christos func_size, func_info, 550 1.1.1.2 christos rep_block_size, num_fres); 551 1.1 christos cur_fidx++; 552 1.1 christos BFD_ASSERT (!err); 553 1.1 christos } 554 1.1 christos 555 1.1 christos for (j = 0; j < num_fres; j++) 556 1.1 christos { 557 1.1 christos sframe_frame_row_entry fre; 558 1.1 christos if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre)) 559 1.1 christos { 560 1.1 christos int err = sframe_encoder_add_fre (sfe_ctx, 561 1.1 christos cur_fidx-1+num_enc_fidx, 562 1.1 christos &fre); 563 1.1 christos BFD_ASSERT (!err); 564 1.1 christos } 565 1.1 christos } 566 1.1 christos } 567 1.1.1.3 christos sfd_info->sfd_state = SFRAME_SEC_MERGED; 568 1.1 christos /* Free the SFrame decoder context. */ 569 1.1 christos sframe_decoder_free (&sfd_ctx); 570 1.1 christos 571 1.1 christos return true; 572 1.1 christos } 573 1.1 christos 574 1.1.1.3 christos /* Adjust an address in the .sframe section. Given OFFSET within 575 1.1.1.3 christos SEC, this returns the new offset in the merged .sframe section, 576 1.1.1.3 christos or -1 if the address refers to an FDE which has been removed. 577 1.1.1.3 christos 578 1.1.1.3 christos PS: This function assumes that _bfd_elf_merge_section_sframe has 579 1.1.1.3 christos not been called on the input section SEC yet. Note how it uses 580 1.1.1.3 christos sframe_encoder_get_num_fidx () to figure out the offset of FDE 581 1.1.1.3 christos in the output section. */ 582 1.1.1.3 christos 583 1.1.1.3 christos bfd_vma 584 1.1.1.3 christos _bfd_elf_sframe_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, 585 1.1.1.3 christos struct bfd_link_info *info, 586 1.1.1.3 christos asection *sec, 587 1.1.1.3 christos bfd_vma offset) 588 1.1.1.3 christos { 589 1.1.1.3 christos struct sframe_dec_info *sfd_info; 590 1.1.1.3 christos struct sframe_enc_info *sfe_info; 591 1.1.1.3 christos sframe_decoder_ctx *sfd_ctx; 592 1.1.1.3 christos sframe_encoder_ctx *sfe_ctx; 593 1.1.1.3 christos struct elf_link_hash_table *htab; 594 1.1.1.3 christos 595 1.1.1.3 christos unsigned int sec_fde_idx, out_num_fdes; 596 1.1.1.3 christos unsigned int sfd_num_fdes, sfe_num_fdes; 597 1.1.1.3 christos uint32_t sfd_fde_offset; 598 1.1.1.3 christos bfd_vma new_offset; 599 1.1.1.3 christos 600 1.1.1.3 christos if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME) 601 1.1.1.3 christos return offset; 602 1.1.1.3 christos 603 1.1.1.3 christos sfd_info = elf_section_data (sec)->sec_info; 604 1.1.1.3 christos sfd_ctx = sfd_info->sfd_ctx; 605 1.1.1.3 christos sfd_num_fdes = sframe_decoder_get_num_fidx (sfd_ctx); 606 1.1.1.3 christos 607 1.1.1.3 christos BFD_ASSERT (sfd_info->sfd_state == SFRAME_SEC_DECODED); 608 1.1.1.3 christos 609 1.1.1.3 christos htab = elf_hash_table (info); 610 1.1.1.3 christos sfe_info = &(htab->sfe_info); 611 1.1.1.3 christos sfe_ctx = sfe_info->sfe_ctx; 612 1.1.1.3 christos sfe_num_fdes = sframe_encoder_get_num_fidx (sfe_ctx); 613 1.1.1.3 christos 614 1.1.1.3 christos /* The index of this FDE in the output section depends on number of deleted 615 1.1.1.3 christos functions (between index 0 and sec_fde_idx), if any. */ 616 1.1.1.3 christos out_num_fdes = 0; 617 1.1.1.3 christos sec_fde_idx = 0; 618 1.1.1.3 christos for (unsigned int i = 0; i < sfd_num_fdes; i++) 619 1.1.1.3 christos { 620 1.1.1.3 christos sfd_fde_offset = sframe_decoder_get_offsetof_fde_start_addr (sfd_ctx, 621 1.1.1.3 christos i, NULL); 622 1.1.1.3 christos if (!sframe_decoder_func_deleted_p (sfd_info, i)) 623 1.1.1.3 christos out_num_fdes++; 624 1.1.1.3 christos 625 1.1.1.3 christos if (sfd_fde_offset == offset) 626 1.1.1.3 christos { 627 1.1.1.3 christos /* Found the index of the FDE (at OFFSET) in the input section. */ 628 1.1.1.3 christos sec_fde_idx = i; 629 1.1.1.3 christos break; 630 1.1.1.3 christos } 631 1.1.1.3 christos } 632 1.1.1.3 christos 633 1.1.1.3 christos if (sframe_decoder_func_deleted_p (sfd_info, sec_fde_idx)) 634 1.1.1.3 christos return (bfd_vma) -1; 635 1.1.1.3 christos 636 1.1.1.3 christos /* The number of FDEs in the output SFrame section. Note that the output 637 1.1.1.3 christos index of the FDE of interest will be (out_num_fdes - 1). */ 638 1.1.1.3 christos out_num_fdes += sfe_num_fdes; 639 1.1.1.3 christos 640 1.1.1.3 christos new_offset = sframe_decoder_get_offsetof_fde_start_addr (sfd_ctx, 641 1.1.1.3 christos out_num_fdes - 1, 642 1.1.1.3 christos NULL); 643 1.1.1.3 christos /* Recall that SFrame section merging has distinct requirements: All SFrame 644 1.1.1.3 christos FDEs from input sections are clubbed together in the beginning of the 645 1.1.1.3 christos output section. So, at this point in the current function, the new_offset 646 1.1.1.3 christos is the correct offset in the merged output SFrame section. Note, however, 647 1.1.1.3 christos that the default mechanism in the _elf_link_input_bfd will do the 648 1.1.1.3 christos following adjustment: 649 1.1.1.3 christos irela->r_offset += o->output_offset; 650 1.1.1.3 christos for all section types. However, such an adjustment in the RELA offset is 651 1.1.1.3 christos _not_ needed for SFrame sections. Perform the reverse adjustment here so 652 1.1.1.3 christos that the default mechanism does not need additional SFrame specific 653 1.1.1.3 christos checks. */ 654 1.1.1.3 christos new_offset -= sec->output_offset; 655 1.1.1.3 christos 656 1.1.1.3 christos return new_offset; 657 1.1.1.3 christos } 658 1.1.1.3 christos 659 1.1 christos /* Write out the .sframe section. This must be called after 660 1.1 christos _bfd_elf_merge_section_sframe has been called on all input 661 1.1 christos .sframe sections. */ 662 1.1 christos 663 1.1 christos bool 664 1.1 christos _bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info) 665 1.1 christos { 666 1.1 christos bool retval = true; 667 1.1 christos 668 1.1 christos struct elf_link_hash_table *htab; 669 1.1 christos struct sframe_enc_info *sfe_info; 670 1.1 christos sframe_encoder_ctx *sfe_ctx; 671 1.1 christos asection *sec; 672 1.1 christos void *contents; 673 1.1 christos size_t sec_size; 674 1.1 christos int err = 0; 675 1.1 christos 676 1.1 christos htab = elf_hash_table (info); 677 1.1 christos sfe_info = &htab->sfe_info; 678 1.1 christos sec = sfe_info->sframe_section; 679 1.1 christos sfe_ctx = sfe_info->sfe_ctx; 680 1.1 christos 681 1.1 christos if (sec == NULL) 682 1.1 christos return true; 683 1.1 christos 684 1.1 christos contents = sframe_encoder_write (sfe_ctx, &sec_size, &err); 685 1.1 christos sec->size = (bfd_size_type) sec_size; 686 1.1 christos 687 1.1 christos if (!bfd_set_section_contents (abfd, sec->output_section, contents, 688 1.1 christos (file_ptr) sec->output_offset, 689 1.1 christos sec->size)) 690 1.1 christos retval = false; 691 1.1.1.3 christos else 692 1.1 christos { 693 1.1 christos Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr; 694 1.1 christos hdr->sh_size = sec->size; 695 1.1 christos } 696 1.1 christos 697 1.1 christos sframe_encoder_free (&sfe_ctx); 698 1.1 christos 699 1.1 christos return retval; 700 1.1 christos } 701