1/* .sframe section processing. 2 Copyright (C) 2022-2024 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 30static bool 31sframe_decoder_func_deleted_p (struct sframe_dec_info *sfd_info, 32 unsigned int func_idx) 33{ 34 if (func_idx < sfd_info->sfd_fde_count) 35 return sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p; 36 37 return false; 38} 39 40/* Mark the function in the decoder info for deletion. */ 41 42static void 43sframe_decoder_mark_func_deleted (struct sframe_dec_info *sfd_info, 44 unsigned int func_idx) 45{ 46 if (func_idx < sfd_info->sfd_fde_count) 47 sfd_info->sfd_func_bfdinfo[func_idx].func_deleted_p = true; 48} 49 50/* Get the relocation offset from the decoder info for the given function. */ 51 52static unsigned int 53sframe_decoder_get_func_r_offset (struct sframe_dec_info *sfd_info, 54 unsigned int func_idx) 55{ 56 BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); 57 unsigned int func_r_offset 58 = sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset; 59 /* There must have been a reloc. */ 60 BFD_ASSERT (func_r_offset); 61 return func_r_offset; 62} 63 64/* Bookkeep the function relocation offset in the decoder info. */ 65 66static void 67sframe_decoder_set_func_r_offset (struct sframe_dec_info *sfd_info, 68 unsigned int func_idx, 69 unsigned int r_offset) 70{ 71 if (func_idx < sfd_info->sfd_fde_count) 72 sfd_info->sfd_func_bfdinfo[func_idx].func_r_offset = r_offset; 73} 74 75/* Get the relocation index in the elf_reloc_cookie for the function. */ 76 77static unsigned int 78sframe_decoder_get_func_reloc_index (struct sframe_dec_info *sfd_info, 79 unsigned int func_idx) 80{ 81 BFD_ASSERT (func_idx < sfd_info->sfd_fde_count); 82 return sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index; 83} 84 85/* Bookkeep the relocation index in the elf_reloc_cookie for the function. */ 86 87static void 88sframe_decoder_set_func_reloc_index (struct sframe_dec_info *sfd_info, 89 unsigned int func_idx, 90 unsigned int reloc_index) 91{ 92 if (func_idx < sfd_info->sfd_fde_count) 93 sfd_info->sfd_func_bfdinfo[func_idx].func_reloc_index = reloc_index; 94} 95 96/* Initialize the set of additional information in CFD_INFO, 97 needed for linking SEC. Returns TRUE if setup is done successfully. */ 98 99static bool 100sframe_decoder_init_func_bfdinfo (asection *sec, 101 struct sframe_dec_info *sfd_info, 102 struct elf_reloc_cookie *cookie) 103{ 104 unsigned int fde_count; 105 unsigned int func_bfdinfo_size, i; 106 107 fde_count = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); 108 sfd_info->sfd_fde_count = fde_count; 109 110 /* Allocate and clear the memory. */ 111 func_bfdinfo_size = (sizeof (struct sframe_func_bfdinfo)) * fde_count; 112 sfd_info->sfd_func_bfdinfo 113 = (struct sframe_func_bfdinfo*) bfd_malloc (func_bfdinfo_size); 114 if (sfd_info->sfd_func_bfdinfo == NULL) 115 return false; 116 memset (sfd_info->sfd_func_bfdinfo, 0, func_bfdinfo_size); 117 118 /* For linker generated .sframe sections, we have no relocs. Skip. */ 119 if ((sec->flags & SEC_LINKER_CREATED) && cookie->rels == NULL) 120 return true; 121 122 for (i = 0; i < fde_count; i++) 123 { 124 cookie->rel = cookie->rels + i; 125 BFD_ASSERT (cookie->rel < cookie->relend); 126 /* Bookkeep the relocation offset and relocation index of each function 127 for later use. */ 128 sframe_decoder_set_func_r_offset (sfd_info, i, cookie->rel->r_offset); 129 sframe_decoder_set_func_reloc_index (sfd_info, i, 130 (cookie->rel - cookie->rels)); 131 132 cookie->rel++; 133 } 134 BFD_ASSERT (cookie->rel == cookie->relend); 135 136 return true; 137} 138 139/* Read the value from CONTENTS at the specified OFFSET for the given ABFD. */ 140 141static bfd_vma 142sframe_read_value (bfd *abfd, bfd_byte *contents, unsigned int offset, 143 unsigned int width) 144{ 145 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 BFD_ASSERT (width == 4); 149 /* FIXME endianness ?? */ 150 unsigned char *buf = contents + offset; 151 bfd_vma value = bfd_get_signed_32 (abfd, buf); 152 return value; 153} 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 159bool 160_bfd_elf_sframe_present (struct bfd_link_info *info) 161{ 162 asection *sframe = bfd_get_section_by_name (info->output_bfd, ".sframe"); 163 164 if (sframe == NULL) 165 return false; 166 167 /* Count only sections which have at least a single FDE. */ 168 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 if (sframe->size > sizeof (sframe_header)) 174 return true; 175 return false; 176} 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 184bool 185_bfd_elf_parse_sframe (bfd *abfd, 186 struct bfd_link_info *info ATTRIBUTE_UNUSED, 187 asection *sec, struct elf_reloc_cookie *cookie) 188{ 189 bfd_byte *sfbuf = NULL; 190 struct sframe_dec_info *sfd_info; 191 sframe_decoder_ctx *sfd_ctx; 192 bfd_size_type sf_size; 193 int decerr = 0; 194 195 if (sec->size == 0 196 || (sec->flags & SEC_HAS_CONTENTS) == 0 197 || sec->sec_info_type != SEC_INFO_TYPE_NONE) 198 { 199 /* This file does not contain .sframe information. */ 200 return false; 201 } 202 203 if (bfd_is_abs_section (sec->output_section)) 204 { 205 /* At least one of the sections is being discarded from the 206 link, so we should just ignore them. */ 207 return false; 208 } 209 210 /* Read the SFrame stack trace information from abfd. */ 211 if (!bfd_malloc_and_get_section (abfd, sec, &sfbuf)) 212 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 sfd_info = bfd_malloc (sizeof (struct sframe_dec_info)); 218 sf_size = sec->size; 219 220 sfd_info->sfd_ctx = sframe_decode ((const char*)sfbuf, sf_size, &decerr); 221 sfd_ctx = sfd_info->sfd_ctx; 222 if (!sfd_ctx) 223 /* Free'ing up any memory held by decoder context is done by 224 sframe_decode in case of error. */ 225 goto fail_no_free; 226 227 if (!sframe_decoder_init_func_bfdinfo (sec, sfd_info, cookie)) 228 { 229 sframe_decoder_free (&sfd_ctx); 230 goto fail_no_free; 231 } 232 233 elf_section_data (sec)->sec_info = sfd_info; 234 sec->sec_info_type = SEC_INFO_TYPE_SFRAME; 235 236 goto success; 237 238fail_no_free: 239 _bfd_error_handler 240 (_("error in %pB(%pA); no .sframe will be created"), 241 abfd, sec); 242 return false; 243success: 244 free (sfbuf); 245 return true; 246} 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 254bool 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{ 260 bool changed; 261 bool keep; 262 unsigned int i; 263 unsigned int func_desc_offset; 264 unsigned int num_fidx; 265 struct sframe_dec_info *sfd_info; 266 267 changed = false; 268 /* FIXME - if relocatable link and changed = true, how does the final 269 .rela.sframe get updated ?. */ 270 keep = false; 271 272 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 if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL) 277 { 278 num_fidx = sframe_decoder_get_num_fidx (sfd_info->sfd_ctx); 279 for (i = 0; i < num_fidx; i++) 280 { 281 func_desc_offset = sframe_decoder_get_func_r_offset (sfd_info, i); 282 283 cookie->rel = cookie->rels 284 + sframe_decoder_get_func_reloc_index (sfd_info, i); 285 keep = !(*reloc_symbol_deleted_p) (func_desc_offset, cookie); 286 287 if (!keep) 288 { 289 sframe_decoder_mark_func_deleted (sfd_info, i); 290 changed = true; 291 } 292 } 293 } 294 return changed; 295} 296 297/* Update the reference to the output .sframe section in the output ELF 298 BFD ABFD. Returns true if no error. */ 299 300bool 301_bfd_elf_set_section_sframe (bfd *abfd, 302 struct bfd_link_info *info) 303{ 304 asection *cfsec; 305 306 cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe"); 307 if (!cfsec) 308 return false; 309 310 elf_sframe (abfd) = cfsec; 311 312 return true; 313} 314 315/* Merge .sframe section SEC. This is called with the relocated 316 CONTENTS. */ 317 318bool 319_bfd_elf_merge_section_sframe (bfd *abfd, 320 struct bfd_link_info *info, 321 asection *sec, 322 bfd_byte *contents) 323{ 324 struct sframe_dec_info *sfd_info; 325 struct sframe_enc_info *sfe_info; 326 sframe_decoder_ctx *sfd_ctx; 327 sframe_encoder_ctx *sfe_ctx; 328 uint8_t sfd_ctx_abi_arch; 329 int8_t sfd_ctx_fixed_fp_offset; 330 int8_t sfd_ctx_fixed_ra_offset; 331 uint8_t dctx_version; 332 uint8_t ectx_version; 333 int encerr = 0; 334 335 struct elf_link_hash_table *htab; 336 asection *cfsec; 337 338 /* Sanity check - handle SFrame sections only. */ 339 if (sec->sec_info_type != SEC_INFO_TYPE_SFRAME) 340 return false; 341 342 sfd_info = (struct sframe_dec_info *) elf_section_data (sec)->sec_info; 343 sfd_ctx = sfd_info->sfd_ctx; 344 345 htab = elf_hash_table (info); 346 sfe_info = &(htab->sfe_info); 347 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 if (sfd_ctx == NULL || sfe_info == NULL) 354 return false; 355 356 if (htab->sfe_info.sfe_ctx == NULL) 357 { 358 sfd_ctx_abi_arch = sframe_decoder_get_abi_arch (sfd_ctx); 359 sfd_ctx_fixed_fp_offset = sframe_decoder_get_fixed_fp_offset (sfd_ctx); 360 sfd_ctx_fixed_ra_offset = sframe_decoder_get_fixed_ra_offset (sfd_ctx); 361 362 /* Valid values are non-zero. */ 363 if (!sfd_ctx_abi_arch) 364 return false; 365 366 htab->sfe_info.sfe_ctx = sframe_encode (SFRAME_VERSION_2, 367 0, /* SFrame flags. */ 368 sfd_ctx_abi_arch, 369 sfd_ctx_fixed_fp_offset, 370 sfd_ctx_fixed_ra_offset, 371 &encerr); 372 /* Handle errors from sframe_encode. */ 373 if (htab->sfe_info.sfe_ctx == NULL) 374 return false; 375 } 376 sfe_ctx = sfe_info->sfe_ctx; 377 378 if (sfe_info->sframe_section == NULL) 379 { 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 cfsec = bfd_get_section_by_name (info->output_bfd, ".sframe"); 385 if (cfsec) 386 { 387 sfe_info->sframe_section = cfsec; 388 // elf_sframe (abfd) = cfsec; 389 } 390 else 391 return false; 392 } 393 394 /* Check that all .sframe sections being linked have the same 395 ABI/arch. */ 396 if (sframe_decoder_get_abi_arch (sfd_ctx) 397 != sframe_encoder_get_abi_arch (sfe_ctx)) 398 { 399 _bfd_error_handler 400 (_("input SFrame sections with different abi prevent .sframe" 401 " generation")); 402 return false; 403 } 404 405 /* Check that all .sframe sections being linked have the same version. */ 406 dctx_version = sframe_decoder_get_version (sfd_ctx); 407 ectx_version = sframe_encoder_get_version (sfe_ctx); 408 if (dctx_version != SFRAME_VERSION_2 || dctx_version != ectx_version) 409 { 410 _bfd_error_handler 411 (_("input SFrame sections with different format versions prevent" 412 " .sframe generation")); 413 return false; 414 } 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 uint32_t i = 0, j = 0, cur_fidx = 0; 421 422 uint32_t num_fidx = sframe_decoder_get_num_fidx (sfd_ctx); 423 uint32_t num_enc_fidx = sframe_encoder_get_num_fidx (sfe_ctx); 424 425 for (i = 0; i < num_fidx; i++) 426 { 427 unsigned int num_fres = 0; 428 int32_t func_start_addr; 429 bfd_vma address; 430 uint32_t func_size = 0; 431 unsigned char func_info = 0; 432 unsigned int r_offset = 0; 433 bool pltn_reloc_by_hand = false; 434 unsigned int pltn_r_offset = 0; 435 uint8_t rep_block_size = 0; 436 437 if (!sframe_decoder_get_funcdesc_v2 (sfd_ctx, i, &num_fres, &func_size, 438 &func_start_addr, &func_info, 439 &rep_block_size)) 440 { 441 /* If function belongs to a deleted section, skip editing the 442 function descriptor entry. */ 443 if (sframe_decoder_func_deleted_p(sfd_info, i)) 444 continue; 445 446 /* Don't edit function descriptor entries for relocatable link. */ 447 if (!bfd_link_relocatable (info)) 448 { 449 if (!(sec->flags & SEC_LINKER_CREATED)) 450 { 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 r_offset = sframe_decoder_get_func_r_offset (sfd_info, i); 455 } 456 else 457 { 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 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 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 if (i > 0) 473 { 474 pltn_r_offset 475 = r_offset + (i * sizeof (sframe_func_desc_entry)); 476 pltn_reloc_by_hand = true; 477 } 478 } 479 480 /* Get the SFrame FDE function start address after relocation. */ 481 address = sframe_read_value (abfd, contents, r_offset, 4); 482 if (pltn_reloc_by_hand) 483 address += sframe_read_value (abfd, contents, 484 pltn_r_offset, 4); 485 address += (sec->output_offset + r_offset); 486 487 /* FIXME For testing only. Cleanup later. */ 488 // address += (sec->output_section->vma); 489 490 func_start_addr = address; 491 } 492 493 /* Update the encoder context with updated content. */ 494 int err = sframe_encoder_add_funcdesc_v2 (sfe_ctx, func_start_addr, 495 func_size, func_info, 496 rep_block_size, num_fres); 497 cur_fidx++; 498 BFD_ASSERT (!err); 499 } 500 501 for (j = 0; j < num_fres; j++) 502 { 503 sframe_frame_row_entry fre; 504 if (!sframe_decoder_get_fre (sfd_ctx, i, j, &fre)) 505 { 506 int err = sframe_encoder_add_fre (sfe_ctx, 507 cur_fidx-1+num_enc_fidx, 508 &fre); 509 BFD_ASSERT (!err); 510 } 511 } 512 } 513 /* Free the SFrame decoder context. */ 514 sframe_decoder_free (&sfd_ctx); 515 516 return true; 517} 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 523bool 524_bfd_elf_write_section_sframe (bfd *abfd, struct bfd_link_info *info) 525{ 526 bool retval = true; 527 528 struct elf_link_hash_table *htab; 529 struct sframe_enc_info *sfe_info; 530 sframe_encoder_ctx *sfe_ctx; 531 asection *sec; 532 void *contents; 533 size_t sec_size; 534 int err = 0; 535 536 htab = elf_hash_table (info); 537 sfe_info = &htab->sfe_info; 538 sec = sfe_info->sframe_section; 539 sfe_ctx = sfe_info->sfe_ctx; 540 541 if (sec == NULL) 542 return true; 543 544 contents = sframe_encoder_write (sfe_ctx, &sec_size, &err); 545 sec->size = (bfd_size_type) sec_size; 546 547 if (!bfd_set_section_contents (abfd, sec->output_section, contents, 548 (file_ptr) sec->output_offset, 549 sec->size)) 550 retval = false; 551 else if (!bfd_link_relocatable (info)) 552 { 553 Elf_Internal_Shdr *hdr = &elf_section_data (sec)->this_hdr; 554 hdr->sh_size = sec->size; 555 } 556 /* For relocatable links, do not update the section size as the section 557 contents have not been relocated. */ 558 559 sframe_encoder_free (&sfe_ctx); 560 561 return retval; 562} 563