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
extract_uint(const uchar_t * data,uint64_t * ndx,int do_swap)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
ld_unwind_make_hdr(Ofl_desc * ofl)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
bintabcompare(const void * p1,const void * p2)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
ld_unwind_populate_hdr(Ofl_desc * ofl)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
ld_unwind_register(Os_desc * osp,Ofl_desc * ofl)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