17e16fca0SAli Bahrami /* 27e16fca0SAli Bahrami * CDDL HEADER START 37e16fca0SAli Bahrami * 47e16fca0SAli Bahrami * The contents of this file are subject to the terms of the 57e16fca0SAli Bahrami * Common Development and Distribution License (the "License"). 67e16fca0SAli Bahrami * You may not use this file except in compliance with the License. 77e16fca0SAli Bahrami * 87e16fca0SAli Bahrami * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97e16fca0SAli Bahrami * or http://www.opensolaris.org/os/licensing. 107e16fca0SAli Bahrami * See the License for the specific language governing permissions 117e16fca0SAli Bahrami * and limitations under the License. 127e16fca0SAli Bahrami * 137e16fca0SAli Bahrami * When distributing Covered Code, include this CDDL HEADER in each 147e16fca0SAli Bahrami * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157e16fca0SAli Bahrami * If applicable, add the following below this CDDL HEADER, with the 167e16fca0SAli Bahrami * fields enclosed by brackets "[]" replaced with your own identifying 177e16fca0SAli Bahrami * information: Portions Copyright [yyyy] [name of copyright owner] 187e16fca0SAli Bahrami * 197e16fca0SAli Bahrami * CDDL HEADER END 207e16fca0SAli Bahrami */ 217e16fca0SAli Bahrami 227e16fca0SAli Bahrami /* 231007fd6fSAli Bahrami * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24cffcfaeeSAlexander Eremin * Copyright 2014 Nexenta Systems, Inc. 257e16fca0SAli Bahrami */ 267e16fca0SAli Bahrami 277e16fca0SAli Bahrami #include <string.h> 287e16fca0SAli Bahrami #include <stdio.h> 297e16fca0SAli Bahrami #include <sys/types.h> 307e16fca0SAli Bahrami #include <sgs.h> 317e16fca0SAli Bahrami #include <debug.h> 327e16fca0SAli Bahrami #include <_libld.h> 337e16fca0SAli Bahrami #include <dwarf.h> 347e16fca0SAli Bahrami #include <stdlib.h> 357e16fca0SAli Bahrami 367e16fca0SAli Bahrami /* 377e16fca0SAli Bahrami * A EH_FRAME_HDR consists of the following: 387e16fca0SAli Bahrami * 397e16fca0SAli Bahrami * Encoding Field 407e16fca0SAli Bahrami * -------------------------------- 417e16fca0SAli Bahrami * unsigned byte version 427e16fca0SAli Bahrami * unsigned byte eh_frame_ptr_enc 437e16fca0SAli Bahrami * unsigned byte fde_count_enc 447e16fca0SAli Bahrami * unsigned byte table_enc 457e16fca0SAli Bahrami * encoded eh_frame_ptr 467e16fca0SAli Bahrami * encoded fde_count 477e16fca0SAli Bahrami * [ binary search table ] 487e16fca0SAli Bahrami * 497e16fca0SAli Bahrami * The binary search table entries each consists of: 507e16fca0SAli Bahrami * 517e16fca0SAli Bahrami * encoded initial_func_loc 527e16fca0SAli Bahrami * encoded FDE_address 537e16fca0SAli Bahrami * 547e16fca0SAli Bahrami * The entries in the binary search table are sorted 557e16fca0SAli Bahrami * in a increasing order by the initial location. 567e16fca0SAli Bahrami * 577e16fca0SAli Bahrami * 587e16fca0SAli Bahrami * version 597e16fca0SAli Bahrami * 607e16fca0SAli Bahrami * Version of the .eh_frame_hdr format. This value shall be 1. 617e16fca0SAli Bahrami * 627e16fca0SAli Bahrami * eh_frame_ptr_enc 637e16fca0SAli Bahrami * 647e16fca0SAli Bahrami * The encoding format of the eh_frame_ptr field. For shared 657e16fca0SAli Bahrami * libraries the encoding must be 667e16fca0SAli Bahrami * DW_EH_PE_sdata4|DW_EH_PE_pcrel or 677e16fca0SAli Bahrami * DW_EH_PE_sdata4|DW_EH_PE_datarel. 687e16fca0SAli Bahrami * 697e16fca0SAli Bahrami * 707e16fca0SAli Bahrami * fde_count_enc 717e16fca0SAli Bahrami * 727e16fca0SAli Bahrami * The encoding format of the fde_count field. A value of 737e16fca0SAli Bahrami * DW_EH_PE_omit indicates the binary search table is not 747e16fca0SAli Bahrami * present. 757e16fca0SAli Bahrami * 767e16fca0SAli Bahrami * table_enc 777e16fca0SAli Bahrami * 787e16fca0SAli Bahrami * The encoding format of the entries in the binary search 797e16fca0SAli Bahrami * table. A value of DW_EH_PE_omit indicates the binary search 807e16fca0SAli Bahrami * table is not present. For shared libraries the encoding 817e16fca0SAli Bahrami * must be DW_EH_PE_sdata4|DW_EH_PE_pcrel or 827e16fca0SAli Bahrami * DW_EH_PE_sdata4|DW_EH_PE_datarel. 837e16fca0SAli Bahrami * 847e16fca0SAli Bahrami * 857e16fca0SAli Bahrami * eh_frame_ptr 867e16fca0SAli Bahrami * 877e16fca0SAli Bahrami * The encoded value of the pointer to the start of the 887e16fca0SAli Bahrami * .eh_frame section. 897e16fca0SAli Bahrami * 907e16fca0SAli Bahrami * fde_count 917e16fca0SAli Bahrami * 927e16fca0SAli Bahrami * The encoded value of the count of entries in the binary 937e16fca0SAli Bahrami * search table. 947e16fca0SAli Bahrami * 957e16fca0SAli Bahrami * binary search table 967e16fca0SAli Bahrami * 977e16fca0SAli Bahrami * A binary search table containing fde_count entries. Each 987e16fca0SAli Bahrami * entry of the table consist of two encoded values, the 997e16fca0SAli Bahrami * initial location of the function to which an FDE applies, 1007e16fca0SAli Bahrami * and the address of the FDE. The entries are sorted in an 1017e16fca0SAli Bahrami * increasing order by the initial location value. 1027e16fca0SAli Bahrami * 1037e16fca0SAli Bahrami */ 1047e16fca0SAli Bahrami 1057e16fca0SAli Bahrami 1067e16fca0SAli Bahrami /* 1077e16fca0SAli Bahrami * EH_FRAME sections 1087e16fca0SAli Bahrami * ================= 1097e16fca0SAli Bahrami * 1107e16fca0SAli Bahrami * The call frame information needed for unwinding the stack is output in 1117e16fca0SAli Bahrami * an ELF section(s) of type SHT_AMD64_UNWIND (amd64) or SHT_PROGBITS (other). 1127e16fca0SAli Bahrami * In the simplest case there will be one such section per object file and it 1137e16fca0SAli Bahrami * will be named ".eh_frame". An .eh_frame section consists of one or more 1147e16fca0SAli Bahrami * subsections. Each subsection contains a CIE (Common Information Entry) 1157e16fca0SAli Bahrami * followed by varying number of FDEs (Frame Descriptor Entry). A FDE 1167e16fca0SAli Bahrami * corresponds to an explicit or compiler generated function in a 1177e16fca0SAli Bahrami * compilation unit, all FDEs can access the CIE that begins their 1187e16fca0SAli Bahrami * subsection for data. 1197e16fca0SAli Bahrami * 1207e16fca0SAli Bahrami * If an object file contains C++ template instantiations, there shall be 1217e16fca0SAli Bahrami * a separate CIE immediately preceding each FDE corresponding to an 1227e16fca0SAli Bahrami * instantiation. 1237e16fca0SAli Bahrami * 1247e16fca0SAli Bahrami * Using the preferred encoding specified below, the .eh_frame section can 1257e16fca0SAli Bahrami * be entirely resolved at link time and thus can become part of the 1267e16fca0SAli Bahrami * text segment. 1277e16fca0SAli Bahrami * 1287e16fca0SAli Bahrami * .eh_frame Section Layout 1297e16fca0SAli Bahrami * ------------------------ 1307e16fca0SAli Bahrami * 1317e16fca0SAli Bahrami * EH_PE encoding below refers to the pointer encoding as specified in the 1327e16fca0SAli Bahrami * enhanced LSB Chapter 7 for Eh_Frame_Hdr. 1337e16fca0SAli Bahrami * 1347e16fca0SAli Bahrami * Common Information Entry (CIE) 1357e16fca0SAli Bahrami * ------------------------------ 1367e16fca0SAli Bahrami * CIE has the following format: 1377e16fca0SAli Bahrami * 1387e16fca0SAli Bahrami * Length 1397e16fca0SAli Bahrami * in 1407e16fca0SAli Bahrami * Field Byte Description 1417e16fca0SAli Bahrami * ----- ------ ----------- 1427e16fca0SAli Bahrami * 1. Length 4 Length of CIE (not including 1437e16fca0SAli Bahrami * this 4-byte field). 1447e16fca0SAli Bahrami * 1457e16fca0SAli Bahrami * 2. CIE id 4 Value Zero (0) for .eh_frame 1467e16fca0SAli Bahrami * (used to distinguish CIEs and 1477e16fca0SAli Bahrami * FDEs when scanning the section) 1487e16fca0SAli Bahrami * 1497e16fca0SAli Bahrami * 3. Version 1 Value One (1) 1507e16fca0SAli Bahrami * 1517e16fca0SAli Bahrami * 4. CIE Augmentation string Null-terminated string with legal 1527e16fca0SAli Bahrami * values being "" or 'z' optionally 15357ef7aa9SRod Evans * followed by single occurrences of 1547e16fca0SAli Bahrami * 'P', 'L', or 'R' in any order. 1557e16fca0SAli Bahrami * String The presence of character(s) in the 1567e16fca0SAli Bahrami * string dictates the content of 1577e16fca0SAli Bahrami * field 8, the Augmentation Section. 1587e16fca0SAli Bahrami * Each character has one or two 1597e16fca0SAli Bahrami * associated operands in the AS. 1607e16fca0SAli Bahrami * Operand order depends on 1617e16fca0SAli Bahrami * position in the string ('z' must 1627e16fca0SAli Bahrami * be first). 1637e16fca0SAli Bahrami * 1647e16fca0SAli Bahrami * 5. Code Align Factor uleb128 To be multiplied with the 1657e16fca0SAli Bahrami * "Advance Location" instructions in 1667e16fca0SAli Bahrami * the Call Frame Instructions 1677e16fca0SAli Bahrami * 1687e16fca0SAli Bahrami * 6. Data Align Factor sleb128 To be multiplied with all offset 1697e16fca0SAli Bahrami * in the Call Frame Instructions 1707e16fca0SAli Bahrami * 1717e16fca0SAli Bahrami * 7. Ret Address Reg 1 A "virtual" register representation 1727e16fca0SAli Bahrami * of the return address. In Dwarf V2, 1737e16fca0SAli Bahrami * this is a byte, otherwise it is 1747e16fca0SAli Bahrami * uleb128. It is a byte in gcc 3.3.x 1757e16fca0SAli Bahrami * 1767e16fca0SAli Bahrami * 8. Optional CIE varying Present if Augmentation String in 1777e16fca0SAli Bahrami * Augmentation Section field 4 is not 0. 1787e16fca0SAli Bahrami * 1797e16fca0SAli Bahrami * z: 1807e16fca0SAli Bahrami * size uleb128 Length of the remainder of the 1817e16fca0SAli Bahrami * Augmentation Section 1827e16fca0SAli Bahrami * 1837e16fca0SAli Bahrami * P: 1847e16fca0SAli Bahrami * personality_enc 1 Encoding specifier - preferred 1857e16fca0SAli Bahrami * value is a pc-relative, signed 1867e16fca0SAli Bahrami * 4-byte 1877e16fca0SAli Bahrami * 1887e16fca0SAli Bahrami * 1897e16fca0SAli Bahrami * personality routine (encoded) Encoded pointer to personality 1907e16fca0SAli Bahrami * routine (actually to the PLT 1917e16fca0SAli Bahrami * entry for the personality 1927e16fca0SAli Bahrami * routine) 1937e16fca0SAli Bahrami * R: 1947e16fca0SAli Bahrami * code_enc 1 Non-default encoding for the 1957e16fca0SAli Bahrami * code-pointers (FDE members 1967e16fca0SAli Bahrami * "initial_location" and "address_range" 1977e16fca0SAli Bahrami * and the operand for DW_CFA_set_loc) 1987e16fca0SAli Bahrami * - preferred value is pc-relative, 1997e16fca0SAli Bahrami * signed 4-byte. 2007e16fca0SAli Bahrami * L: 2017e16fca0SAli Bahrami * lsda_enc 1 FDE augmentation bodies may contain 2027e16fca0SAli Bahrami * LSDA pointers. If so they are 2037e16fca0SAli Bahrami * encoded as specified here - 2047e16fca0SAli Bahrami * preferred value is pc-relative, 2057e16fca0SAli Bahrami * signed 4-byte possibly indirect 2067e16fca0SAli Bahrami * thru a GOT entry. 2077e16fca0SAli Bahrami * 2087e16fca0SAli Bahrami * 2097e16fca0SAli Bahrami * 9. Optional Call Frame varying 2107e16fca0SAli Bahrami * Instructions 2117e16fca0SAli Bahrami * 2127e16fca0SAli Bahrami * The size of the optional call frame instruction area must be computed 2137e16fca0SAli Bahrami * based on the overall size and the offset reached while scanning the 2147e16fca0SAli Bahrami * preceding fields of the CIE. 2157e16fca0SAli Bahrami * 2167e16fca0SAli Bahrami * 2177e16fca0SAli Bahrami * Frame Descriptor Entry (FDE) 2187e16fca0SAli Bahrami * ---------------------------- 2197e16fca0SAli Bahrami * FDE has the following format: 2207e16fca0SAli Bahrami * 2217e16fca0SAli Bahrami * Length 2227e16fca0SAli Bahrami * in 2237e16fca0SAli Bahrami * Field Byte Description 2247e16fca0SAli Bahrami * ----- ------ ----------- 2257e16fca0SAli Bahrami * 1. Length 4 Length of remainder of this FDE 2267e16fca0SAli Bahrami * 2277e16fca0SAli Bahrami * 2. CIE Pointer 4 Distance from this field to the 2287e16fca0SAli Bahrami * nearest preceding CIE 2297e16fca0SAli Bahrami * (uthe value is subtracted from the 2307e16fca0SAli Bahrami * current address). This value 2317e16fca0SAli Bahrami * can never be zero and thus can 2327e16fca0SAli Bahrami * be used to distinguish CIE's and 2337e16fca0SAli Bahrami * FDE's when scanning the 2347e16fca0SAli Bahrami * .eh_frame section 2357e16fca0SAli Bahrami * 2367e16fca0SAli Bahrami * 3. Initial Location varying Reference to the function code 2377e16fca0SAli Bahrami * corresponding to this FDE. 2387e16fca0SAli Bahrami * If 'R' is missing from the CIE 2397e16fca0SAli Bahrami * Augmentation String, the field is an 2407e16fca0SAli Bahrami * 8-byte absolute pointer. Otherwise, 2417e16fca0SAli Bahrami * the corresponding EH_PE encoding in the 2427e16fca0SAli Bahrami * CIE Augmentation Section is used to 2437e16fca0SAli Bahrami * interpret the reference. 2447e16fca0SAli Bahrami * 2457e16fca0SAli Bahrami * 4. Address Range varying Size of the function code corresponding 2467e16fca0SAli Bahrami * to this FDE. 2477e16fca0SAli Bahrami * If 'R' is missing from the CIE 2487e16fca0SAli Bahrami * Augmentation String, the field is an 2497e16fca0SAli Bahrami * 8-byte unsigned number. Otherwise, 2507e16fca0SAli Bahrami * the size is determined by the 2517e16fca0SAli Bahrami * corresponding EH_PE encoding in the 2527e16fca0SAli Bahrami * CIE Augmentation Section (the 2537e16fca0SAli Bahrami * value is always absolute). 2547e16fca0SAli Bahrami * 2557e16fca0SAli Bahrami * 5. Optional FDE varying present if CIE augmentation 2567e16fca0SAli Bahrami * Augmentation Section string is non-empty. 2577e16fca0SAli Bahrami * 2587e16fca0SAli Bahrami * 2597e16fca0SAli Bahrami * 'z': 2607e16fca0SAli Bahrami * length uleb128 length of the remainder of the 2617e16fca0SAli Bahrami * FDE augmentation section 2627e16fca0SAli Bahrami * 2637e16fca0SAli Bahrami * 2647e16fca0SAli Bahrami * 'L' (and length > 0): 2657e16fca0SAli Bahrami * LSDA varying LSDA pointer, encoded in the 2667e16fca0SAli Bahrami * format specified by the 2677e16fca0SAli Bahrami * corresponding operand in the CIE's 2687e16fca0SAli Bahrami * augmentation body. 2697e16fca0SAli Bahrami * 2707e16fca0SAli Bahrami * 6. Optional Call varying 2717e16fca0SAli Bahrami * Frame Instructions 2727e16fca0SAli Bahrami * 2737e16fca0SAli Bahrami * The size of the optional call frame instruction area must be computed 2747e16fca0SAli Bahrami * based on the overall size and the offset reached while scanning the 2757e16fca0SAli Bahrami * preceding fields of the FDE. 2767e16fca0SAli Bahrami * 2777e16fca0SAli Bahrami * The overall size of a .eh_frame section is given in the ELF section 2787e16fca0SAli Bahrami * header. The only way to determine the number of entries is to scan 2797e16fca0SAli Bahrami * the section till the end and count. 2807e16fca0SAli Bahrami * 2817e16fca0SAli Bahrami */ 2827e16fca0SAli Bahrami 2837e16fca0SAli Bahrami 2847e16fca0SAli Bahrami 2857e16fca0SAli Bahrami 2867e16fca0SAli Bahrami static uint_t 2877e16fca0SAli Bahrami extract_uint(const uchar_t *data, uint64_t *ndx, int do_swap) 2887e16fca0SAli Bahrami { 2897e16fca0SAli Bahrami uint_t r; 2907e16fca0SAli Bahrami uchar_t *p = (uchar_t *)&r; 2917e16fca0SAli Bahrami 2927e16fca0SAli Bahrami data += *ndx; 2937e16fca0SAli Bahrami if (do_swap) 2947e16fca0SAli Bahrami UL_ASSIGN_BSWAP_WORD(p, data); 2957e16fca0SAli Bahrami else 2967e16fca0SAli Bahrami UL_ASSIGN_WORD(p, data); 2977e16fca0SAli Bahrami 2987e16fca0SAli Bahrami (*ndx) += 4; 2997e16fca0SAli Bahrami return (r); 3007e16fca0SAli Bahrami } 3017e16fca0SAli Bahrami 3027e16fca0SAli Bahrami /* 3037e16fca0SAli Bahrami * Create an unwind header (.eh_frame_hdr) output section. 3047e16fca0SAli Bahrami * The section is created and space reserved, but the data 3057e16fca0SAli Bahrami * is not copied into place. That is done by a later call 3067e16fca0SAli Bahrami * to ld_unwind_populate(), after active relocations have been 3077e16fca0SAli Bahrami * processed. 3087e16fca0SAli Bahrami * 3097e16fca0SAli Bahrami * When GNU linkonce processing is in effect, we can end up in a situation 3107e16fca0SAli Bahrami * where the FDEs related to discarded sections remain in the eh_frame 3117e16fca0SAli Bahrami * section. Ideally, we would remove these dead entries from eh_frame. 3127e16fca0SAli Bahrami * However, that optimization has not yet been implemented. In the current 3137e16fca0SAli Bahrami * implementation, the number of dead FDEs cannot be determined until 3147e16fca0SAli Bahrami * active relocations are processed, and that processing follows the 3157e16fca0SAli Bahrami * call to this function. This means that we are unable to detect dead FDEs 3167e16fca0SAli Bahrami * here, and the section created by this routine is sized for maximum case 3177e16fca0SAli Bahrami * where all FDEs are valid. 3187e16fca0SAli Bahrami */ 3197e16fca0SAli Bahrami uintptr_t 3207e16fca0SAli Bahrami ld_unwind_make_hdr(Ofl_desc *ofl) 3217e16fca0SAli Bahrami { 3227e16fca0SAli Bahrami int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0; 3237e16fca0SAli Bahrami Shdr *shdr; 3247e16fca0SAli Bahrami Elf_Data *elfdata; 3257e16fca0SAli Bahrami Is_desc *isp; 3267e16fca0SAli Bahrami size_t size; 3277e16fca0SAli Bahrami Xword fde_cnt; 32857ef7aa9SRod Evans Aliste idx1; 3297e16fca0SAli Bahrami Os_desc *osp; 3307e16fca0SAli Bahrami 3317e16fca0SAli Bahrami /* 3327e16fca0SAli Bahrami * we only build a unwind header if we have 3337e16fca0SAli Bahrami * some unwind information in the file. 3347e16fca0SAli Bahrami */ 33557ef7aa9SRod Evans if (ofl->ofl_unwind == NULL) 3367e16fca0SAli Bahrami return (1); 3377e16fca0SAli Bahrami 3387e16fca0SAli Bahrami /* 3397e16fca0SAli Bahrami * Allocate and initialize the Elf_Data structure. 3407e16fca0SAli Bahrami */ 341635216b6SRod Evans if ((elfdata = libld_calloc(sizeof (Elf_Data), 1)) == NULL) 3427e16fca0SAli Bahrami return (S_ERROR); 3437e16fca0SAli Bahrami elfdata->d_type = ELF_T_BYTE; 3447e16fca0SAli Bahrami elfdata->d_align = ld_targ.t_m.m_word_align; 3457e16fca0SAli Bahrami elfdata->d_version = ofl->ofl_dehdr->e_version; 3467e16fca0SAli Bahrami 3477e16fca0SAli Bahrami /* 3487e16fca0SAli Bahrami * Allocate and initialize the Shdr structure. 3497e16fca0SAli Bahrami */ 350635216b6SRod Evans if ((shdr = libld_calloc(sizeof (Shdr), 1)) == NULL) 3517e16fca0SAli Bahrami return (S_ERROR); 3527e16fca0SAli Bahrami shdr->sh_type = ld_targ.t_m.m_sht_unwind; 3537e16fca0SAli Bahrami shdr->sh_flags = SHF_ALLOC; 3547e16fca0SAli Bahrami shdr->sh_addralign = ld_targ.t_m.m_word_align; 3557e16fca0SAli Bahrami shdr->sh_entsize = 0; 3567e16fca0SAli Bahrami 3577e16fca0SAli Bahrami /* 3587e16fca0SAli Bahrami * Allocate and initialize the Is_desc structure. 3597e16fca0SAli Bahrami */ 360635216b6SRod Evans if ((isp = libld_calloc(1, sizeof (Is_desc))) == NULL) 3617e16fca0SAli Bahrami return (S_ERROR); 3627e16fca0SAli Bahrami isp->is_name = MSG_ORIG(MSG_SCN_UNWINDHDR); 3637e16fca0SAli Bahrami isp->is_shdr = shdr; 3647e16fca0SAli Bahrami isp->is_indata = elfdata; 3657e16fca0SAli Bahrami 36669112eddSAli Bahrami if ((ofl->ofl_unwindhdr = ld_place_section(ofl, isp, NULL, 3671dd9d86fSAli Bahrami ld_targ.t_id.id_unwindhdr, NULL)) == (Os_desc *)S_ERROR) 3687e16fca0SAli Bahrami return (S_ERROR); 3697e16fca0SAli Bahrami 3707e16fca0SAli Bahrami /* 3717e16fca0SAli Bahrami * Scan through all of the input Frame information, counting each FDE 3727e16fca0SAli Bahrami * that requires an index. Each fde_entry gets a corresponding entry 3737e16fca0SAli Bahrami * in the binary search table. 3747e16fca0SAli Bahrami */ 3757e16fca0SAli Bahrami fde_cnt = 0; 37657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_unwind, idx1, osp)) { 37757ef7aa9SRod Evans Aliste idx2; 3781dd9d86fSAli Bahrami int os_isdescs_idx; 3797e16fca0SAli Bahrami 3801dd9d86fSAli Bahrami OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx2, isp) { 3817e16fca0SAli Bahrami uchar_t *data; 3827e16fca0SAli Bahrami uint64_t off = 0; 3837e16fca0SAli Bahrami 3847e16fca0SAli Bahrami data = isp->is_indata->d_buf; 3857e16fca0SAli Bahrami size = isp->is_indata->d_size; 3867e16fca0SAli Bahrami 3877e16fca0SAli Bahrami while (off < size) { 3887e16fca0SAli Bahrami uint_t length, id; 3897e16fca0SAli Bahrami uint64_t ndx = 0; 3907e16fca0SAli Bahrami 3917e16fca0SAli Bahrami /* 3927e16fca0SAli Bahrami * Extract length in lsb format. A zero length 3937e16fca0SAli Bahrami * indicates that this CIE is a terminator and 3947e16fca0SAli Bahrami * that processing for unwind information is 3957e16fca0SAli Bahrami * complete. 3967e16fca0SAli Bahrami */ 3977e16fca0SAli Bahrami length = extract_uint(data + off, &ndx, bswap); 3987e16fca0SAli Bahrami if (length == 0) 3997e16fca0SAli Bahrami break; 4007e16fca0SAli Bahrami 4017e16fca0SAli Bahrami /* 4027e16fca0SAli Bahrami * Extract CIE id in lsb format. 4037e16fca0SAli Bahrami */ 4047e16fca0SAli Bahrami id = extract_uint(data + off, &ndx, bswap); 4057e16fca0SAli Bahrami 4067e16fca0SAli Bahrami /* 4077e16fca0SAli Bahrami * A CIE record has a id of '0', otherwise 4087e16fca0SAli Bahrami * this is a FDE entry and the 'id' is the 4097e16fca0SAli Bahrami * CIE pointer. 4107e16fca0SAli Bahrami */ 4117e16fca0SAli Bahrami if (id == 0) { 4127e16fca0SAli Bahrami uint_t cieversion; 4137e16fca0SAli Bahrami cieversion = data[off + ndx]; 4147e16fca0SAli Bahrami ndx += 1; 4157e16fca0SAli Bahrami /* BEGIN CSTYLED */ 416cffcfaeeSAlexander Eremin if (cieversion != 1 && cieversion != 3) { 4171007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, 4187e16fca0SAli Bahrami MSG_INTL(MSG_UNW_BADCIEVERS), 4197e16fca0SAli Bahrami isp->is_file->ifl_name, 4207e16fca0SAli Bahrami isp->is_name, off); 4217e16fca0SAli Bahrami return (S_ERROR); 4227e16fca0SAli Bahrami } 4237e16fca0SAli Bahrami /* END CSTYLED */ 4247e16fca0SAli Bahrami } else { 4257e16fca0SAli Bahrami fde_cnt++; 4267e16fca0SAli Bahrami } 4277e16fca0SAli Bahrami off += length + 4; 4287e16fca0SAli Bahrami } 4297e16fca0SAli Bahrami } 4307e16fca0SAli Bahrami } 4317e16fca0SAli Bahrami 4327e16fca0SAli Bahrami /* 4337e16fca0SAli Bahrami * section size: 4347e16fca0SAli Bahrami * byte version +1 4357e16fca0SAli Bahrami * byte eh_frame_ptr_enc +1 4367e16fca0SAli Bahrami * byte fde_count_enc +1 4377e16fca0SAli Bahrami * byte table_enc +1 4387e16fca0SAli Bahrami * 4 bytes eh_frame_ptr +4 4397e16fca0SAli Bahrami * 4 bytes fde_count +4 4407e16fca0SAli Bahrami * [4 bytes] [4bytes] * fde_count ... 4417e16fca0SAli Bahrami */ 4427e16fca0SAli Bahrami size = 12 + (8 * fde_cnt); 4437e16fca0SAli Bahrami 444635216b6SRod Evans if ((elfdata->d_buf = libld_calloc(size, 1)) == NULL) 4457e16fca0SAli Bahrami return (S_ERROR); 4467e16fca0SAli Bahrami elfdata->d_size = size; 4477e16fca0SAli Bahrami shdr->sh_size = (Xword)size; 4487e16fca0SAli Bahrami 4497e16fca0SAli Bahrami return (1); 4507e16fca0SAli Bahrami } 4517e16fca0SAli Bahrami 4527e16fca0SAli Bahrami /* 4537e16fca0SAli Bahrami * the comparator function needs to calculate 4547e16fca0SAli Bahrami * the actual 'initloc' of a bintab entry - to 4557e16fca0SAli Bahrami * do this we initialize the following global to point 4567e16fca0SAli Bahrami * to it. 4577e16fca0SAli Bahrami */ 4587e16fca0SAli Bahrami static Addr framehdr_addr; 4597e16fca0SAli Bahrami 4607e16fca0SAli Bahrami static int 4617e16fca0SAli Bahrami bintabcompare(const void *p1, const void *p2) 4627e16fca0SAli Bahrami { 4637e16fca0SAli Bahrami uint_t *bintab1, *bintab2; 4647e16fca0SAli Bahrami uint_t ent1, ent2; 4657e16fca0SAli Bahrami 4667e16fca0SAli Bahrami bintab1 = (uint_t *)p1; 4677e16fca0SAli Bahrami bintab2 = (uint_t *)p2; 4687e16fca0SAli Bahrami 4697e16fca0SAli Bahrami assert(bintab1 != 0); 4707e16fca0SAli Bahrami assert(bintab2 != 0); 4717e16fca0SAli Bahrami 4727e16fca0SAli Bahrami ent1 = *bintab1 + framehdr_addr; 4737e16fca0SAli Bahrami ent2 = *bintab2 + framehdr_addr; 4747e16fca0SAli Bahrami 4757e16fca0SAli Bahrami if (ent1 > ent2) 4767e16fca0SAli Bahrami return (1); 4777e16fca0SAli Bahrami if (ent1 < ent2) 4787e16fca0SAli Bahrami return (-1); 4797e16fca0SAli Bahrami return (0); 4807e16fca0SAli Bahrami } 4817e16fca0SAli Bahrami 4827e16fca0SAli Bahrami uintptr_t 4837e16fca0SAli Bahrami ld_unwind_populate_hdr(Ofl_desc *ofl) 4847e16fca0SAli Bahrami { 4857e16fca0SAli Bahrami uchar_t *hdrdata; 4867e16fca0SAli Bahrami uint_t *binarytable; 4877e16fca0SAli Bahrami uint_t hdroff; 4887e16fca0SAli Bahrami Aliste idx; 4897e16fca0SAli Bahrami Addr hdraddr; 4907e16fca0SAli Bahrami Os_desc *hdrosp; 4917e16fca0SAli Bahrami Os_desc *osp; 4927e16fca0SAli Bahrami Os_desc *first_unwind; 4937e16fca0SAli Bahrami uint_t fde_count; 4947e16fca0SAli Bahrami uint_t *uint_ptr; 4957e16fca0SAli Bahrami int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0; 4967e16fca0SAli Bahrami 4977e16fca0SAli Bahrami /* 4987e16fca0SAli Bahrami * Are we building the unwind hdr? 4997e16fca0SAli Bahrami */ 5007e16fca0SAli Bahrami if ((hdrosp = ofl->ofl_unwindhdr) == 0) 5017e16fca0SAli Bahrami return (1); 5027e16fca0SAli Bahrami 5037e16fca0SAli Bahrami hdrdata = hdrosp->os_outdata->d_buf; 5047e16fca0SAli Bahrami hdraddr = hdrosp->os_shdr->sh_addr; 5057e16fca0SAli Bahrami hdroff = 0; 5067e16fca0SAli Bahrami 5077e16fca0SAli Bahrami /* 5087e16fca0SAli Bahrami * version == 1 5097e16fca0SAli Bahrami */ 5107e16fca0SAli Bahrami hdrdata[hdroff++] = 1; 5117e16fca0SAli Bahrami /* 5127e16fca0SAli Bahrami * The encodings are: 5137e16fca0SAli Bahrami * 5147e16fca0SAli Bahrami * eh_frameptr_enc sdata4 | pcrel 5157e16fca0SAli Bahrami * fde_count_enc udata4 5167e16fca0SAli Bahrami * table_enc sdata4 | datarel 5177e16fca0SAli Bahrami */ 5187e16fca0SAli Bahrami hdrdata[hdroff++] = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; 5197e16fca0SAli Bahrami hdrdata[hdroff++] = DW_EH_PE_udata4; 5207e16fca0SAli Bahrami hdrdata[hdroff++] = DW_EH_PE_sdata4 | DW_EH_PE_datarel; 5217e16fca0SAli Bahrami 5227e16fca0SAli Bahrami /* 5237e16fca0SAli Bahrami * Header Offsets 5247e16fca0SAli Bahrami * ----------------------------------- 5257e16fca0SAli Bahrami * byte version +1 5267e16fca0SAli Bahrami * byte eh_frame_ptr_enc +1 5277e16fca0SAli Bahrami * byte fde_count_enc +1 5287e16fca0SAli Bahrami * byte table_enc +1 5297e16fca0SAli Bahrami * 4 bytes eh_frame_ptr +4 5307e16fca0SAli Bahrami * 4 bytes fde_count +4 5317e16fca0SAli Bahrami */ 5327e16fca0SAli Bahrami /* LINTED */ 5337e16fca0SAli Bahrami binarytable = (uint_t *)(hdrdata + 12); 5347e16fca0SAli Bahrami first_unwind = 0; 5357e16fca0SAli Bahrami fde_count = 0; 5367e16fca0SAli Bahrami 5377e16fca0SAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) { 5387e16fca0SAli Bahrami uchar_t *data; 5397e16fca0SAli Bahrami size_t size; 540*37915d86SRichard Lowe uint64_t off = 0, ujunk; 541*37915d86SRichard Lowe int64_t sjunk; 5427e16fca0SAli Bahrami uint_t cieRflag = 0, ciePflag = 0; 5437e16fca0SAli Bahrami Shdr *shdr; 5447e16fca0SAli Bahrami 5457e16fca0SAli Bahrami /* 5467e16fca0SAli Bahrami * remember first UNWIND section to 5477e16fca0SAli Bahrami * point to in the frame_ptr entry. 5487e16fca0SAli Bahrami */ 5497e16fca0SAli Bahrami if (first_unwind == 0) 5507e16fca0SAli Bahrami first_unwind = osp; 5517e16fca0SAli Bahrami 5527e16fca0SAli Bahrami data = osp->os_outdata->d_buf; 5537e16fca0SAli Bahrami shdr = osp->os_shdr; 5547e16fca0SAli Bahrami size = shdr->sh_size; 5557e16fca0SAli Bahrami 5567e16fca0SAli Bahrami while (off < size) { 5577e16fca0SAli Bahrami uint_t length, id; 5587e16fca0SAli Bahrami uint64_t ndx = 0; 5597e16fca0SAli Bahrami 5607e16fca0SAli Bahrami /* 5617e16fca0SAli Bahrami * Extract length in lsb format. A zero length 5627e16fca0SAli Bahrami * indicates that this CIE is a terminator and that 5637e16fca0SAli Bahrami * processing of unwind information is complete. 5647e16fca0SAli Bahrami */ 5657e16fca0SAli Bahrami length = extract_uint(data + off, &ndx, bswap); 5667e16fca0SAli Bahrami if (length == 0) 5677e16fca0SAli Bahrami goto done; 5687e16fca0SAli Bahrami 5697e16fca0SAli Bahrami /* 5707e16fca0SAli Bahrami * Extract CIE id in lsb format. 5717e16fca0SAli Bahrami */ 5727e16fca0SAli Bahrami id = extract_uint(data + off, &ndx, bswap); 5737e16fca0SAli Bahrami 5747e16fca0SAli Bahrami /* 5757e16fca0SAli Bahrami * A CIE record has a id of '0'; otherwise 5767e16fca0SAli Bahrami * this is a FDE entry and the 'id' is the 5777e16fca0SAli Bahrami * CIE pointer. 5787e16fca0SAli Bahrami */ 5797e16fca0SAli Bahrami if (id == 0) { 5807e16fca0SAli Bahrami char *cieaugstr; 5817e16fca0SAli Bahrami uint_t cieaugndx; 582cffcfaeeSAlexander Eremin uint_t cieversion; 5837e16fca0SAli Bahrami 5847e16fca0SAli Bahrami ciePflag = 0; 5857e16fca0SAli Bahrami cieRflag = 0; 5867e16fca0SAli Bahrami /* 5877e16fca0SAli Bahrami * We need to drill through the CIE 5887e16fca0SAli Bahrami * to find the Rflag. It's the Rflag 5897e16fca0SAli Bahrami * which describes how the FDE code-pointers 5907e16fca0SAli Bahrami * are encoded. 5917e16fca0SAli Bahrami */ 5927e16fca0SAli Bahrami 593cffcfaeeSAlexander Eremin cieversion = data[off + ndx]; 594cffcfaeeSAlexander Eremin ndx += 1; 5957e16fca0SAli Bahrami 5967e16fca0SAli Bahrami /* 5977e16fca0SAli Bahrami * augstr 5987e16fca0SAli Bahrami */ 5997e16fca0SAli Bahrami cieaugstr = (char *)(&data[off + ndx]); 6007e16fca0SAli Bahrami ndx += strlen(cieaugstr) + 1; 6017e16fca0SAli Bahrami 6027e16fca0SAli Bahrami /* 6037e16fca0SAli Bahrami * calign & dalign 6047e16fca0SAli Bahrami */ 605*37915d86SRichard Lowe if (uleb_extract(&data[off], &ndx, 606*37915d86SRichard Lowe size - off, &ujunk) == DW_OVERFLOW) { 607*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 608*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFOVRFLW), 609*37915d86SRichard Lowe ofl->ofl_name, 610*37915d86SRichard Lowe osp->os_name); 611*37915d86SRichard Lowe return (S_ERROR); 612*37915d86SRichard Lowe } 613*37915d86SRichard Lowe 614*37915d86SRichard Lowe if (sleb_extract(&data[off], &ndx, 615*37915d86SRichard Lowe size - off, &sjunk) == DW_OVERFLOW) { 616*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 617*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFOVRFLW), 618*37915d86SRichard Lowe ofl->ofl_name, 619*37915d86SRichard Lowe osp->os_name); 620*37915d86SRichard Lowe return (S_ERROR); 621*37915d86SRichard Lowe } 6227e16fca0SAli Bahrami 6237e16fca0SAli Bahrami /* 6247e16fca0SAli Bahrami * retreg 6257e16fca0SAli Bahrami */ 626*37915d86SRichard Lowe if (cieversion == 1) { 6277e16fca0SAli Bahrami ndx++; 628*37915d86SRichard Lowe } else { 629*37915d86SRichard Lowe if (uleb_extract(&data[off], &ndx, 630*37915d86SRichard Lowe size - off, &ujunk) == 631*37915d86SRichard Lowe DW_OVERFLOW) { 632*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 633*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFOVRFLW), 634*37915d86SRichard Lowe ofl->ofl_name, 635*37915d86SRichard Lowe osp->os_name); 636*37915d86SRichard Lowe return (S_ERROR); 637*37915d86SRichard Lowe } 638*37915d86SRichard Lowe } 6397e16fca0SAli Bahrami /* 6407e16fca0SAli Bahrami * we walk through the augmentation 6417e16fca0SAli Bahrami * section now looking for the Rflag 6427e16fca0SAli Bahrami */ 6437e16fca0SAli Bahrami for (cieaugndx = 0; cieaugstr[cieaugndx]; 6447e16fca0SAli Bahrami cieaugndx++) { 6457e16fca0SAli Bahrami /* BEGIN CSTYLED */ 6467e16fca0SAli Bahrami switch (cieaugstr[cieaugndx]) { 6477e16fca0SAli Bahrami case 'z': 6487e16fca0SAli Bahrami /* size */ 649*37915d86SRichard Lowe if (uleb_extract(&data[off], 650*37915d86SRichard Lowe &ndx, size - off, &ujunk) == 651*37915d86SRichard Lowe DW_OVERFLOW) { 652*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 653*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFOVRFLW), 654*37915d86SRichard Lowe ofl->ofl_name, 655*37915d86SRichard Lowe osp->os_name); 656*37915d86SRichard Lowe return (S_ERROR); 657*37915d86SRichard Lowe } 6587e16fca0SAli Bahrami break; 6597e16fca0SAli Bahrami case 'P': 6607e16fca0SAli Bahrami /* personality */ 6617e16fca0SAli Bahrami ciePflag = data[off + ndx]; 6627e16fca0SAli Bahrami ndx++; 6637e16fca0SAli Bahrami /* 6647e16fca0SAli Bahrami * Just need to extract the 6657e16fca0SAli Bahrami * value to move on to the next 6667e16fca0SAli Bahrami * field. 6677e16fca0SAli Bahrami */ 668*37915d86SRichard Lowe switch (dwarf_ehe_extract( 669*37915d86SRichard Lowe &data[off], size - off, 670*37915d86SRichard Lowe &ndx, &ujunk, ciePflag, 671965630c1SRichard Lowe ofl->ofl_dehdr->e_ident, B_FALSE, 672*37915d86SRichard Lowe shdr->sh_addr, off + ndx, 0)) { 673*37915d86SRichard Lowe case DW_OVERFLOW: 674*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 675*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFOVRFLW), 676*37915d86SRichard Lowe ofl->ofl_name, 677*37915d86SRichard Lowe osp->os_name); 678*37915d86SRichard Lowe return (S_ERROR); 679*37915d86SRichard Lowe case DW_BAD_ENCODING: 680*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 681*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFBADENC), 682*37915d86SRichard Lowe ofl->ofl_name, 683*37915d86SRichard Lowe osp->os_name, ciePflag); 684*37915d86SRichard Lowe return (S_ERROR); 685*37915d86SRichard Lowe case DW_SUCCESS: 686*37915d86SRichard Lowe break; 687*37915d86SRichard Lowe } 6887e16fca0SAli Bahrami break; 6897e16fca0SAli Bahrami case 'R': 6907e16fca0SAli Bahrami /* code encoding */ 6917e16fca0SAli Bahrami cieRflag = data[off + ndx]; 6927e16fca0SAli Bahrami ndx++; 6937e16fca0SAli Bahrami break; 6947e16fca0SAli Bahrami case 'L': 6957e16fca0SAli Bahrami /* lsda encoding */ 6967e16fca0SAli Bahrami ndx++; 6977e16fca0SAli Bahrami break; 6987e16fca0SAli Bahrami } 6997e16fca0SAli Bahrami /* END CSTYLED */ 7007e16fca0SAli Bahrami } 7017e16fca0SAli Bahrami } else { 7027e16fca0SAli Bahrami uint_t bintabndx; 7037e16fca0SAli Bahrami uint64_t initloc; 7047e16fca0SAli Bahrami uint64_t fdeaddr; 705965630c1SRichard Lowe uint64_t gotaddr = 0; 706965630c1SRichard Lowe 707965630c1SRichard Lowe if (ofl->ofl_osgot != NULL) 708965630c1SRichard Lowe gotaddr = 709965630c1SRichard Lowe ofl->ofl_osgot->os_shdr->sh_addr; 7107e16fca0SAli Bahrami 711*37915d86SRichard Lowe switch (dwarf_ehe_extract(&data[off], 712*37915d86SRichard Lowe size - off, &ndx, &initloc, cieRflag, 713*37915d86SRichard Lowe ofl->ofl_dehdr->e_ident, B_FALSE, 714*37915d86SRichard Lowe shdr->sh_addr, off + ndx, gotaddr)) { 715*37915d86SRichard Lowe case DW_OVERFLOW: 716*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 717*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFOVRFLW), 718*37915d86SRichard Lowe ofl->ofl_name, 719*37915d86SRichard Lowe osp->os_name); 720*37915d86SRichard Lowe return (S_ERROR); 721*37915d86SRichard Lowe case DW_BAD_ENCODING: 722*37915d86SRichard Lowe ld_eprintf(ofl, ERR_FATAL, 723*37915d86SRichard Lowe MSG_INTL(MSG_SCN_DWFBADENC), 724*37915d86SRichard Lowe ofl->ofl_name, 725*37915d86SRichard Lowe osp->os_name, cieRflag); 726*37915d86SRichard Lowe return (S_ERROR); 727*37915d86SRichard Lowe case DW_SUCCESS: 728*37915d86SRichard Lowe break; 729*37915d86SRichard Lowe } 7307e16fca0SAli Bahrami 7317e16fca0SAli Bahrami /* 7327e16fca0SAli Bahrami * Ignore FDEs with initloc set to 0. 7337e16fca0SAli Bahrami * initloc will not be 0 unless this FDE was 7347e16fca0SAli Bahrami * abandoned due to GNU linkonce processing. 7357e16fca0SAli Bahrami * The 0 value occurs because we don't resolve 7367e16fca0SAli Bahrami * sloppy relocations for unwind header target 7377e16fca0SAli Bahrami * sections. 7387e16fca0SAli Bahrami */ 7397e16fca0SAli Bahrami if (initloc != 0) { 7407e16fca0SAli Bahrami bintabndx = fde_count * 2; 7417e16fca0SAli Bahrami fde_count++; 7427e16fca0SAli Bahrami 7437e16fca0SAli Bahrami /* 7447e16fca0SAli Bahrami * FDEaddr is adjusted 7457e16fca0SAli Bahrami * to account for the length & id which 7467e16fca0SAli Bahrami * have already been consumed. 7477e16fca0SAli Bahrami */ 7487e16fca0SAli Bahrami fdeaddr = shdr->sh_addr + off; 7497e16fca0SAli Bahrami 7507e16fca0SAli Bahrami binarytable[bintabndx] = 7517e16fca0SAli Bahrami (uint_t)(initloc - hdraddr); 7527e16fca0SAli Bahrami binarytable[bintabndx + 1] = 7537e16fca0SAli Bahrami (uint_t)(fdeaddr - hdraddr); 7547e16fca0SAli Bahrami } 7557e16fca0SAli Bahrami } 7567e16fca0SAli Bahrami 7577e16fca0SAli Bahrami /* 7587e16fca0SAli Bahrami * the length does not include the length 7597e16fca0SAli Bahrami * itself - so account for that too. 7607e16fca0SAli Bahrami */ 7617e16fca0SAli Bahrami off += length + 4; 7627e16fca0SAli Bahrami } 7637e16fca0SAli Bahrami } 7647e16fca0SAli Bahrami 7657e16fca0SAli Bahrami done: 7667e16fca0SAli Bahrami /* 7677e16fca0SAli Bahrami * Do a quicksort on the binary table. If this is a cross 7687e16fca0SAli Bahrami * link from a system with the opposite byte order, xlate 7697e16fca0SAli Bahrami * the resulting values into LSB order. 7707e16fca0SAli Bahrami */ 7717e16fca0SAli Bahrami framehdr_addr = hdraddr; 7727e16fca0SAli Bahrami qsort((void *)binarytable, (size_t)fde_count, 7737e16fca0SAli Bahrami (size_t)(sizeof (uint_t) * 2), bintabcompare); 7747e16fca0SAli Bahrami if (bswap) { 7757e16fca0SAli Bahrami uint_t *btable = binarytable; 7767e16fca0SAli Bahrami uint_t cnt; 7777e16fca0SAli Bahrami 7787e16fca0SAli Bahrami for (cnt = fde_count * 2; cnt-- > 0; btable++) 7797e16fca0SAli Bahrami *btable = ld_bswap_Word(*btable); 7807e16fca0SAli Bahrami } 7817e16fca0SAli Bahrami 7827e16fca0SAli Bahrami /* 7837e16fca0SAli Bahrami * Fill in: 7847e16fca0SAli Bahrami * first_frame_ptr 7857e16fca0SAli Bahrami * fde_count 7867e16fca0SAli Bahrami */ 7877e16fca0SAli Bahrami hdroff = 4; 7887e16fca0SAli Bahrami /* LINTED */ 7897e16fca0SAli Bahrami uint_ptr = (uint_t *)(&hdrdata[hdroff]); 7907e16fca0SAli Bahrami *uint_ptr = first_unwind->os_shdr->sh_addr - 7917e16fca0SAli Bahrami (hdrosp->os_shdr->sh_addr + hdroff); 7927e16fca0SAli Bahrami if (bswap) 7937e16fca0SAli Bahrami *uint_ptr = ld_bswap_Word(*uint_ptr); 7947e16fca0SAli Bahrami 7957e16fca0SAli Bahrami hdroff += 4; 7967e16fca0SAli Bahrami /* LINTED */ 7977e16fca0SAli Bahrami uint_ptr = (uint_t *)&hdrdata[hdroff]; 7987e16fca0SAli Bahrami *uint_ptr = fde_count; 7997e16fca0SAli Bahrami if (bswap) 8007e16fca0SAli Bahrami *uint_ptr = ld_bswap_Word(*uint_ptr); 8017e16fca0SAli Bahrami 8027e16fca0SAli Bahrami /* 8037e16fca0SAli Bahrami * If relaxed relocations are active, then there is a chance 8047e16fca0SAli Bahrami * that we didn't use all the space reserved for this section. 8057e16fca0SAli Bahrami * For details, see the note at head of ld_unwind_make_hdr() above. 8067e16fca0SAli Bahrami * 8077e16fca0SAli Bahrami * Find the PT_SUNW_UNWIND program header, and change the size values 8087e16fca0SAli Bahrami * to the size of the subset of the section that was actually used. 8097e16fca0SAli Bahrami */ 8107e16fca0SAli Bahrami if (ofl->ofl_flags1 & FLG_OF1_RLXREL) { 8117e16fca0SAli Bahrami Word phnum = ofl->ofl_nehdr->e_phnum; 8127e16fca0SAli Bahrami Phdr *phdr = ofl->ofl_phdr; 8137e16fca0SAli Bahrami 8147e16fca0SAli Bahrami for (; phnum-- > 0; phdr++) { 8157e16fca0SAli Bahrami if (phdr->p_type == PT_SUNW_UNWIND) { 8167e16fca0SAli Bahrami phdr->p_memsz = 12 + (8 * fde_count); 8177e16fca0SAli Bahrami phdr->p_filesz = phdr->p_memsz; 8187e16fca0SAli Bahrami break; 8197e16fca0SAli Bahrami } 8207e16fca0SAli Bahrami } 8217e16fca0SAli Bahrami } 8227e16fca0SAli Bahrami 8237e16fca0SAli Bahrami return (1); 8247e16fca0SAli Bahrami } 8257e16fca0SAli Bahrami 8267e16fca0SAli Bahrami /* 8277e16fca0SAli Bahrami * Append an .eh_frame section to our output list if not already present. 8287e16fca0SAli Bahrami * 8297e16fca0SAli Bahrami * Usually, there is a single .eh_frame output section. However, there can 8307e16fca0SAli Bahrami * be more if there are incompatible section flags on incoming sections. 8317e16fca0SAli Bahrami * If this does happen, the frame_ptr field of the eh_frame_hdr section 8327e16fca0SAli Bahrami * will point at the base of the first output section, and the other 8337e16fca0SAli Bahrami * sections will not be accessible via frame_ptr. However, the .eh_frame_hdr 8347e16fca0SAli Bahrami * will be able to access all the data in the different .eh_frame sections, 8357e16fca0SAli Bahrami * because the entries in sorted table are all encoded as DW_EH_PE_datarel. 8367e16fca0SAli Bahrami */ 8377e16fca0SAli Bahrami uintptr_t 8387e16fca0SAli Bahrami ld_unwind_register(Os_desc *osp, Ofl_desc * ofl) 8397e16fca0SAli Bahrami { 8407e16fca0SAli Bahrami Aliste idx; 8417e16fca0SAli Bahrami Os_desc *_osp; 8427e16fca0SAli Bahrami /* 8437e16fca0SAli Bahrami * Check to see if this output section is already 8447e16fca0SAli Bahrami * on the list. 8457e16fca0SAli Bahrami */ 8467e16fca0SAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, _osp)) 8477e16fca0SAli Bahrami if (osp == _osp) 8487e16fca0SAli Bahrami return (1); 8497e16fca0SAli Bahrami 8507e16fca0SAli Bahrami /* 8517e16fca0SAli Bahrami * Append output section to unwind list 8527e16fca0SAli Bahrami */ 85357ef7aa9SRod Evans if (aplist_append(&ofl->ofl_unwind, osp, AL_CNT_OFL_UNWIND) == NULL) 8547e16fca0SAli Bahrami return (S_ERROR); 85557ef7aa9SRod Evans 8567e16fca0SAli Bahrami return (1); 8577e16fca0SAli Bahrami } 858