unwind.c revision 57ef7aa924e4bfdf3118d9b5b4285dfc94b632f3
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * CDDL HEADER START
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The contents of this file are subject to the terms of the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Common Development and Distribution License (the "License").
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * You may not use this file except in compliance with the License.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * or http://www.opensolaris.org/os/licensing.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * See the License for the specific language governing permissions
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * and limitations under the License.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * When distributing Covered Code, include this CDDL HEADER in each
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * If applicable, add the following below this CDDL HEADER, with the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * fields enclosed by brackets "[]" replaced with your own identifying
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * information: Portions Copyright [yyyy] [name of copyright owner]
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * CDDL HEADER END
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/*
d1f855d73e0bf529109aa3dc1b967fc6ac19b4fc * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Use is subject to license terms.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <string.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <stdio.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <sys/types.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <sgs.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <debug.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <_libld.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <dwarf.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek#include <stdlib.h>
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * A EH_FRAME_HDR consists of the following:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Encoding Field
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * --------------------------------
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * unsigned byte version
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * unsigned byte eh_frame_ptr_enc
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * unsigned byte fde_count_enc
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * unsigned byte table_enc
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * encoded eh_frame_ptr
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * encoded fde_count
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * [ binary search table ]
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The binary search table entries each consists of:
99653d4ee642c6528e88224f12409a5f23060994eschrock *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * encoded initial_func_loc
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * encoded FDE_address
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The entries in the binary search table are sorted
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * in a increasing order by the initial location.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * version
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Version of the .eh_frame_hdr format. This value shall be 1.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * eh_frame_ptr_enc
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The encoding format of the eh_frame_ptr field. For shared
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * libraries the encoding must be
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * DW_EH_PE_sdata4|DW_EH_PE_pcrel or
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * DW_EH_PE_sdata4|DW_EH_PE_datarel.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * fde_count_enc
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The encoding format of the fde_count field. A value of
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * DW_EH_PE_omit indicates the binary search table is not
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * present.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * table_enc
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The encoding format of the entries in the binary search
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * table. A value of DW_EH_PE_omit indicates the binary search
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * table is not present. For shared libraries the encoding
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * must be DW_EH_PE_sdata4|DW_EH_PE_pcrel or
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * DW_EH_PE_sdata4|DW_EH_PE_datarel.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * eh_frame_ptr
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The encoded value of the pointer to the start of the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * .eh_frame section.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * fde_count
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The encoded value of the count of entries in the binary
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * search table.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * binary search table
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * A binary search table containing fde_count entries. Each
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * entry of the table consist of two encoded values, the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * initial location of the function to which an FDE applies,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * and the address of the FDE. The entries are sorted in an
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * increasing order by the initial location value.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * EH_FRAME sections
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * =================
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The call frame information needed for unwinding the stack is output in
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * an ELF section(s) of type SHT_AMD64_UNWIND (amd64) or SHT_PROGBITS (other).
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * In the simplest case there will be one such section per object file and it
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * will be named ".eh_frame". An .eh_frame section consists of one or more
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * subsections. Each subsection contains a CIE (Common Information Entry)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * followed by varying number of FDEs (Frame Descriptor Entry). A FDE
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * corresponds to an explicit or compiler generated function in a
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * compilation unit, all FDEs can access the CIE that begins their
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * subsection for data.
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * If an object file contains C++ template instantiations, there shall be
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * a separate CIE immediately preceding each FDE corresponding to an
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * instantiation.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * Using the preferred encoding specified below, the .eh_frame section can
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * be entirely resolved at link time and thus can become part of the
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * text segment.
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * .eh_frame Section Layout
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * ------------------------
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * EH_PE encoding below refers to the pointer encoding as specified in the
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * enhanced LSB Chapter 7 for Eh_Frame_Hdr.
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * Common Information Entry (CIE)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * ------------------------------
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * CIE has the following format:
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * Length
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * in
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * Field Byte Description
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * ----- ------ -----------
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * 1. Length 4 Length of CIE (not including
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * this 4-byte field).
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * 2. CIE id 4 Value Zero (0) for .eh_frame
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * (used to distinguish CIEs and
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * FDEs when scanning the section)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * 3. Version 1 Value One (1)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * 4. CIE Augmentation string Null-terminated string with legal
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * values being "" or 'z' optionally
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * followed by single occurrences of
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * 'P', 'L', or 'R' in any order.
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * String The presence of character(s) in the
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * string dictates the content of
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * field 8, the Augmentation Section.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Each character has one or two
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * associated operands in the AS.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Operand order depends on
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * position in the string ('z' must
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * be first).
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 5. Code Align Factor uleb128 To be multiplied with the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * "Advance Location" instructions in
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the Call Frame Instructions
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 6. Data Align Factor sleb128 To be multiplied with all offset
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * in the Call Frame Instructions
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 7. Ret Address Reg 1 A "virtual" register representation
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * of the return address. In Dwarf V2,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * this is a byte, otherwise it is
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * uleb128. It is a byte in gcc 3.3.x
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 8. Optional CIE varying Present if Augmentation String in
99653d4ee642c6528e88224f12409a5f23060994eschrock * Augmentation Section field 4 is not 0.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * z:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * size uleb128 Length of the remainder of the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Augmentation Section
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * P:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * personality_enc 1 Encoding specifier - preferred
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * value is a pc-relative, signed
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 4-byte
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * personality routine (encoded) Encoded pointer to personality
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * routine (actually to the PLT
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * entry for the personality
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * routine)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * R:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * code_enc 1 Non-default encoding for the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * code-pointers (FDE members
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * "initial_location" and "address_range"
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * and the operand for DW_CFA_set_loc)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * - preferred value is pc-relative,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * signed 4-byte.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * L:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * lsda_enc 1 FDE augmentation bodies may contain
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * LSDA pointers. If so they are
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * encoded as specified here -
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * preferred value is pc-relative,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * signed 4-byte possibly indirect
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * thru a GOT entry.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * 9. Optional Call Frame varying
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Instructions
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The size of the optional call frame instruction area must be computed
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * based on the overall size and the offset reached while scanning the
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * preceding fields of the CIE.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * Frame Descriptor Entry (FDE)
c75cc341903ca38e644edfae5357a4020418f9be * ----------------------------
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * FDE has the following format:
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Length
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * in
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Field Byte Description
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * ----- ------ -----------
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 1. Length 4 Length of remainder of this FDE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * 2. CIE Pointer 4 Distance from this field to the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * nearest preceding CIE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * (uthe value is subtracted from the
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * current address). This value
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * can never be zero and thus can
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * be used to distinguish CIE's and
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * FDE's when scanning the
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * .eh_frame section
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek *
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * 3. Initial Location varying Reference to the function code
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * corresponding to this FDE.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * If 'R' is missing from the CIE
c75cc341903ca38e644edfae5357a4020418f9be * Augmentation String, the field is an
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * 8-byte absolute pointer. Otherwise,
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * the corresponding EH_PE encoding in the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * CIE Augmentation Section is used to
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * interpret the reference.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 4. Address Range varying Size of the function code corresponding
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * to this FDE.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * If 'R' is missing from the CIE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Augmentation String, the field is an
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 8-byte unsigned number. Otherwise,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the size is determined by the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * corresponding EH_PE encoding in the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * CIE Augmentation Section (the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * value is always absolute).
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 5. Optional FDE varying present if CIE augmentation
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Augmentation Section string is non-empty.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 'z':
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * length uleb128 length of the remainder of the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * FDE augmentation section
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 'L' (and length > 0):
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * LSDA varying LSDA pointer, encoded in the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * format specified by the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * corresponding operand in the CIE's
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * augmentation body.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 6. Optional Call varying
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Frame Instructions
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The size of the optional call frame instruction area must be computed
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * based on the overall size and the offset reached while scanning the
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * preceding fields of the FDE.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The overall size of a .eh_frame section is given in the ELF section
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * header. The only way to determine the number of entries is to scan
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the section till the end and count.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekstatic uint_t
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekextract_uint(const uchar_t *data, uint64_t *ndx, int do_swap)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek{
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t r;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uchar_t *p = (uchar_t *)&r;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek data += *ndx;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (do_swap)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek UL_ASSIGN_BSWAP_WORD(p, data);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek else
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek UL_ASSIGN_WORD(p, data);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek (*ndx) += 4;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (r);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek}
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Create an unwind header (.eh_frame_hdr) output section.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The section is created and space reserved, but the data
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * is not copied into place. That is done by a later call
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * to ld_unwind_populate(), after active relocations have been
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * processed.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek *
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * When GNU linkonce processing is in effect, we can end up in a situation
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * where the FDEs related to discarded sections remain in the eh_frame
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * section. Ideally, we would remove these dead entries from eh_frame.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * However, that optimization has not yet been implemented. In the current
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * implementation, the number of dead FDEs cannot be determined until
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * active relocations are processed, and that processing follows the
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens * call to this function. This means that we are unable to detect dead FDEs
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * here, and the section created by this routine is sized for maximum case
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * where all FDEs are valid.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekuintptr_t
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekld_unwind_make_hdr(Ofl_desc *ofl)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek{
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Shdr *shdr;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Elf_Data *elfdata;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Is_desc *isp;
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek size_t size;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Xword fde_cnt;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Aliste idx1;
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek Os_desc *osp;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /*
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * we only build a unwind header if we have
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * some unwind information in the file.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if (ofl->ofl_unwind == NULL)
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek return (1);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /*
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * Allocate and initialize the Elf_Data structure.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek */
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek if ((elfdata = libld_calloc(sizeof (Elf_Data), 1)) == 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (S_ERROR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek elfdata->d_type = ELF_T_BYTE;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek elfdata->d_align = ld_targ.t_m.m_word_align;
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek elfdata->d_version = ofl->ofl_dehdr->e_version;
c75cc341903ca38e644edfae5357a4020418f9be
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek /*
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek * Allocate and initialize the Shdr structure.
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((shdr = libld_calloc(sizeof (Shdr), 1)) == 0)
ff17c8bf86c3e567734be83f90267edee20f580fgjelinek return (S_ERROR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek shdr->sh_type = ld_targ.t_m.m_sht_unwind;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek shdr->sh_flags = SHF_ALLOC;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek shdr->sh_addralign = ld_targ.t_m.m_word_align;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek shdr->sh_entsize = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Allocate and initialize the Is_desc structure.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((isp = libld_calloc(1, sizeof (Is_desc))) == 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (S_ERROR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek isp->is_name = MSG_ORIG(MSG_SCN_UNWINDHDR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek isp->is_shdr = shdr;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek isp->is_indata = elfdata;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((ofl->ofl_unwindhdr = ld_place_section(ofl, isp,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek ld_targ.t_id.id_unwindhdr, 0)) == (Os_desc *)S_ERROR)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (S_ERROR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Scan through all of the input Frame information, counting each FDE
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * that requires an index. Each fde_entry gets a corresponding entry
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * in the binary search table.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek fde_cnt = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek for (APLIST_TRAVERSE(ofl->ofl_unwind, idx1, osp)) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Aliste idx2;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek for (APLIST_TRAVERSE(osp->os_isdescs, idx2, isp)) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uchar_t *data;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint64_t off = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek data = isp->is_indata->d_buf;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek size = isp->is_indata->d_size;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek while (off < size) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t length, id;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint64_t ndx = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Extract length in lsb format. A zero length
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * indicates that this CIE is a terminator and
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * that processing for unwind information is
99653d4ee642c6528e88224f12409a5f23060994eschrock * complete.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek length = extract_uint(data + off, &ndx, bswap);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (length == 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek break;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
5f8e16172ef40e14cf931b329fedb86ea369a42cnn /*
5f8e16172ef40e14cf931b329fedb86ea369a42cnn * Extract CIE id in lsb format.
5f8e16172ef40e14cf931b329fedb86ea369a42cnn */
5f8e16172ef40e14cf931b329fedb86ea369a42cnn id = extract_uint(data + off, &ndx, bswap);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /*
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * A CIE record has a id of '0', otherwise
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * this is a FDE entry and the 'id' is the
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * CIE pointer.
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (id == 0) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock uint_t cieversion;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock /*
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock * The only CIE version supported
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * is '1' - quick sanity check
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * here.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek cieversion = data[off + ndx];
990b4856d0eaada6f8140335733a1b1771ed2746lling ndx += 1;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /* BEGIN CSTYLED */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (cieversion != 1) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek eprintf(ofl->ofl_lml, ERR_FATAL,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek MSG_INTL(MSG_UNW_BADCIEVERS),
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek isp->is_file->ifl_name,
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek isp->is_name, off);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (S_ERROR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek }
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /* END CSTYLED */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek } else {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek fde_cnt++;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock off += length + 4;
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock }
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * section size:
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte version +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte eh_frame_ptr_enc +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte fde_count_enc +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte table_enc +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 4 bytes eh_frame_ptr +4
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 4 bytes fde_count +4
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * [4 bytes] [4bytes] * fde_count ...
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek size = 12 + (8 * fde_cnt);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if ((elfdata->d_buf = libld_calloc(size, 1)) == 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (S_ERROR);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek elfdata->d_size = size;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek shdr->sh_size = (Xword)size;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (1);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek}
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek/*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the comparator function needs to calculate
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * the actual 'initloc' of a bintab entry - to
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * do this we initialize the following global to point
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * to it.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekstatic Addr framehdr_addr;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekstatic int
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekbintabcompare(const void *p1, const void *p2)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek{
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t *bintab1, *bintab2;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t ent1, ent2;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek bintab1 = (uint_t *)p1;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek bintab2 = (uint_t *)p2;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek assert(bintab1 != 0);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek assert(bintab2 != 0);
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek ent1 = *bintab1 + framehdr_addr;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek ent2 = *bintab2 + framehdr_addr;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek if (ent1 > ent2)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek return (1);
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek if (ent1 < ent2)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek return (-1);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek return (0);
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek}
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinekuintptr_t
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinekld_unwind_populate_hdr(Ofl_desc *ofl)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek{
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek uchar_t *hdrdata;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek uint_t *binarytable;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t hdroff;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Aliste idx;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek Addr hdraddr;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek Os_desc *hdrosp;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek Os_desc *osp;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Os_desc *first_unwind;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek uint_t fde_count;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek uint_t *uint_ptr;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek int bswap = (ofl->ofl_flags1 & FLG_OF1_ENCDIFF) != 0;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * Are we building the unwind hdr?
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek */
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek if ((hdrosp = ofl->ofl_unwindhdr) == 0)
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek return (1);
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek hdrdata = hdrosp->os_outdata->d_buf;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek hdraddr = hdrosp->os_shdr->sh_addr;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek hdroff = 0;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek /*
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * version == 1
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek hdrdata[hdroff++] = 1;
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * The encodings are:
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek *
11506c4105b984bf64636b0e2f9e88bd67fb9651gjelinek * eh_frameptr_enc sdata4 | pcrel
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * fde_count_enc udata4
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * table_enc sdata4 | datarel
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek hdrdata[hdroff++] = DW_EH_PE_sdata4 | DW_EH_PE_pcrel;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek hdrdata[hdroff++] = DW_EH_PE_udata4;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek hdrdata[hdroff++] = DW_EH_PE_sdata4 | DW_EH_PE_datarel;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Header Offsets
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * -----------------------------------
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte version +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte eh_frame_ptr_enc +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte fde_count_enc +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * byte table_enc +1
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 4 bytes eh_frame_ptr +4
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * 4 bytes fde_count +4
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /* LINTED */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek binarytable = (uint_t *)(hdrdata + 12);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek first_unwind = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek fde_count = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, osp)) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uchar_t *data;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek size_t size;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint64_t off = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t cieRflag = 0, ciePflag = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek Shdr *shdr;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * remember first UNWIND section to
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * point to in the frame_ptr entry.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (first_unwind == 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek first_unwind = osp;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek data = osp->os_outdata->d_buf;
990b4856d0eaada6f8140335733a1b1771ed2746lling shdr = osp->os_shdr;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek size = shdr->sh_size;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek while (off < size) {
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint_t length, id;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek uint64_t ndx = 0;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
99653d4ee642c6528e88224f12409a5f23060994eschrock /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Extract length in lsb format. A zero length
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * indicates that this CIE is a terminator and that
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * processing of unwind information is complete.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek length = extract_uint(data + off, &ndx, bswap);
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek if (length == 0)
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek goto done;
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek /*
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek * Extract CIE id in lsb format.
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek */
0b5de56d26c0148ad33bb3a9201091502f24d910gjelinek id = extract_uint(data + off, &ndx, bswap);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * A CIE record has a id of '0'; otherwise
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * this is a FDE entry and the 'id' is the
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * CIE pointer.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (id == 0) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 char *cieaugstr;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint_t cieaugndx;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ciePflag = 0;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 cieRflag = 0;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * We need to drill through the CIE
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * to find the Rflag. It's the Rflag
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * which describes how the FDE code-pointers
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * are encoded.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * burn through version
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ndx++;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * augstr
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 cieaugstr = (char *)(&data[off + ndx]);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ndx += strlen(cieaugstr) + 1;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * calign & dalign
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (void) uleb_extract(&data[off], &ndx);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (void) sleb_extract(&data[off], &ndx);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * retreg
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ndx++;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * we walk through the augmentation
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * section now looking for the Rflag
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 for (cieaugndx = 0; cieaugstr[cieaugndx];
286822dd6ee35fa0959e7b55e659b92ea1c12f71 cieaugndx++) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* BEGIN CSTYLED */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 switch (cieaugstr[cieaugndx]) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 case 'z':
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* size */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (void) uleb_extract(&data[off],
286822dd6ee35fa0959e7b55e659b92ea1c12f71 &ndx);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 break;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 case 'P':
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* personality */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ciePflag = data[off + ndx];
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ndx++;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Just need to extract the
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * value to move on to the next
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * field.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (void) dwarf_ehe_extract(
286822dd6ee35fa0959e7b55e659b92ea1c12f71 &data[off + ndx],
286822dd6ee35fa0959e7b55e659b92ea1c12f71 &ndx, ciePflag,
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ofl->ofl_dehdr->e_ident,
286822dd6ee35fa0959e7b55e659b92ea1c12f71 shdr->sh_addr, off + ndx);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 break;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 case 'R':
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* code encoding */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 cieRflag = data[off + ndx];
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ndx++;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 break;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 case 'L':
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* lsda encoding */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 ndx++;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 break;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* END CSTYLED */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71 } else {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint_t bintabndx;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint64_t initloc;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint64_t fdeaddr;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 initloc = dwarf_ehe_extract(&data[off],
286822dd6ee35fa0959e7b55e659b92ea1c12f71 &ndx, cieRflag, ofl->ofl_dehdr->e_ident,
286822dd6ee35fa0959e7b55e659b92ea1c12f71 shdr->sh_addr, off + ndx);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Ignore FDEs with initloc set to 0.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * initloc will not be 0 unless this FDE was
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * abandoned due to GNU linkonce processing.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * The 0 value occurs because we don't resolve
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * sloppy relocations for unwind header target
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * sections.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (initloc != 0) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 bintabndx = fde_count * 2;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 fde_count++;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * FDEaddr is adjusted
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * to account for the length & id which
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * have already been consumed.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 fdeaddr = shdr->sh_addr + off;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 binarytable[bintabndx] =
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (uint_t)(initloc - hdraddr);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 binarytable[bintabndx + 1] =
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (uint_t)(fdeaddr - hdraddr);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * the length does not include the length
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * itself - so account for that too.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 off += length + 4;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71done:
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Do a quicksort on the binary table. If this is a cross
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * link from a system with the opposite byte order, xlate
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * the resulting values into LSB order.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 framehdr_addr = hdraddr;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 qsort((void *)binarytable, (size_t)fde_count,
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (size_t)(sizeof (uint_t) * 2), bintabcompare);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (bswap) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint_t *btable = binarytable;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint_t cnt;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 for (cnt = fde_count * 2; cnt-- > 0; btable++)
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *btable = ld_bswap_Word(*btable);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Fill in:
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * first_frame_ptr
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * fde_count
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 hdroff = 4;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* LINTED */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint_ptr = (uint_t *)(&hdrdata[hdroff]);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *uint_ptr = first_unwind->os_shdr->sh_addr -
286822dd6ee35fa0959e7b55e659b92ea1c12f71 (hdrosp->os_shdr->sh_addr + hdroff);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (bswap)
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *uint_ptr = ld_bswap_Word(*uint_ptr);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 hdroff += 4;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /* LINTED */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 uint_ptr = (uint_t *)&hdrdata[hdroff];
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *uint_ptr = fde_count;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (bswap)
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *uint_ptr = ld_bswap_Word(*uint_ptr);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * If relaxed relocations are active, then there is a chance
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * that we didn't use all the space reserved for this section.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * For details, see the note at head of ld_unwind_make_hdr() above.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Find the PT_SUNW_UNWIND program header, and change the size values
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * to the size of the subset of the section that was actually used.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (ofl->ofl_flags1 & FLG_OF1_RLXREL) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 Word phnum = ofl->ofl_nehdr->e_phnum;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 Phdr *phdr = ofl->ofl_phdr;
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 for (; phnum-- > 0; phdr++) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (phdr->p_type == PT_SUNW_UNWIND) {
286822dd6ee35fa0959e7b55e659b92ea1c12f71 phdr->p_memsz = 12 + (8 * fde_count);
286822dd6ee35fa0959e7b55e659b92ea1c12f71 phdr->p_filesz = phdr->p_memsz;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 break;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71 }
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 return (1);
286822dd6ee35fa0959e7b55e659b92ea1c12f71}
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71/*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Append an .eh_frame section to our output list if not already present.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 *
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Usually, there is a single .eh_frame output section. However, there can
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * be more if there are incompatible section flags on incoming sections.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * If this does happen, the frame_ptr field of the eh_frame_hdr section
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * will point at the base of the first output section, and the other
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * sections will not be accessible via frame_ptr. However, the .eh_frame_hdr
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * will be able to access all the data in the different .eh_frame sections,
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * because the entries in sorted table are all encoded as DW_EH_PE_datarel.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71uintptr_t
286822dd6ee35fa0959e7b55e659b92ea1c12f71ld_unwind_register(Os_desc *osp, Ofl_desc * ofl)
286822dd6ee35fa0959e7b55e659b92ea1c12f71{
286822dd6ee35fa0959e7b55e659b92ea1c12f71 Aliste idx;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 Os_desc *_osp;
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Check to see if this output section is already
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * on the list.
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 for (APLIST_TRAVERSE(ofl->ofl_unwind, idx, _osp))
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (osp == _osp)
286822dd6ee35fa0959e7b55e659b92ea1c12f71 return (1);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 /*
286822dd6ee35fa0959e7b55e659b92ea1c12f71 * Append output section to unwind list
286822dd6ee35fa0959e7b55e659b92ea1c12f71 */
286822dd6ee35fa0959e7b55e659b92ea1c12f71 if (aplist_append(&ofl->ofl_unwind, osp, AL_CNT_OFL_UNWIND) == NULL)
286822dd6ee35fa0959e7b55e659b92ea1c12f71 return (S_ERROR);
286822dd6ee35fa0959e7b55e659b92ea1c12f71
286822dd6ee35fa0959e7b55e659b92ea1c12f71 return (1);
286822dd6ee35fa0959e7b55e659b92ea1c12f71}
286822dd6ee35fa0959e7b55e659b92ea1c12f71