1 /* sframe.c - SFrame decoder/encoder. 2 3 Copyright (C) 2022-2025 Free Software Foundation, Inc. 4 5 This file is part of libsframe. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <stdarg.h> 24 #include <string.h> 25 #include <stddef.h> 26 #include "sframe-impl.h" 27 #include "swap.h" 28 29 struct sf_fde_tbl 30 { 31 unsigned int count; 32 unsigned int alloced; 33 sframe_func_desc_entry entry[1]; 34 }; 35 36 struct sf_fre_tbl 37 { 38 unsigned int count; 39 unsigned int alloced; 40 sframe_frame_row_entry entry[1]; 41 }; 42 43 #define _sf_printflike_(string_index,first_to_check) \ 44 __attribute__ ((__format__ (__printf__, (string_index), (first_to_check)))) 45 46 static void debug_printf (const char *, ...); 47 48 static int _sframe_debug; /* Control for printing out debug info. */ 49 static int number_of_entries = 64; 50 51 static void 52 sframe_init_debug (void) 53 { 54 static int inited; 55 56 if (!inited) 57 { 58 _sframe_debug = getenv ("SFRAME_DEBUG") != NULL; 59 inited = 1; 60 } 61 } 62 63 _sf_printflike_ (1, 2) 64 static void debug_printf (const char *format, ...) 65 { 66 if (_sframe_debug) 67 { 68 va_list args; 69 70 va_start (args, format); 71 vfprintf (stderr, format, args); 72 va_end (args); 73 } 74 } 75 76 /* Generate bitmask of given size in bytes. This is used for 77 some checks on the FRE start address. 78 SFRAME_FRE_TYPE_ADDR1 => 1 byte => [ bitmask = 0xff ] 79 SFRAME_FRE_TYPE_ADDR2 => 2 byte => [ bitmask = 0xffff ] 80 SFRAME_FRE_TYPE_ADDR4 => 4 byte => [ bitmask = 0xffffffff ]. */ 81 #define SFRAME_BITMASK_OF_SIZE(size_in_bytes) \ 82 (((uint64_t)1 << (size_in_bytes*8)) - 1) 83 84 /* Store the specified error code into errp if it is non-NULL. 85 Return SFRAME_ERR. */ 86 87 static int 88 sframe_set_errno (int *errp, int error) 89 { 90 if (errp != NULL) 91 *errp = error; 92 return SFRAME_ERR; 93 } 94 95 /* Store the specified error code into errp if it is non-NULL. 96 Return NULL. */ 97 98 static void * 99 sframe_ret_set_errno (int *errp, int error) 100 { 101 if (errp != NULL) 102 *errp = error; 103 return NULL; 104 } 105 106 /* Get the SFrame header size. */ 107 108 static uint32_t 109 sframe_get_hdr_size (sframe_header *sfh) 110 { 111 return SFRAME_V1_HDR_SIZE (*sfh); 112 } 113 114 /* Access functions for frame row entry data. */ 115 116 static uint8_t 117 sframe_fre_get_offset_count (uint8_t fre_info) 118 { 119 return SFRAME_V1_FRE_OFFSET_COUNT (fre_info); 120 } 121 122 static uint8_t 123 sframe_fre_get_offset_size (uint8_t fre_info) 124 { 125 return SFRAME_V1_FRE_OFFSET_SIZE (fre_info); 126 } 127 128 static bool 129 sframe_get_fre_ra_mangled_p (uint8_t fre_info) 130 { 131 return SFRAME_V1_FRE_MANGLED_RA_P (fre_info); 132 } 133 134 /* Access functions for info from function descriptor entry. */ 135 136 static uint32_t 137 sframe_get_fre_type (sframe_func_desc_entry *fdep) 138 { 139 uint32_t fre_type = 0; 140 if (fdep) 141 fre_type = SFRAME_V1_FUNC_FRE_TYPE (fdep->sfde_func_info); 142 return fre_type; 143 } 144 145 static uint32_t 146 sframe_get_fde_type (sframe_func_desc_entry *fdep) 147 { 148 uint32_t fde_type = 0; 149 if (fdep) 150 fde_type = SFRAME_V1_FUNC_FDE_TYPE (fdep->sfde_func_info); 151 return fde_type; 152 } 153 154 /* Check if flipping is needed, based on ENDIAN. */ 155 156 static int 157 need_swapping (int endian) 158 { 159 unsigned int ui = 1; 160 char *c = (char *)&ui; 161 int is_little = (int)*c; 162 163 switch (endian) 164 { 165 case SFRAME_ABI_AARCH64_ENDIAN_LITTLE: 166 case SFRAME_ABI_AMD64_ENDIAN_LITTLE: 167 return !is_little; 168 case SFRAME_ABI_AARCH64_ENDIAN_BIG: 169 case SFRAME_ABI_S390X_ENDIAN_BIG: 170 return is_little; 171 default: 172 break; 173 } 174 175 return 0; 176 } 177 178 /* Flip the endianness of the SFrame header. */ 179 180 static void 181 flip_header (sframe_header *sfheader) 182 { 183 swap_thing (sfheader->sfh_preamble.sfp_magic); 184 swap_thing (sfheader->sfh_preamble.sfp_version); 185 swap_thing (sfheader->sfh_preamble.sfp_flags); 186 swap_thing (sfheader->sfh_cfa_fixed_fp_offset); 187 swap_thing (sfheader->sfh_cfa_fixed_ra_offset); 188 swap_thing (sfheader->sfh_num_fdes); 189 swap_thing (sfheader->sfh_num_fres); 190 swap_thing (sfheader->sfh_fre_len); 191 swap_thing (sfheader->sfh_fdeoff); 192 swap_thing (sfheader->sfh_freoff); 193 } 194 195 static void 196 flip_fde (sframe_func_desc_entry *fdep) 197 { 198 swap_thing (fdep->sfde_func_start_address); 199 swap_thing (fdep->sfde_func_size); 200 swap_thing (fdep->sfde_func_start_fre_off); 201 swap_thing (fdep->sfde_func_num_fres); 202 } 203 204 /* Check if SFrame header has valid data. */ 205 206 static bool 207 sframe_header_sanity_check_p (sframe_header *hp) 208 { 209 /* Check preamble is valid. */ 210 if (hp->sfh_preamble.sfp_magic != SFRAME_MAGIC 211 || (hp->sfh_preamble.sfp_version != SFRAME_VERSION_1 212 && hp->sfh_preamble.sfp_version != SFRAME_VERSION_2) 213 || (hp->sfh_preamble.sfp_flags & ~SFRAME_V2_F_ALL_FLAGS)) 214 return false; 215 216 /* Check offsets are valid. */ 217 if (hp->sfh_fdeoff > hp->sfh_freoff) 218 return false; 219 220 return true; 221 } 222 223 /* Flip the start address pointed to by FP. */ 224 225 static void 226 flip_fre_start_address (char *addr, uint32_t fre_type) 227 { 228 if (fre_type == SFRAME_FRE_TYPE_ADDR2) 229 { 230 uint16_t *start_addr = (uint16_t *)addr; 231 swap_thing (*start_addr); 232 } 233 else if (fre_type == SFRAME_FRE_TYPE_ADDR4) 234 { 235 uint32_t *start_addr = (uint32_t *)addr; 236 swap_thing (*start_addr); 237 } 238 } 239 240 static void 241 flip_fre_stack_offsets (char *offsets, uint8_t offset_size, uint8_t offset_cnt) 242 { 243 int j; 244 245 if (offset_size == SFRAME_FRE_OFFSET_2B) 246 { 247 uint16_t *ust = (uint16_t *)offsets; 248 for (j = offset_cnt; j > 0; ust++, j--) 249 swap_thing (*ust); 250 } 251 else if (offset_size == SFRAME_FRE_OFFSET_4B) 252 { 253 uint32_t *uit = (uint32_t *)offsets; 254 for (j = offset_cnt; j > 0; uit++, j--) 255 swap_thing (*uit); 256 } 257 } 258 259 /* Get the FRE start address size, given the FRE_TYPE. */ 260 261 static size_t 262 sframe_fre_start_addr_size (uint32_t fre_type) 263 { 264 size_t addr_size = 0; 265 switch (fre_type) 266 { 267 case SFRAME_FRE_TYPE_ADDR1: 268 addr_size = 1; 269 break; 270 case SFRAME_FRE_TYPE_ADDR2: 271 addr_size = 2; 272 break; 273 case SFRAME_FRE_TYPE_ADDR4: 274 addr_size = 4; 275 break; 276 default: 277 /* No other value is expected. */ 278 sframe_assert (0); 279 break; 280 } 281 return addr_size; 282 } 283 284 /* Check if the FREP has valid data. */ 285 286 static bool 287 sframe_fre_sanity_check_p (sframe_frame_row_entry *frep) 288 { 289 uint8_t offset_size, offset_cnt; 290 uint8_t fre_info; 291 292 if (frep == NULL) 293 return false; 294 295 fre_info = frep->fre_info; 296 offset_size = sframe_fre_get_offset_size (fre_info); 297 298 if (offset_size != SFRAME_FRE_OFFSET_1B 299 && offset_size != SFRAME_FRE_OFFSET_2B 300 && offset_size != SFRAME_FRE_OFFSET_4B) 301 return false; 302 303 offset_cnt = sframe_fre_get_offset_count (fre_info); 304 if (offset_cnt > MAX_NUM_STACK_OFFSETS) 305 return false; 306 307 return true; 308 } 309 310 /* Get FRE_INFO's offset size in bytes. */ 311 312 static size_t 313 sframe_fre_offset_bytes_size (uint8_t fre_info) 314 { 315 uint8_t offset_size, offset_cnt; 316 317 offset_size = sframe_fre_get_offset_size (fre_info); 318 319 debug_printf ("offset_size = %u\n", offset_size); 320 321 offset_cnt = sframe_fre_get_offset_count (fre_info); 322 323 if (offset_size == SFRAME_FRE_OFFSET_2B 324 || offset_size == SFRAME_FRE_OFFSET_4B) /* 2 or 4 bytes. */ 325 return (offset_cnt * (offset_size * 2)); 326 327 return (offset_cnt); 328 } 329 330 /* Get total size in bytes to represent FREP in the binary format. This 331 includes the starting address, FRE info, and all the offsets. */ 332 333 static size_t 334 sframe_fre_entry_size (sframe_frame_row_entry *frep, uint32_t fre_type) 335 { 336 if (frep == NULL) 337 return 0; 338 339 uint8_t fre_info = frep->fre_info; 340 size_t addr_size = sframe_fre_start_addr_size (fre_type); 341 342 return (addr_size + sizeof (frep->fre_info) 343 + sframe_fre_offset_bytes_size (fre_info)); 344 } 345 346 /* Get the function descriptor entry at index FUNC_IDX in the decoder 347 context CTX. */ 348 349 static sframe_func_desc_entry * 350 sframe_decoder_get_funcdesc_at_index (sframe_decoder_ctx *ctx, 351 uint32_t func_idx) 352 { 353 sframe_func_desc_entry *fdep; 354 uint32_t num_fdes; 355 int err; 356 357 num_fdes = sframe_decoder_get_num_fidx (ctx); 358 if (num_fdes == 0 359 || func_idx >= num_fdes 360 || ctx->sfd_funcdesc == NULL) 361 return sframe_ret_set_errno (&err, SFRAME_ERR_DCTX_INVAL); 362 363 fdep = &ctx->sfd_funcdesc[func_idx]; 364 return fdep; 365 } 366 367 /* Get the offset of the start PC of the SFrame FDE at FUNC_IDX from the start 368 of the SFrame section. This section-relative offset is used within 369 libsframe for sorting the SFrame FDEs, and also information lookup routines 370 like sframe_find_fre. 371 372 If FUNC_IDX is not a valid index in the given decoder object, returns 0. */ 373 374 static int32_t 375 sframe_decoder_get_secrel_func_start_addr (sframe_decoder_ctx *dctx, 376 uint32_t func_idx) 377 { 378 int err = 0; 379 int32_t offsetof_fde_in_sec 380 = sframe_decoder_get_offsetof_fde_start_addr (dctx, func_idx, &err); 381 /* If func_idx is not a valid index, return 0. */ 382 if (err) 383 return 0; 384 385 int32_t func_start_addr = dctx->sfd_funcdesc[func_idx].sfde_func_start_address; 386 387 return func_start_addr + offsetof_fde_in_sec; 388 } 389 390 /* Check whether for the given FDEP, the SFrame Frame Row Entry identified via 391 the START_IP_OFFSET and the END_IP_OFFSET, provides the stack trace 392 information for the PC. */ 393 394 static bool 395 sframe_fre_check_range_p (sframe_decoder_ctx *dctx, uint32_t func_idx, 396 uint32_t start_ip_offset, uint32_t end_ip_offset, 397 int32_t pc) 398 { 399 sframe_func_desc_entry *fdep; 400 int32_t func_start_addr; 401 uint8_t rep_block_size; 402 uint32_t fde_type; 403 uint32_t pc_offset; 404 bool mask_p; 405 406 fdep = &dctx->sfd_funcdesc[func_idx]; 407 func_start_addr = sframe_decoder_get_secrel_func_start_addr (dctx, func_idx); 408 fde_type = sframe_get_fde_type (fdep); 409 mask_p = (fde_type == SFRAME_FDE_TYPE_PCMASK); 410 rep_block_size = fdep->sfde_func_rep_size; 411 412 if (func_start_addr > pc) 413 return false; 414 415 /* Given func_start_addr <= pc, pc - func_start_addr must be positive. */ 416 pc_offset = pc - func_start_addr; 417 /* For SFrame FDEs encoding information for repetitive pattern of insns, 418 masking with the rep_block_size is necessary to find the matching FRE. */ 419 if (mask_p) 420 pc_offset = pc_offset % rep_block_size; 421 422 return (start_ip_offset <= pc_offset) && (end_ip_offset >= pc_offset); 423 } 424 425 static int 426 flip_fre (char *fp, uint32_t fre_type, size_t *fre_size) 427 { 428 uint8_t fre_info; 429 uint8_t offset_size, offset_cnt; 430 size_t addr_size, fre_info_size = 0; 431 int err = 0; 432 433 if (fre_size == NULL) 434 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 435 436 flip_fre_start_address (fp, fre_type); 437 438 /* Advance the buffer pointer to where the FRE info is. */ 439 addr_size = sframe_fre_start_addr_size (fre_type); 440 fp += addr_size; 441 442 /* FRE info is uint8_t. No need to flip. */ 443 fre_info = *(uint8_t*)fp; 444 offset_size = sframe_fre_get_offset_size (fre_info); 445 offset_cnt = sframe_fre_get_offset_count (fre_info); 446 447 /* Advance the buffer pointer to where the stack offsets are. */ 448 fre_info_size = sizeof (uint8_t); 449 fp += fre_info_size; 450 flip_fre_stack_offsets (fp, offset_size, offset_cnt); 451 452 *fre_size 453 = addr_size + fre_info_size + sframe_fre_offset_bytes_size (fre_info); 454 455 return 0; 456 } 457 458 /* Endian flip the contents of FRAME_BUF of size BUF_SIZE. 459 The SFrame header in the FRAME_BUF must be endian flipped prior to 460 calling flip_sframe. 461 462 Endian flipping at decode time vs encode time have different needs. At 463 encode time, the frame_buf is in host endianness, and hence, values should 464 be read up before the buffer is changed to foreign endianness. This change 465 of behaviour is specified via TO_FOREIGN arg. 466 467 If an error code is returned, the buffer should not be used. */ 468 469 static int 470 flip_sframe (char *frame_buf, size_t buf_size, uint32_t to_foreign) 471 { 472 unsigned int i, j, prev_frep_index; 473 sframe_header *ihp; 474 char *fdes; 475 char *fp = NULL; 476 sframe_func_desc_entry *fdep; 477 unsigned int num_fdes = 0; 478 unsigned int num_fres = 0; 479 uint32_t fre_type = 0; 480 uint32_t fre_offset = 0; 481 size_t esz = 0; 482 size_t hdrsz = 0; 483 int err = 0; 484 /* For error checking. */ 485 size_t bytes_flipped = 0; 486 487 /* Header must be in host endianness at this time. */ 488 ihp = (sframe_header *)frame_buf; 489 490 if (!sframe_header_sanity_check_p (ihp)) 491 return sframe_set_errno (&err, SFRAME_ERR_BUF_INVAL); 492 493 /* The contents of the SFrame header are safe to read. Get the number of 494 FDEs and the first FDE in the buffer. */ 495 hdrsz = sframe_get_hdr_size (ihp); 496 num_fdes = ihp->sfh_num_fdes; 497 fdes = frame_buf + hdrsz + ihp->sfh_fdeoff; 498 fdep = (sframe_func_desc_entry *)fdes; 499 500 j = 0; 501 prev_frep_index = 0; 502 for (i = 0; i < num_fdes; fdep++, i++) 503 { 504 if ((char*)fdep >= (frame_buf + buf_size)) 505 goto bad; 506 507 if (to_foreign) 508 { 509 num_fres = fdep->sfde_func_num_fres; 510 fre_type = sframe_get_fre_type (fdep); 511 fre_offset = fdep->sfde_func_start_fre_off; 512 } 513 514 flip_fde (fdep); 515 bytes_flipped += sizeof (sframe_func_desc_entry); 516 517 if (!to_foreign) 518 { 519 num_fres = fdep->sfde_func_num_fres; 520 fre_type = sframe_get_fre_type (fdep); 521 fre_offset = fdep->sfde_func_start_fre_off; 522 } 523 524 fp = frame_buf + hdrsz + ihp->sfh_freoff; 525 fp += fre_offset; 526 for (; j < prev_frep_index + num_fres; j++) 527 { 528 if (flip_fre (fp, fre_type, &esz)) 529 goto bad; 530 bytes_flipped += esz; 531 532 if (esz == 0 || esz > buf_size) 533 goto bad; 534 fp += esz; 535 } 536 prev_frep_index = j; 537 } 538 /* All FDEs and FREs must have been endian flipped by now. */ 539 if ((j != ihp->sfh_num_fres) || (bytes_flipped > (buf_size - hdrsz))) 540 goto bad; 541 /* Optional trailing section padding. */ 542 for (fp = frame_buf + hdrsz + bytes_flipped; fp < frame_buf + buf_size; fp++) 543 if (*fp != '\0') 544 goto bad; 545 546 /* Success. */ 547 return 0; 548 bad: 549 return SFRAME_ERR; 550 } 551 552 /* The SFrame Decoder. */ 553 554 /* Get SFrame header from the given decoder context DCTX. */ 555 556 static sframe_header * 557 sframe_decoder_get_header (sframe_decoder_ctx *dctx) 558 { 559 sframe_header *hp = NULL; 560 if (dctx != NULL) 561 hp = &dctx->sfd_header; 562 return hp; 563 } 564 565 /* Compare function for qsort'ing the FDE table. */ 566 567 static int 568 fde_func (const void *p1, const void *p2) 569 { 570 const sframe_func_desc_entry *aa = p1; 571 const sframe_func_desc_entry *bb = p2; 572 573 if (aa->sfde_func_start_address < bb->sfde_func_start_address) 574 return -1; 575 else if (aa->sfde_func_start_address > bb->sfde_func_start_address) 576 return 1; 577 return 0; 578 } 579 580 /* Get IDX'th offset from FRE. Set errp as applicable. */ 581 582 static int32_t 583 sframe_get_fre_offset (sframe_frame_row_entry *fre, int idx, int *errp) 584 { 585 uint8_t offset_cnt, offset_size; 586 587 if (fre == NULL || !sframe_fre_sanity_check_p (fre)) 588 return sframe_set_errno (errp, SFRAME_ERR_FRE_INVAL); 589 590 offset_cnt = sframe_fre_get_offset_count (fre->fre_info); 591 offset_size = sframe_fre_get_offset_size (fre->fre_info); 592 593 if (offset_cnt < idx + 1) 594 return sframe_set_errno (errp, SFRAME_ERR_FREOFFSET_NOPRESENT); 595 596 if (errp) 597 *errp = 0; /* Offset Valid. */ 598 599 if (offset_size == SFRAME_FRE_OFFSET_1B) 600 { 601 int8_t *sp = (int8_t *)fre->fre_offsets; 602 return sp[idx]; 603 } 604 else if (offset_size == SFRAME_FRE_OFFSET_2B) 605 { 606 int16_t *sp = (int16_t *)fre->fre_offsets; 607 return sp[idx]; 608 } 609 else 610 { 611 int32_t *ip = (int32_t *)fre->fre_offsets; 612 return ip[idx]; 613 } 614 } 615 616 /* Free the decoder context. */ 617 618 void 619 sframe_decoder_free (sframe_decoder_ctx **dctxp) 620 { 621 if (dctxp != NULL) 622 { 623 sframe_decoder_ctx *dctx = *dctxp; 624 if (dctx == NULL) 625 return; 626 627 if (dctx->sfd_funcdesc != NULL) 628 { 629 free (dctx->sfd_funcdesc); 630 dctx->sfd_funcdesc = NULL; 631 } 632 if (dctx->sfd_fres != NULL) 633 { 634 free (dctx->sfd_fres); 635 dctx->sfd_fres = NULL; 636 } 637 if (dctx->sfd_buf != NULL) 638 { 639 free (dctx->sfd_buf); 640 dctx->sfd_buf = NULL; 641 } 642 643 free (*dctxp); 644 *dctxp = NULL; 645 } 646 } 647 648 /* Create an FDE function info byte given an FRE_TYPE and an FDE_TYPE. */ 649 /* FIXME API for linker. Revisit if its better placed somewhere else? */ 650 651 unsigned char 652 sframe_fde_create_func_info (uint32_t fre_type, 653 uint32_t fde_type) 654 { 655 unsigned char func_info; 656 sframe_assert (fre_type == SFRAME_FRE_TYPE_ADDR1 657 || fre_type == SFRAME_FRE_TYPE_ADDR2 658 || fre_type == SFRAME_FRE_TYPE_ADDR4); 659 sframe_assert (fde_type == SFRAME_FDE_TYPE_PCINC 660 || fde_type == SFRAME_FDE_TYPE_PCMASK); 661 func_info = SFRAME_V1_FUNC_INFO (fde_type, fre_type); 662 return func_info; 663 } 664 665 /* Get the FRE type given the function size. */ 666 /* FIXME API for linker. Revisit if its better placed somewhere else? */ 667 668 uint32_t 669 sframe_calc_fre_type (size_t func_size) 670 { 671 uint32_t fre_type = 0; 672 if (func_size < SFRAME_FRE_TYPE_ADDR1_LIMIT) 673 fre_type = SFRAME_FRE_TYPE_ADDR1; 674 else if (func_size < SFRAME_FRE_TYPE_ADDR2_LIMIT) 675 fre_type = SFRAME_FRE_TYPE_ADDR2; 676 /* Adjust the check a bit so that it remains warning-free but meaningful 677 on 32-bit systems. */ 678 else if (func_size <= (size_t) (SFRAME_FRE_TYPE_ADDR4_LIMIT - 1)) 679 fre_type = SFRAME_FRE_TYPE_ADDR4; 680 return fre_type; 681 } 682 683 /* Get the base reg id from the FRE info. Set errp if failure. */ 684 685 uint8_t 686 sframe_fre_get_base_reg_id (sframe_frame_row_entry *fre, int *errp) 687 { 688 if (fre == NULL) 689 return sframe_set_errno (errp, SFRAME_ERR_FRE_INVAL); 690 691 uint8_t fre_info = fre->fre_info; 692 return SFRAME_V1_FRE_CFA_BASE_REG_ID (fre_info); 693 } 694 695 /* Get the CFA offset from the FRE. If the offset is invalid, sets errp. */ 696 697 int32_t 698 sframe_fre_get_cfa_offset (sframe_decoder_ctx *dctx, 699 sframe_frame_row_entry *fre, int *errp) 700 { 701 int32_t offset = sframe_get_fre_offset (fre, SFRAME_FRE_CFA_OFFSET_IDX, errp); 702 703 /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets). */ 704 if (sframe_decoder_get_abi_arch (dctx) == SFRAME_ABI_S390X_ENDIAN_BIG) 705 offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset); 706 707 return offset; 708 } 709 710 /* Get the FP offset from the FRE. If the offset is invalid, sets errp. 711 712 For s390x the offset may be an encoded register number, indicated by 713 LSB set to one, which is only valid in the topmost frame. */ 714 715 int32_t 716 sframe_fre_get_fp_offset (sframe_decoder_ctx *dctx, 717 sframe_frame_row_entry *fre, int *errp) 718 { 719 uint32_t fp_offset_idx = 0; 720 int8_t fp_offset = sframe_decoder_get_fixed_fp_offset (dctx); 721 /* If the FP offset is not being tracked, return the fixed FP offset 722 from the SFrame header. */ 723 if (fp_offset != SFRAME_CFA_FIXED_FP_INVALID) 724 { 725 if (errp) 726 *errp = 0; 727 return fp_offset; 728 } 729 730 /* In some ABIs, the stack offset to recover RA (using the CFA) from is 731 fixed (like AMD64). In such cases, the stack offset to recover FP will 732 appear at the second index. */ 733 fp_offset_idx = ((sframe_decoder_get_fixed_ra_offset (dctx) 734 != SFRAME_CFA_FIXED_RA_INVALID) 735 ? SFRAME_FRE_RA_OFFSET_IDX 736 : SFRAME_FRE_FP_OFFSET_IDX); 737 return sframe_get_fre_offset (fre, fp_offset_idx, errp); 738 } 739 740 /* Get the RA offset from the FRE. If the offset is invalid, sets errp. 741 742 For s390x an RA offset value of SFRAME_FRE_RA_OFFSET_INVALID indicates 743 that the RA is not saved, which is only valid in the topmost frame. 744 For s390x the offset may be an encoded register number, indicated by 745 LSB set to one, which is only valid in the topmost frame. */ 746 747 int32_t 748 sframe_fre_get_ra_offset (sframe_decoder_ctx *dctx, 749 sframe_frame_row_entry *fre, int *errp) 750 { 751 int8_t ra_offset = sframe_decoder_get_fixed_ra_offset (dctx); 752 /* If the RA offset was not being tracked, return the fixed RA offset 753 from the SFrame header. */ 754 if (ra_offset != SFRAME_CFA_FIXED_RA_INVALID) 755 { 756 if (errp) 757 *errp = 0; 758 return ra_offset; 759 } 760 761 /* Otherwise, get the RA offset from the FRE. */ 762 return sframe_get_fre_offset (fre, SFRAME_FRE_RA_OFFSET_IDX, errp); 763 } 764 765 /* Get whether the RA is mangled. */ 766 767 bool 768 sframe_fre_get_ra_mangled_p (sframe_decoder_ctx *dctx ATTRIBUTE_UNUSED, 769 sframe_frame_row_entry *fre, int *errp) 770 { 771 if (fre == NULL || !sframe_fre_sanity_check_p (fre)) 772 return sframe_set_errno (errp, SFRAME_ERR_FRE_INVAL); 773 774 return sframe_get_fre_ra_mangled_p (fre->fre_info); 775 } 776 777 static int 778 sframe_frame_row_entry_copy (sframe_frame_row_entry *dst, 779 sframe_frame_row_entry *src) 780 { 781 int err = 0; 782 783 if (dst == NULL || src == NULL) 784 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 785 786 memcpy (dst, src, sizeof (sframe_frame_row_entry)); 787 return 0; 788 } 789 790 /* Decode the SFrame FRE start address offset value from FRE_BUF in on-disk 791 binary format, given the FRE_TYPE. Updates the FRE_START_ADDR. 792 793 Returns 0 on success, SFRAME_ERR otherwise. */ 794 795 static int 796 sframe_decode_fre_start_address (const char *fre_buf, 797 uint32_t *fre_start_addr, 798 uint32_t fre_type) 799 { 800 uint32_t saddr = 0; 801 int err = 0; 802 size_t addr_size = 0; 803 804 addr_size = sframe_fre_start_addr_size (fre_type); 805 806 if (fre_type == SFRAME_FRE_TYPE_ADDR1) 807 { 808 uint8_t *uc = (uint8_t *)fre_buf; 809 saddr = (uint32_t)*uc; 810 } 811 else if (fre_type == SFRAME_FRE_TYPE_ADDR2) 812 { 813 uint16_t *ust = (uint16_t *)fre_buf; 814 /* SFrame is an unaligned on-disk format. Using memcpy helps avoid the 815 use of undesirable unaligned loads. See PR libsframe/29856. */ 816 uint16_t tmp = 0; 817 memcpy (&tmp, ust, addr_size); 818 saddr = (uint32_t)tmp; 819 } 820 else if (fre_type == SFRAME_FRE_TYPE_ADDR4) 821 { 822 uint32_t *uit = (uint32_t *)fre_buf; 823 uint32_t tmp = 0; 824 memcpy (&tmp, uit, addr_size); 825 saddr = (uint32_t)tmp; 826 } 827 else 828 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 829 830 *fre_start_addr = saddr; 831 return 0; 832 } 833 834 /* Decode a frame row entry FRE which starts at location FRE_BUF. The function 835 updates ESZ to the size of the FRE as stored in the binary format. 836 837 This function works closely with the SFrame binary format. 838 839 Returns SFRAME_ERR if failure. */ 840 841 static int 842 sframe_decode_fre (const char *fre_buf, sframe_frame_row_entry *fre, 843 uint32_t fre_type, size_t *esz) 844 { 845 int err = 0; 846 const char *stack_offsets = NULL; 847 size_t stack_offsets_sz; 848 size_t addr_size; 849 size_t fre_size; 850 851 if (fre_buf == NULL || fre == NULL || esz == NULL) 852 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 853 854 /* Copy over the FRE start address. */ 855 sframe_decode_fre_start_address (fre_buf, &fre->fre_start_addr, fre_type); 856 857 addr_size = sframe_fre_start_addr_size (fre_type); 858 fre->fre_info = *(uint8_t *)(fre_buf + addr_size); 859 /* Sanity check as the API works closely with the binary format. */ 860 sframe_assert (sizeof (fre->fre_info) == sizeof (uint8_t)); 861 862 /* Cleanup the space for fre_offsets first, then copy over the valid 863 bytes. */ 864 memset (fre->fre_offsets, 0, MAX_OFFSET_BYTES); 865 /* Get offsets size. */ 866 stack_offsets_sz = sframe_fre_offset_bytes_size (fre->fre_info); 867 stack_offsets = fre_buf + addr_size + sizeof (fre->fre_info); 868 memcpy (fre->fre_offsets, stack_offsets, stack_offsets_sz); 869 870 /* The FRE has been decoded. Use it to perform one last sanity check. */ 871 fre_size = sframe_fre_entry_size (fre, fre_type); 872 sframe_assert (fre_size == (addr_size + sizeof (fre->fre_info) 873 + stack_offsets_sz)); 874 *esz = fre_size; 875 876 return 0; 877 } 878 879 /* Decode the specified SFrame buffer SF_BUF of size SF_SIZE and return the 880 new SFrame decoder context. 881 882 Sets ERRP for the caller if any error. Frees up the allocated memory in 883 case of error. */ 884 885 sframe_decoder_ctx * 886 sframe_decode (const char *sf_buf, size_t sf_size, int *errp) 887 { 888 const sframe_preamble *sfp; 889 size_t hdrsz; 890 sframe_header *sfheaderp; 891 sframe_decoder_ctx *dctx; 892 char *frame_buf; 893 char *tempbuf = NULL; 894 895 int fidx_size; 896 uint32_t fre_bytes; 897 int foreign_endian = 0; 898 899 sframe_init_debug (); 900 901 if ((sf_buf == NULL) || (!sf_size)) 902 return sframe_ret_set_errno (errp, SFRAME_ERR_INVAL); 903 else if (sf_size < sizeof (sframe_header)) 904 return sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); 905 906 sfp = (const sframe_preamble *) sf_buf; 907 908 debug_printf ("sframe_decode: magic=0x%x version=%u flags=%u\n", 909 sfp->sfp_magic, sfp->sfp_version, sfp->sfp_flags); 910 911 /* Check for foreign endianness. */ 912 if (sfp->sfp_magic != SFRAME_MAGIC) 913 { 914 if (sfp->sfp_magic == bswap_16 (SFRAME_MAGIC)) 915 foreign_endian = 1; 916 else 917 return sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); 918 } 919 920 /* Initialize a new decoder context. */ 921 if ((dctx = malloc (sizeof (sframe_decoder_ctx))) == NULL) 922 return sframe_ret_set_errno (errp, SFRAME_ERR_NOMEM); 923 memset (dctx, 0, sizeof (sframe_decoder_ctx)); 924 925 if (foreign_endian) 926 { 927 /* Allocate a new buffer and initialize it. */ 928 tempbuf = (char *) malloc (sf_size * sizeof (char)); 929 if (tempbuf == NULL) 930 return sframe_ret_set_errno (errp, SFRAME_ERR_NOMEM); 931 memcpy (tempbuf, sf_buf, sf_size); 932 933 /* Flip the header. */ 934 sframe_header *ihp = (sframe_header *) tempbuf; 935 flip_header (ihp); 936 /* Flip the rest of the SFrame section data buffer. */ 937 if (flip_sframe (tempbuf, sf_size, 0)) 938 { 939 free (tempbuf); 940 return sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); 941 } 942 frame_buf = tempbuf; 943 /* This buffer is malloc'd when endian flipping the contents of the input 944 buffer are needed. Keep a reference to it so it can be free'd up 945 later in sframe_decoder_free (). */ 946 dctx->sfd_buf = tempbuf; 947 } 948 else 949 frame_buf = (char *)sf_buf; 950 951 /* Handle the SFrame header. */ 952 dctx->sfd_header = *(sframe_header *) frame_buf; 953 /* Validate the contents of SFrame header. */ 954 sfheaderp = &dctx->sfd_header; 955 if (!sframe_header_sanity_check_p (sfheaderp)) 956 { 957 sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); 958 goto decode_fail_free; 959 } 960 hdrsz = sframe_get_hdr_size (sfheaderp); 961 frame_buf += hdrsz; 962 963 /* Handle the SFrame Function Descriptor Entry section. */ 964 fidx_size 965 = sfheaderp->sfh_num_fdes * sizeof (sframe_func_desc_entry); 966 dctx->sfd_funcdesc = malloc (fidx_size); 967 if (dctx->sfd_funcdesc == NULL) 968 { 969 sframe_ret_set_errno (errp, SFRAME_ERR_NOMEM); 970 goto decode_fail_free; 971 } 972 memcpy (dctx->sfd_funcdesc, frame_buf, fidx_size); 973 974 debug_printf ("%u total fidx size\n", fidx_size); 975 976 frame_buf += (fidx_size); 977 978 /* Handle the SFrame Frame Row Entry section. */ 979 dctx->sfd_fres = (char *) malloc (sfheaderp->sfh_fre_len); 980 if (dctx->sfd_fres == NULL) 981 { 982 sframe_ret_set_errno (errp, SFRAME_ERR_NOMEM); 983 goto decode_fail_free; 984 } 985 memcpy (dctx->sfd_fres, frame_buf, sfheaderp->sfh_fre_len); 986 987 fre_bytes = sfheaderp->sfh_fre_len; 988 dctx->sfd_fre_nbytes = fre_bytes; 989 990 debug_printf ("%u total fre bytes\n", fre_bytes); 991 992 return dctx; 993 994 decode_fail_free: 995 if (foreign_endian && tempbuf != NULL) 996 free (tempbuf); 997 sframe_decoder_free (&dctx); 998 dctx = NULL; 999 return dctx; 1000 } 1001 1002 /* Get the size of the SFrame header from the decoder context CTX. */ 1003 1004 unsigned int 1005 sframe_decoder_get_hdr_size (sframe_decoder_ctx *ctx) 1006 { 1007 sframe_header *dhp; 1008 dhp = sframe_decoder_get_header (ctx); 1009 return sframe_get_hdr_size (dhp); 1010 } 1011 1012 /* Get the SFrame's abi/arch info given the decoder context DCTX. */ 1013 1014 uint8_t 1015 sframe_decoder_get_abi_arch (sframe_decoder_ctx *dctx) 1016 { 1017 sframe_header *sframe_header; 1018 sframe_header = sframe_decoder_get_header (dctx); 1019 return sframe_header->sfh_abi_arch; 1020 } 1021 1022 /* Get the format version from the SFrame decoder context DCTX. */ 1023 1024 uint8_t 1025 sframe_decoder_get_version (sframe_decoder_ctx *dctx) 1026 { 1027 sframe_header *dhp; 1028 dhp = sframe_decoder_get_header (dctx); 1029 return dhp->sfh_preamble.sfp_version; 1030 } 1031 1032 /* Get the section flags from the SFrame decoder context DCTX. */ 1033 1034 uint8_t 1035 sframe_decoder_get_flags (sframe_decoder_ctx *dctx) 1036 { 1037 const sframe_header *dhp = sframe_decoder_get_header (dctx); 1038 return dhp->sfh_preamble.sfp_flags; 1039 } 1040 1041 /* Get the SFrame's fixed FP offset given the decoder context CTX. */ 1042 int8_t 1043 sframe_decoder_get_fixed_fp_offset (sframe_decoder_ctx *ctx) 1044 { 1045 sframe_header *dhp; 1046 dhp = sframe_decoder_get_header (ctx); 1047 return dhp->sfh_cfa_fixed_fp_offset; 1048 } 1049 1050 /* Get the SFrame's fixed RA offset given the decoder context CTX. */ 1051 int8_t 1052 sframe_decoder_get_fixed_ra_offset (sframe_decoder_ctx *ctx) 1053 { 1054 sframe_header *dhp; 1055 dhp = sframe_decoder_get_header (ctx); 1056 return dhp->sfh_cfa_fixed_ra_offset; 1057 } 1058 1059 /* Get the offset of the sfde_func_start_address field (from the start of the 1060 on-disk layout of the SFrame section) of the FDE at FUNC_IDX in the decoder 1061 context DCTX. 1062 1063 If FUNC_IDX is more than the number of SFrame FDEs in the section, sets 1064 error code in ERRP, but returns the (hypothetical) offset. This is useful 1065 for the linker when arranging input FDEs into the output section to be 1066 emitted. */ 1067 1068 uint32_t 1069 sframe_decoder_get_offsetof_fde_start_addr (sframe_decoder_ctx *dctx, 1070 uint32_t func_idx, int *errp) 1071 { 1072 if (func_idx >= sframe_decoder_get_num_fidx (dctx)) 1073 sframe_ret_set_errno (errp, SFRAME_ERR_FDE_NOTFOUND); 1074 else if (errp) 1075 *errp = 0; 1076 1077 return (sframe_decoder_get_hdr_size (dctx) 1078 + func_idx * sizeof (sframe_func_desc_entry) 1079 + offsetof (sframe_func_desc_entry, sfde_func_start_address)); 1080 } 1081 1082 /* Find the function descriptor entry starting which contains the specified 1083 address ADDR. */ 1084 1085 static sframe_func_desc_entry * 1086 sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr, 1087 int *errp, uint32_t *func_idx) 1088 { 1089 sframe_header *dhp; 1090 sframe_func_desc_entry *fdp; 1091 int low, high; 1092 1093 if (ctx == NULL) 1094 return sframe_ret_set_errno (errp, SFRAME_ERR_INVAL); 1095 1096 dhp = sframe_decoder_get_header (ctx); 1097 1098 if (dhp == NULL || dhp->sfh_num_fdes == 0 || ctx->sfd_funcdesc == NULL) 1099 return sframe_ret_set_errno (errp, SFRAME_ERR_DCTX_INVAL); 1100 /* If the FDE sub-section is not sorted on PCs, skip the lookup because 1101 binary search cannot be used. */ 1102 if ((sframe_decoder_get_flags (ctx) & SFRAME_F_FDE_SORTED) == 0) 1103 return sframe_ret_set_errno (errp, SFRAME_ERR_FDE_NOTSORTED); 1104 1105 /* Do the binary search. */ 1106 fdp = (sframe_func_desc_entry *) ctx->sfd_funcdesc; 1107 low = 0; 1108 high = dhp->sfh_num_fdes - 1; 1109 while (low <= high) 1110 { 1111 int mid = low + (high - low) / 2; 1112 1113 /* Given sfde_func_start_address <= addr, 1114 addr - sfde_func_start_address must be positive. */ 1115 if (sframe_decoder_get_secrel_func_start_addr (ctx, mid) <= addr 1116 && ((uint32_t)(addr - sframe_decoder_get_secrel_func_start_addr (ctx, 1117 mid)) 1118 < fdp[mid].sfde_func_size)) 1119 { 1120 *func_idx = mid; 1121 return fdp + mid; 1122 } 1123 1124 if (sframe_decoder_get_secrel_func_start_addr (ctx, mid) < addr) 1125 low = mid + 1; 1126 else 1127 high = mid - 1; 1128 } 1129 1130 return sframe_ret_set_errno (errp, SFRAME_ERR_FDE_NOTFOUND); 1131 } 1132 1133 /* Get the end IP offset for the FRE at index i in the FDEP. The buffer FRES 1134 is the starting location for the FRE. */ 1135 1136 static uint32_t 1137 sframe_fre_get_end_ip_offset (sframe_func_desc_entry *fdep, unsigned int i, 1138 const char *fres) 1139 { 1140 uint32_t end_ip_offset; 1141 uint32_t fre_type; 1142 1143 fre_type = sframe_get_fre_type (fdep); 1144 1145 /* Get the start address of the next FRE in sequence. */ 1146 if (i < fdep->sfde_func_num_fres - 1) 1147 { 1148 sframe_decode_fre_start_address (fres, &end_ip_offset, fre_type); 1149 end_ip_offset -= 1; 1150 } 1151 else 1152 /* The end IP offset for the FRE needs to be deduced from the function 1153 size. */ 1154 end_ip_offset = fdep->sfde_func_size - 1; 1155 1156 return end_ip_offset; 1157 } 1158 1159 /* Find the SFrame Row Entry which contains the PC. Returns 1160 SFRAME_ERR if failure. */ 1161 1162 int 1163 sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, 1164 sframe_frame_row_entry *frep) 1165 { 1166 sframe_frame_row_entry cur_fre; 1167 sframe_func_desc_entry *fdep; 1168 uint32_t func_idx; 1169 uint32_t fre_type, i; 1170 int32_t func_start_addr; 1171 uint32_t start_ip_offset, end_ip_offset; 1172 const char *fres; 1173 size_t size = 0; 1174 int err = 0; 1175 1176 if ((ctx == NULL) || (frep == NULL)) 1177 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1178 1179 /* Find the FDE which contains the PC, then scan its fre entries. */ 1180 fdep = sframe_get_funcdesc_with_addr_internal (ctx, pc, &err, &func_idx); 1181 if (fdep == NULL || ctx->sfd_fres == NULL) 1182 return sframe_set_errno (&err, SFRAME_ERR_DCTX_INVAL); 1183 1184 fre_type = sframe_get_fre_type (fdep); 1185 1186 fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off; 1187 func_start_addr = sframe_decoder_get_secrel_func_start_addr (ctx, func_idx); 1188 1189 for (i = 0; i < fdep->sfde_func_num_fres; i++) 1190 { 1191 err = sframe_decode_fre (fres, &cur_fre, fre_type, &size); 1192 if (err) 1193 return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); 1194 1195 start_ip_offset = cur_fre.fre_start_addr; 1196 end_ip_offset = sframe_fre_get_end_ip_offset (fdep, i, fres + size); 1197 1198 /* Stop search if FRE's start_ip is greater than pc. Given 1199 func_start_addr <= pc, pc - func_start_addr must be positive. */ 1200 if (start_ip_offset > (uint32_t)(pc - func_start_addr)) 1201 return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); 1202 1203 if (sframe_fre_check_range_p (ctx, func_idx, start_ip_offset, 1204 end_ip_offset, pc)) 1205 { 1206 sframe_frame_row_entry_copy (frep, &cur_fre); 1207 return 0; 1208 } 1209 fres += size; 1210 } 1211 return sframe_set_errno (&err, SFRAME_ERR_FDE_INVAL); 1212 } 1213 1214 /* Return the number of function descriptor entries in the SFrame decoder 1215 DCTX. */ 1216 1217 uint32_t 1218 sframe_decoder_get_num_fidx (sframe_decoder_ctx *ctx) 1219 { 1220 uint32_t num_fdes = 0; 1221 sframe_header *dhp = NULL; 1222 dhp = sframe_decoder_get_header (ctx); 1223 if (dhp) 1224 num_fdes = dhp->sfh_num_fdes; 1225 return num_fdes; 1226 } 1227 1228 /* Get the data (NUM_FRES, FUNC_START_ADDRESS) from the function 1229 descriptor entry at index I'th in the decoder CTX. If failed, 1230 return error code. */ 1231 /* FIXME - consolidate the args and return a 1232 sframe_func_desc_index_elem rather? */ 1233 1234 int 1235 sframe_decoder_get_funcdesc (sframe_decoder_ctx *ctx, 1236 unsigned int i, 1237 uint32_t *num_fres, 1238 uint32_t *func_size, 1239 int32_t *func_start_address, 1240 unsigned char *func_info) 1241 { 1242 sframe_func_desc_entry *fdp; 1243 int err = 0; 1244 1245 if (ctx == NULL || func_start_address == NULL || num_fres == NULL 1246 || func_size == NULL) 1247 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1248 1249 fdp = sframe_decoder_get_funcdesc_at_index (ctx, i); 1250 1251 if (fdp == NULL) 1252 return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND); 1253 1254 *num_fres = fdp->sfde_func_num_fres; 1255 *func_start_address = fdp->sfde_func_start_address; 1256 *func_size = fdp->sfde_func_size; 1257 *func_info = fdp->sfde_func_info; 1258 1259 return 0; 1260 } 1261 1262 int 1263 sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *dctx, 1264 unsigned int i, 1265 uint32_t *num_fres, 1266 uint32_t *func_size, 1267 int32_t *func_start_address, 1268 unsigned char *func_info, 1269 uint8_t *rep_block_size) 1270 { 1271 sframe_func_desc_entry *fdp; 1272 int err = 0; 1273 1274 if (dctx == NULL || func_start_address == NULL 1275 || num_fres == NULL || func_size == NULL 1276 || sframe_decoder_get_version (dctx) == SFRAME_VERSION_1) 1277 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1278 1279 fdp = sframe_decoder_get_funcdesc_at_index (dctx, i); 1280 1281 if (fdp == NULL) 1282 return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND); 1283 1284 *num_fres = fdp->sfde_func_num_fres; 1285 *func_start_address = fdp->sfde_func_start_address; 1286 *func_size = fdp->sfde_func_size; 1287 *func_info = fdp->sfde_func_info; 1288 *rep_block_size = fdp->sfde_func_rep_size; 1289 1290 return 0; 1291 } 1292 /* Get the FRE_IDX'th FRE of the function at FUNC_IDX'th function 1293 descriptor entry in the SFrame decoder CTX. Returns error code as 1294 applicable. */ 1295 1296 int 1297 sframe_decoder_get_fre (sframe_decoder_ctx *ctx, 1298 unsigned int func_idx, 1299 unsigned int fre_idx, 1300 sframe_frame_row_entry *fre) 1301 { 1302 sframe_func_desc_entry *fdep; 1303 sframe_frame_row_entry ifre; 1304 const char *fres; 1305 uint32_t i; 1306 uint32_t fre_type; 1307 size_t esz = 0; 1308 int err = 0; 1309 1310 if (ctx == NULL || fre == NULL) 1311 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1312 1313 /* Get function descriptor entry at index func_idx. */ 1314 fdep = sframe_decoder_get_funcdesc_at_index (ctx, func_idx); 1315 1316 if (fdep == NULL) 1317 return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND); 1318 1319 fre_type = sframe_get_fre_type (fdep); 1320 /* Now scan the FRE entries. */ 1321 fres = ctx->sfd_fres + fdep->sfde_func_start_fre_off; 1322 for (i = 0; i < fdep->sfde_func_num_fres; i++) 1323 { 1324 /* Decode the FRE at the current position. Return it if valid. */ 1325 err = sframe_decode_fre (fres, &ifre, fre_type, &esz); 1326 if (i == fre_idx) 1327 { 1328 if (!sframe_fre_sanity_check_p (&ifre)) 1329 return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); 1330 1331 /* Although a stricter sanity check on fre_start_addr like: 1332 if (fdep->sfde_func_size) 1333 sframe_assert (frep->fre_start_addr < fdep->sfde_func_size); 1334 is more suitable, some code has been seen to not abide by it. See 1335 PR libsframe/33131. */ 1336 sframe_assert (ifre.fre_start_addr <= fdep->sfde_func_size); 1337 1338 sframe_frame_row_entry_copy (fre, &ifre); 1339 1340 return 0; 1341 } 1342 /* Next FRE. */ 1343 fres += esz; 1344 } 1345 1346 return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND); 1347 } 1348 1349 1350 /* SFrame Encoder. */ 1351 1352 /* Get a reference to the ENCODER's SFrame header. */ 1353 1354 static sframe_header * 1355 sframe_encoder_get_header (sframe_encoder_ctx *encoder) 1356 { 1357 sframe_header *hp = NULL; 1358 if (encoder) 1359 hp = &encoder->sfe_header; 1360 return hp; 1361 } 1362 1363 static sframe_func_desc_entry * 1364 sframe_encoder_get_funcdesc_at_index (sframe_encoder_ctx *encoder, 1365 uint32_t func_idx) 1366 { 1367 sframe_func_desc_entry *fde = NULL; 1368 if (func_idx < sframe_encoder_get_num_fidx (encoder)) 1369 { 1370 sf_fde_tbl *func_tbl = encoder->sfe_funcdesc; 1371 fde = func_tbl->entry + func_idx; 1372 } 1373 return fde; 1374 } 1375 1376 /* Create an encoder context with the given SFrame format version VER, FLAGS 1377 and ABI information. Uses the ABI specific FIXED_FP_OFFSET and 1378 FIXED_RA_OFFSET values as provided. Sets errp if failure. */ 1379 1380 sframe_encoder_ctx * 1381 sframe_encode (uint8_t ver, uint8_t flags, uint8_t abi_arch, 1382 int8_t fixed_fp_offset, int8_t fixed_ra_offset, int *errp) 1383 { 1384 sframe_header *hp; 1385 sframe_encoder_ctx *encoder; 1386 1387 if (ver != SFRAME_VERSION) 1388 return sframe_ret_set_errno (errp, SFRAME_ERR_VERSION_INVAL); 1389 1390 if ((encoder = malloc (sizeof (sframe_encoder_ctx))) == NULL) 1391 return sframe_ret_set_errno (errp, SFRAME_ERR_NOMEM); 1392 1393 memset (encoder, 0, sizeof (sframe_encoder_ctx)); 1394 1395 /* Get the SFrame header and update it. */ 1396 hp = sframe_encoder_get_header (encoder); 1397 hp->sfh_preamble.sfp_version = ver; 1398 hp->sfh_preamble.sfp_magic = SFRAME_MAGIC; 1399 hp->sfh_preamble.sfp_flags = flags; 1400 1401 /* Implementation in the SFrame encoder APIs, e.g., 1402 sframe_encoder_write_sframe assume flag SFRAME_F_FDE_FUNC_START_PCREL 1403 set. */ 1404 if (!(flags & SFRAME_F_FDE_FUNC_START_PCREL)) 1405 return sframe_ret_set_errno (errp, SFRAME_ERR_ECTX_INVAL); 1406 1407 hp->sfh_abi_arch = abi_arch; 1408 hp->sfh_cfa_fixed_fp_offset = fixed_fp_offset; 1409 hp->sfh_cfa_fixed_ra_offset = fixed_ra_offset; 1410 1411 return encoder; 1412 } 1413 1414 /* Free the encoder context. */ 1415 1416 void 1417 sframe_encoder_free (sframe_encoder_ctx **encoder) 1418 { 1419 if (encoder != NULL) 1420 { 1421 sframe_encoder_ctx *ectx = *encoder; 1422 if (ectx == NULL) 1423 return; 1424 1425 if (ectx->sfe_funcdesc != NULL) 1426 { 1427 free (ectx->sfe_funcdesc); 1428 ectx->sfe_funcdesc = NULL; 1429 } 1430 if (ectx->sfe_fres != NULL) 1431 { 1432 free (ectx->sfe_fres); 1433 ectx->sfe_fres = NULL; 1434 } 1435 if (ectx->sfe_data != NULL) 1436 { 1437 free (ectx->sfe_data); 1438 ectx->sfe_data = NULL; 1439 } 1440 1441 free (*encoder); 1442 *encoder = NULL; 1443 } 1444 } 1445 1446 /* Get the size of the SFrame header from the encoder ctx ENCODER. */ 1447 1448 unsigned int 1449 sframe_encoder_get_hdr_size (sframe_encoder_ctx *encoder) 1450 { 1451 sframe_header *ehp; 1452 ehp = sframe_encoder_get_header (encoder); 1453 return sframe_get_hdr_size (ehp); 1454 } 1455 1456 /* Get the abi/arch info from the SFrame encoder context ENCODER. */ 1457 1458 uint8_t 1459 sframe_encoder_get_abi_arch (sframe_encoder_ctx *encoder) 1460 { 1461 uint8_t abi_arch = 0; 1462 sframe_header *ehp; 1463 ehp = sframe_encoder_get_header (encoder); 1464 if (ehp) 1465 abi_arch = ehp->sfh_abi_arch; 1466 return abi_arch; 1467 } 1468 1469 /* Get the format version from the SFrame encoder context ENCODER. */ 1470 1471 uint8_t 1472 sframe_encoder_get_version (sframe_encoder_ctx *encoder) 1473 { 1474 sframe_header *ehp; 1475 ehp = sframe_encoder_get_header (encoder); 1476 return ehp->sfh_preamble.sfp_version; 1477 } 1478 1479 /* Get the section flags from the SFrame encoder context ENCODER. */ 1480 1481 uint8_t 1482 sframe_encoder_get_flags (sframe_encoder_ctx *encoder) 1483 { 1484 const sframe_header *ehp = sframe_encoder_get_header (encoder); 1485 return ehp->sfh_preamble.sfp_flags; 1486 } 1487 1488 /* Return the number of function descriptor entries in the SFrame encoder 1489 ENCODER. */ 1490 1491 uint32_t 1492 sframe_encoder_get_num_fidx (sframe_encoder_ctx *encoder) 1493 { 1494 uint32_t num_fdes = 0; 1495 sframe_header *ehp = NULL; 1496 ehp = sframe_encoder_get_header (encoder); 1497 if (ehp) 1498 num_fdes = ehp->sfh_num_fdes; 1499 return num_fdes; 1500 } 1501 1502 /* Get the offset of the sfde_func_start_address field (from the start of the 1503 on-disk layout of the SFrame section) of the FDE at FUNC_IDX in the encoder 1504 context ENCODER. 1505 1506 If FUNC_IDX is more than the number of SFrame FDEs in the section, sets 1507 error code in ERRP, but returns the (hypothetical) offset. This is useful 1508 for the linker when arranging input FDEs into the output section to be 1509 emitted. */ 1510 1511 uint32_t 1512 sframe_encoder_get_offsetof_fde_start_addr (sframe_encoder_ctx *encoder, 1513 uint32_t func_idx, int *errp) 1514 { 1515 if (func_idx >= sframe_encoder_get_num_fidx (encoder)) 1516 sframe_ret_set_errno (errp, SFRAME_ERR_FDE_INVAL); 1517 else if (errp) 1518 *errp = 0; 1519 1520 return (sframe_encoder_get_hdr_size (encoder) 1521 + func_idx * sizeof (sframe_func_desc_entry) 1522 + offsetof (sframe_func_desc_entry, sfde_func_start_address)); 1523 } 1524 1525 /* Add an FRE to function at FUNC_IDX'th function descriptor entry in 1526 the encoder context. */ 1527 1528 int 1529 sframe_encoder_add_fre (sframe_encoder_ctx *encoder, 1530 unsigned int func_idx, 1531 sframe_frame_row_entry *frep) 1532 { 1533 sframe_header *ehp; 1534 sframe_func_desc_entry *fdep; 1535 sframe_frame_row_entry *ectx_frep; 1536 size_t offsets_sz, esz; 1537 uint32_t fre_type; 1538 size_t fre_tbl_sz; 1539 int err = 0; 1540 1541 if (encoder == NULL || frep == NULL) 1542 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1543 if (!sframe_fre_sanity_check_p (frep)) 1544 return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); 1545 1546 /* Use func_idx to gather the function descriptor entry. */ 1547 fdep = sframe_encoder_get_funcdesc_at_index (encoder, func_idx); 1548 1549 if (fdep == NULL) 1550 return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND); 1551 1552 fre_type = sframe_get_fre_type (fdep); 1553 sf_fre_tbl *fre_tbl = encoder->sfe_fres; 1554 1555 if (fre_tbl == NULL) 1556 { 1557 fre_tbl_sz = (sizeof (sf_fre_tbl) 1558 + (number_of_entries * sizeof (sframe_frame_row_entry))); 1559 fre_tbl = malloc (fre_tbl_sz); 1560 1561 if (fre_tbl == NULL) 1562 { 1563 sframe_set_errno (&err, SFRAME_ERR_NOMEM); 1564 goto bad; /* OOM. */ 1565 } 1566 memset (fre_tbl, 0, fre_tbl_sz); 1567 fre_tbl->alloced = number_of_entries; 1568 } 1569 else if (fre_tbl->count == fre_tbl->alloced) 1570 { 1571 fre_tbl_sz = (sizeof (sf_fre_tbl) 1572 + ((fre_tbl->alloced + number_of_entries) 1573 * sizeof (sframe_frame_row_entry))); 1574 fre_tbl = realloc (fre_tbl, fre_tbl_sz); 1575 if (fre_tbl == NULL) 1576 { 1577 sframe_set_errno (&err, SFRAME_ERR_NOMEM); 1578 goto bad; /* OOM. */ 1579 } 1580 1581 memset (&fre_tbl->entry[fre_tbl->alloced], 0, 1582 number_of_entries * sizeof (sframe_frame_row_entry)); 1583 fre_tbl->alloced += number_of_entries; 1584 } 1585 1586 ectx_frep = &fre_tbl->entry[fre_tbl->count]; 1587 ectx_frep->fre_start_addr 1588 = frep->fre_start_addr; 1589 ectx_frep->fre_info = frep->fre_info; 1590 1591 /* Although a stricter sanity check on fre_start_addr like: 1592 if (fdep->sfde_func_size) 1593 sframe_assert (frep->fre_start_addr < fdep->sfde_func_size); 1594 is more suitable, some code has been seen to not abide by it. See PR 1595 libsframe/33131. */ 1596 sframe_assert (frep->fre_start_addr <= fdep->sfde_func_size); 1597 1598 /* frep has already been sanity check'd. Get offsets size. */ 1599 offsets_sz = sframe_fre_offset_bytes_size (frep->fre_info); 1600 memcpy (&ectx_frep->fre_offsets, &frep->fre_offsets, offsets_sz); 1601 1602 esz = sframe_fre_entry_size (frep, fre_type); 1603 fre_tbl->count++; 1604 1605 encoder->sfe_fres = fre_tbl; 1606 encoder->sfe_fre_nbytes += esz; 1607 1608 ehp = sframe_encoder_get_header (encoder); 1609 ehp->sfh_num_fres = fre_tbl->count; 1610 1611 /* Update the value of the number of FREs for the function. */ 1612 fdep->sfde_func_num_fres++; 1613 1614 return 0; 1615 1616 bad: 1617 if (fre_tbl != NULL) 1618 free (fre_tbl); 1619 encoder->sfe_fres = NULL; 1620 encoder->sfe_fre_nbytes = 0; 1621 return -1; 1622 } 1623 1624 /* Add a new function descriptor entry with START_ADDR, FUNC_SIZE and NUM_FRES 1625 to the encoder. */ 1626 1627 int 1628 sframe_encoder_add_funcdesc (sframe_encoder_ctx *encoder, 1629 int32_t start_addr, 1630 uint32_t func_size, 1631 unsigned char func_info, 1632 uint32_t num_fres ATTRIBUTE_UNUSED) 1633 { 1634 sframe_header *ehp; 1635 sf_fde_tbl *fd_info; 1636 size_t fd_tbl_sz; 1637 int err = 0; 1638 1639 /* FIXME book-keep num_fres for error checking. */ 1640 if (encoder == NULL) 1641 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1642 1643 fd_info = encoder->sfe_funcdesc; 1644 ehp = sframe_encoder_get_header (encoder); 1645 1646 if (fd_info == NULL) 1647 { 1648 fd_tbl_sz = (sizeof (sf_fde_tbl) 1649 + (number_of_entries * sizeof (sframe_func_desc_entry))); 1650 fd_info = malloc (fd_tbl_sz); 1651 if (fd_info == NULL) 1652 { 1653 sframe_set_errno (&err, SFRAME_ERR_NOMEM); 1654 goto bad; /* OOM. */ 1655 } 1656 memset (fd_info, 0, fd_tbl_sz); 1657 fd_info->alloced = number_of_entries; 1658 } 1659 else if (fd_info->count == fd_info->alloced) 1660 { 1661 fd_tbl_sz = (sizeof (sf_fde_tbl) 1662 + ((fd_info->alloced + number_of_entries) 1663 * sizeof (sframe_func_desc_entry))); 1664 fd_info = realloc (fd_info, fd_tbl_sz); 1665 if (fd_info == NULL) 1666 { 1667 sframe_set_errno (&err, SFRAME_ERR_NOMEM); 1668 goto bad; /* OOM. */ 1669 } 1670 1671 memset (&fd_info->entry[fd_info->alloced], 0, 1672 number_of_entries * sizeof (sframe_func_desc_entry)); 1673 fd_info->alloced += number_of_entries; 1674 } 1675 1676 fd_info->entry[fd_info->count].sfde_func_start_address = start_addr; 1677 /* Num FREs is updated as FREs are added for the function later via 1678 sframe_encoder_add_fre. */ 1679 fd_info->entry[fd_info->count].sfde_func_size = func_size; 1680 fd_info->entry[fd_info->count].sfde_func_start_fre_off 1681 = encoder->sfe_fre_nbytes; 1682 #if 0 1683 // Linker optimization test code cleanup later ibhagat TODO FIXME 1684 uint32_t fre_type = sframe_calc_fre_type (func_size); 1685 1686 fd_info->entry[fd_info->count].sfde_func_info 1687 = sframe_fde_func_info (fre_type); 1688 #endif 1689 fd_info->entry[fd_info->count].sfde_func_info = func_info; 1690 fd_info->count++; 1691 encoder->sfe_funcdesc = fd_info; 1692 ehp->sfh_num_fdes++; 1693 return 0; 1694 1695 bad: 1696 if (fd_info != NULL) 1697 free (fd_info); 1698 encoder->sfe_funcdesc = NULL; 1699 ehp->sfh_num_fdes = 0; 1700 return -1; 1701 } 1702 1703 /* Add a new function descriptor entry with START_ADDR, FUNC_SIZE, FUNC_INFO 1704 and REP_BLOCK_SIZE to the encoder. 1705 1706 This API is valid only for SFrame format version 2. */ 1707 1708 int 1709 sframe_encoder_add_funcdesc_v2 (sframe_encoder_ctx *encoder, 1710 int32_t start_addr, 1711 uint32_t func_size, 1712 unsigned char func_info, 1713 uint8_t rep_block_size, 1714 uint32_t num_fres ATTRIBUTE_UNUSED) 1715 { 1716 sf_fde_tbl *fd_info; 1717 int err; 1718 1719 if (encoder == NULL 1720 || sframe_encoder_get_version (encoder) == SFRAME_VERSION_1) 1721 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1722 1723 err = sframe_encoder_add_funcdesc (encoder, start_addr, func_size, func_info, 1724 num_fres); 1725 if (err) 1726 return SFRAME_ERR; 1727 1728 fd_info = encoder->sfe_funcdesc; 1729 fd_info->entry[fd_info->count-1].sfde_func_rep_size = rep_block_size; 1730 1731 return 0; 1732 } 1733 1734 static int 1735 sframe_sort_funcdesc (sframe_encoder_ctx *encoder) 1736 { 1737 sframe_header *ehp = sframe_encoder_get_header (encoder); 1738 1739 /* Sort and write out the FDE table. */ 1740 sf_fde_tbl *fd_info = encoder->sfe_funcdesc; 1741 if (fd_info) 1742 { 1743 /* The new encoding of sfde_func_start_address means the distances are 1744 not from the same anchor, so cannot be sorted directly. At the moment 1745 we adress this by manual value adjustments before and after sorting. 1746 FIXME - qsort_r may be more optimal. */ 1747 1748 for (unsigned int i = 0; i < fd_info->count; i++) 1749 fd_info->entry[i].sfde_func_start_address 1750 += sframe_encoder_get_offsetof_fde_start_addr (encoder, i, NULL); 1751 1752 qsort (fd_info->entry, fd_info->count, 1753 sizeof (sframe_func_desc_entry), fde_func); 1754 1755 for (unsigned int i = 0; i < fd_info->count; i++) 1756 fd_info->entry[i].sfde_func_start_address 1757 -= sframe_encoder_get_offsetof_fde_start_addr (encoder, i, NULL); 1758 1759 /* Update preamble's flags. */ 1760 ehp->sfh_preamble.sfp_flags |= SFRAME_F_FDE_SORTED; 1761 } 1762 return 0; 1763 } 1764 1765 /* Write the SFrame FRE start address from the in-memory FRE_START_ADDR 1766 to the buffer CONTENTS (on-disk format), given the FRE_TYPE and 1767 FRE_START_ADDR_SZ. */ 1768 1769 static int 1770 sframe_encoder_write_fre_start_addr (char *contents, 1771 uint32_t fre_start_addr, 1772 uint32_t fre_type, 1773 size_t fre_start_addr_sz) 1774 { 1775 int err = 0; 1776 1777 if (fre_type == SFRAME_FRE_TYPE_ADDR1) 1778 { 1779 uint8_t uc = fre_start_addr; 1780 memcpy (contents, &uc, fre_start_addr_sz); 1781 } 1782 else if (fre_type == SFRAME_FRE_TYPE_ADDR2) 1783 { 1784 uint16_t ust = fre_start_addr; 1785 memcpy (contents, &ust, fre_start_addr_sz); 1786 } 1787 else if (fre_type == SFRAME_FRE_TYPE_ADDR4) 1788 { 1789 uint32_t uit = fre_start_addr; 1790 memcpy (contents, &uit, fre_start_addr_sz); 1791 } 1792 else 1793 return sframe_set_errno (&err, SFRAME_ERR_INVAL); 1794 1795 return 0; 1796 } 1797 1798 /* Write a frame row entry pointed to by FREP into the buffer CONTENTS. The 1799 size in bytes written out are updated in ESZ. 1800 1801 This function works closely with the SFrame binary format. 1802 1803 Returns SFRAME_ERR if failure. */ 1804 1805 static int 1806 sframe_encoder_write_fre (char *contents, sframe_frame_row_entry *frep, 1807 uint32_t fre_type, size_t *esz) 1808 { 1809 size_t fre_sz; 1810 size_t fre_start_addr_sz; 1811 size_t fre_stack_offsets_sz; 1812 int err = 0; 1813 1814 if (!sframe_fre_sanity_check_p (frep)) 1815 return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); 1816 1817 fre_start_addr_sz = sframe_fre_start_addr_size (fre_type); 1818 fre_stack_offsets_sz = sframe_fre_offset_bytes_size (frep->fre_info); 1819 1820 /* The FRE start address must be encodable in the available number of 1821 bytes. */ 1822 uint64_t bitmask = SFRAME_BITMASK_OF_SIZE (fre_start_addr_sz); 1823 sframe_assert ((uint64_t)frep->fre_start_addr <= bitmask); 1824 1825 sframe_encoder_write_fre_start_addr (contents, frep->fre_start_addr, 1826 fre_type, fre_start_addr_sz); 1827 contents += fre_start_addr_sz; 1828 1829 memcpy (contents, &frep->fre_info, sizeof (frep->fre_info)); 1830 contents += sizeof (frep->fre_info); 1831 1832 memcpy (contents, frep->fre_offsets, fre_stack_offsets_sz); 1833 contents+= fre_stack_offsets_sz; 1834 1835 fre_sz = sframe_fre_entry_size (frep, fre_type); 1836 /* Sanity checking. */ 1837 sframe_assert ((fre_start_addr_sz 1838 + sizeof (frep->fre_info) 1839 + fre_stack_offsets_sz) == fre_sz); 1840 1841 *esz = fre_sz; 1842 1843 return 0; 1844 } 1845 1846 /* Serialize the core contents of the SFrame section and write out to the 1847 output buffer held in the ENCODER. Return SFRAME_ERR if failure. */ 1848 1849 static int 1850 sframe_encoder_write_sframe (sframe_encoder_ctx *encoder) 1851 { 1852 char *contents; 1853 size_t buf_size; 1854 size_t hdr_size; 1855 size_t all_fdes_size; 1856 size_t fre_size; 1857 size_t esz = 0; 1858 sframe_header *ehp; 1859 sf_fde_tbl *fd_info; 1860 sf_fre_tbl *fr_info; 1861 uint32_t i, num_fdes; 1862 uint32_t j, num_fres; 1863 sframe_func_desc_entry *fdep; 1864 sframe_frame_row_entry *frep; 1865 1866 uint32_t fre_type; 1867 int err = 0; 1868 1869 contents = encoder->sfe_data; 1870 buf_size = encoder->sfe_data_size; 1871 num_fdes = sframe_encoder_get_num_fidx (encoder); 1872 all_fdes_size = num_fdes * sizeof (sframe_func_desc_entry); 1873 ehp = sframe_encoder_get_header (encoder); 1874 hdr_size = sframe_get_hdr_size (ehp); 1875 1876 fd_info = encoder->sfe_funcdesc; 1877 fr_info = encoder->sfe_fres; 1878 1879 /* Sanity checks: 1880 - buffers must be malloc'd by the caller. */ 1881 if ((contents == NULL) || (buf_size < hdr_size)) 1882 return sframe_set_errno (&err, SFRAME_ERR_BUF_INVAL); 1883 if (fr_info == NULL) 1884 return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); 1885 1886 /* Write out the FRE table first. 1887 1888 Recall that read/write of FREs needs information from the corresponding 1889 FDE; the latter stores the information about the FRE type record used for 1890 the function. Also note that sorting of FDEs does NOT impact the order 1891 in which FREs are stored in the SFrame's FRE sub-section. This means 1892 that writing out FREs after sorting of FDEs will need some additional 1893 book-keeping. At this time, we can afford to avoid it by writing out 1894 the FREs first to the output buffer. */ 1895 fre_size = 0; 1896 uint32_t global = 0; 1897 uint32_t fre_index = 0; 1898 1899 contents += hdr_size + all_fdes_size; 1900 for (i = 0; i < num_fdes; i++) 1901 { 1902 fdep = &fd_info->entry[i]; 1903 fre_type = sframe_get_fre_type (fdep); 1904 num_fres = fdep->sfde_func_num_fres; 1905 1906 for (j = 0; j < num_fres; j++) 1907 { 1908 fre_index = global + j; 1909 frep = &fr_info->entry[fre_index]; 1910 1911 sframe_encoder_write_fre (contents, frep, fre_type, &esz); 1912 contents += esz; 1913 fre_size += esz; /* For debugging only. */ 1914 } 1915 global += j; 1916 } 1917 1918 sframe_assert (fre_size == ehp->sfh_fre_len); 1919 sframe_assert (global == ehp->sfh_num_fres); 1920 sframe_assert ((size_t)(contents - encoder->sfe_data) == buf_size); 1921 1922 /* Sort the FDE table */ 1923 sframe_sort_funcdesc (encoder); 1924 1925 /* Sanity checks: 1926 - the FDE section must have been sorted by now on the start address 1927 of each function. */ 1928 if (!(sframe_encoder_get_flags (encoder) & SFRAME_F_FDE_SORTED) 1929 || (fd_info == NULL)) 1930 return sframe_set_errno (&err, SFRAME_ERR_FDE_INVAL); 1931 1932 contents = encoder->sfe_data; 1933 /* Write out the SFrame header. The SFrame header in the encoder 1934 object has already been updated with correct offsets by the caller. */ 1935 memcpy (contents, ehp, hdr_size); 1936 contents += hdr_size; 1937 1938 /* Write out the FDE table sorted on funtion start address. */ 1939 memcpy (contents, fd_info->entry, all_fdes_size); 1940 contents += all_fdes_size; 1941 1942 return 0; 1943 } 1944 1945 /* Serialize the contents of the encoder and return the buffer. ENCODED_SIZE 1946 is updated to the size of the buffer. */ 1947 1948 char * 1949 sframe_encoder_write (sframe_encoder_ctx *encoder, 1950 size_t *encoded_size, int *errp) 1951 { 1952 sframe_header *ehp; 1953 size_t hdrsize, fsz, fresz, bufsize; 1954 int foreign_endian; 1955 1956 /* Initialize the encoded_size to zero. This makes it simpler to just 1957 return from the function in case of failure. Free'ing up of 1958 encoder->sfe_data is the responsibility of the caller. */ 1959 *encoded_size = 0; 1960 1961 if (encoder == NULL || encoded_size == NULL || errp == NULL) 1962 return sframe_ret_set_errno (errp, SFRAME_ERR_INVAL); 1963 1964 ehp = sframe_encoder_get_header (encoder); 1965 hdrsize = sframe_get_hdr_size (ehp); 1966 fsz = sframe_encoder_get_num_fidx (encoder) 1967 * sizeof (sframe_func_desc_entry); 1968 fresz = encoder->sfe_fre_nbytes; 1969 1970 /* The total size of buffer is the sum of header, SFrame Function Descriptor 1971 Entries section and the FRE section. */ 1972 bufsize = hdrsize + fsz + fresz; 1973 encoder->sfe_data = (char *) malloc (bufsize); 1974 if (encoder->sfe_data == NULL) 1975 return sframe_ret_set_errno (errp, SFRAME_ERR_NOMEM); 1976 encoder->sfe_data_size = bufsize; 1977 1978 /* Update the information in the SFrame header. */ 1979 /* SFrame FDE section follows immediately after the header. */ 1980 ehp->sfh_fdeoff = 0; 1981 /* SFrame FRE section follows immediately after the SFrame FDE section. */ 1982 ehp->sfh_freoff = fsz; 1983 ehp->sfh_fre_len = fresz; 1984 1985 foreign_endian = need_swapping (ehp->sfh_abi_arch); 1986 1987 /* Write out the FDE Index and the FRE table in the sfe_data. */ 1988 if (sframe_encoder_write_sframe (encoder)) 1989 return sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); 1990 1991 /* Endian flip the contents if necessary. */ 1992 if (foreign_endian) 1993 { 1994 if (flip_sframe (encoder->sfe_data, bufsize, 1)) 1995 return sframe_ret_set_errno (errp, SFRAME_ERR_BUF_INVAL); 1996 flip_header ((sframe_header*)encoder->sfe_data); 1997 } 1998 1999 *encoded_size = bufsize; 2000 return encoder->sfe_data; 2001 } 2002