107dc194Richard Lowe/*
207dc194Richard Lowe  Copyright (C) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
34d9fdb4Robert Mustacchi  Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
44d9fdb4Robert Mustacchi  Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
54d9fdb4Robert Mustacchi
64d9fdb4Robert Mustacchi  This program is free software; you can redistribute it
74d9fdb4Robert Mustacchi  and/or modify it under the terms of version 2.1 of the
84d9fdb4Robert Mustacchi  GNU Lesser General Public License as published by the Free
94d9fdb4Robert Mustacchi  Software Foundation.
104d9fdb4Robert Mustacchi
114d9fdb4Robert Mustacchi  This program is distributed in the hope that it would be
124d9fdb4Robert Mustacchi  useful, but WITHOUT ANY WARRANTY; without even the implied
134d9fdb4Robert Mustacchi  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
144d9fdb4Robert Mustacchi  PURPOSE.
154d9fdb4Robert Mustacchi
164d9fdb4Robert Mustacchi  Further, this software is distributed without any warranty
174d9fdb4Robert Mustacchi  that it is free of the rightful claim of any third person
184d9fdb4Robert Mustacchi  regarding infringement or the like.  Any license provided
194d9fdb4Robert Mustacchi  herein, whether implied or otherwise, applies only to this
204d9fdb4Robert Mustacchi  software file.  Patent licenses, if any, provided herein
214d9fdb4Robert Mustacchi  do not apply to combinations of this program with other
224d9fdb4Robert Mustacchi  software, or any other product whatsoever.
234d9fdb4Robert Mustacchi
244d9fdb4Robert Mustacchi  You should have received a copy of the GNU Lesser General
254d9fdb4Robert Mustacchi  Public License along with this program; if not, write the
264d9fdb4Robert Mustacchi  Free Software Foundation, Inc., 51 Franklin Street - Fifth
274d9fdb4Robert Mustacchi  Floor, Boston MA 02110-1301, USA.
2807dc194Richard Lowe
294d9fdb4Robert Mustacchi*/
3007dc194Richard Lowe
314d9fdb4Robert Mustacchi/*  This  implements _dwarf_get_fde_list_internal()
324d9fdb4Robert Mustacchi    and related helper functions for reading cie/fde data.  */
3307dc194Richard Lowe
344d9fdb4Robert Mustacchi#include "config.h"
354d9fdb4Robert Mustacchi#include <stdio.h>
364d9fdb4Robert Mustacchi#ifdef HAVE_STDLIB_H
374d9fdb4Robert Mustacchi#include <stdlib.h>
384d9fdb4Robert Mustacchi#endif /* HAVE_STDLIB_H */
394d9fdb4Robert Mustacchi#include "dwarf_incl.h"
404d9fdb4Robert Mustacchi#include "dwarf_alloc.h"
414d9fdb4Robert Mustacchi#include "dwarf_error.h"
424d9fdb4Robert Mustacchi#include "dwarf_util.h"
434d9fdb4Robert Mustacchi#include "dwarf_frame.h"
444d9fdb4Robert Mustacchi#include "dwarf_arange.h" /* using Arange as a way to build a list */
454d9fdb4Robert Mustacchi#include "dwarfstring.h"
4607dc194Richard Lowe
474d9fdb4Robert Mustacchi/*  For a little information about .eh_frame see
484d9fdb4Robert Mustacchi    https://stackoverflow.com/questions/14091231/what-do-the-eh-frame-and-eh-frame-hdr-sections-store-exactly
494d9fdb4Robert Mustacchi    http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
504d9fdb4Robert Mustacchi    The above give information about fields and sizes but
514d9fdb4Robert Mustacchi    very very little about content.
5207dc194Richard Lowe
534d9fdb4Robert Mustacchi    .eh_frame_hdr contains data for C++ unwinding. Namely
544d9fdb4Robert Mustacchi    tables for fast access into .eh_frame.
5507dc194Richard Lowe*/
5607dc194Richard Lowe
5707dc194Richard Lowe
5807dc194Richard Lowe
594d9fdb4Robert Mustacchi#define TRUE 1
604d9fdb4Robert Mustacchi#define FALSE 0
6107dc194Richard Lowe
624d9fdb4Robert Mustacchi#if 0  /* FOR DEBUGGING */
634d9fdb4Robert Mustacchi/* For debugging only. */
644d9fdb4Robert Mustacchistatic void
654d9fdb4Robert Mustacchidump_bytes(const char *msg,Dwarf_Small * start, long len)
664d9fdb4Robert Mustacchi{
674d9fdb4Robert Mustacchi    Dwarf_Small *end = start + len;
684d9fdb4Robert Mustacchi    Dwarf_Small *cur = start;
694d9fdb4Robert Mustacchi    printf("%s (0x%lx) ",msg,(unsigned long)start);
704d9fdb4Robert Mustacchi    for (; cur < end; cur++) {
714d9fdb4Robert Mustacchi        printf("%02x", *cur);
724d9fdb4Robert Mustacchi    }
734d9fdb4Robert Mustacchi    printf("\n");
744d9fdb4Robert Mustacchi}
7507dc194Richard Lowe
764d9fdb4Robert Mustacchi#endif
7707dc194Richard Lowe
7807dc194Richard Lowestatic int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
794d9fdb4Robert Mustacchi    Dwarf_Cie cur_cie_ptr,
804d9fdb4Robert Mustacchi    Dwarf_Cie * cie_ptr_to_use_out,
814d9fdb4Robert Mustacchi    Dwarf_Cie head_cie_ptr);
8207dc194Richard Lowestatic void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
834d9fdb4Robert Mustacchi    Dwarf_Cie head_cie_ptr);
8407dc194Richard Lowestatic int dwarf_create_cie_from_start(Dwarf_Debug dbg,
854d9fdb4Robert Mustacchi    Dwarf_Small * cie_ptr_val,
864d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr,
874d9fdb4Robert Mustacchi    Dwarf_Unsigned section_index,
884d9fdb4Robert Mustacchi    Dwarf_Unsigned section_length,
894d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr_end,
904d9fdb4Robert Mustacchi    Dwarf_Unsigned cie_id_value,
914d9fdb4Robert Mustacchi    Dwarf_Unsigned cie_count,
924d9fdb4Robert Mustacchi    int use_gnu_cie_calc,
934d9fdb4Robert Mustacchi    Dwarf_Cie * cie_ptr_to_use_out,
944d9fdb4Robert Mustacchi    Dwarf_Error * error);
954d9fdb4Robert Mustacchi
9607dc194Richard Lowestatic int get_gcc_eh_augmentation(Dwarf_Debug dbg,
974d9fdb4Robert Mustacchi    Dwarf_Small * frame_ptr,
984d9fdb4Robert Mustacchi    unsigned long
994d9fdb4Robert Mustacchi    *size_of_augmentation_data,
1004d9fdb4Robert Mustacchi    enum Dwarf_augmentation_type augtype,
1014d9fdb4Robert Mustacchi    Dwarf_Small * section_end_pointer,
1024d9fdb4Robert Mustacchi    char *augmentation,
1034d9fdb4Robert Mustacchi    Dwarf_Error *error);
10407dc194Richard Lowe
10507dc194Richard Lowestatic int
1064d9fdb4Robert Mustacchignu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
1074d9fdb4Robert Mustacchi    Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
1084d9fdb4Robert Mustacchi    Dwarf_Half address_size,
1094d9fdb4Robert Mustacchi    unsigned char *pers_hand_enc_out,
1104d9fdb4Robert Mustacchi    unsigned char *lsda_enc_out,
1114d9fdb4Robert Mustacchi    unsigned char *fde_begin_enc_out,
1124d9fdb4Robert Mustacchi    Dwarf_Addr * gnu_pers_addr_out,
1134d9fdb4Robert Mustacchi    Dwarf_Error *error);
11407dc194Richard Lowe
11507dc194Richard Lowe
11607dc194Richard Lowestatic int read_encoded_ptr(Dwarf_Debug dbg,
1174d9fdb4Robert Mustacchi    Dwarf_Small * section_pointer,
1184d9fdb4Robert Mustacchi    Dwarf_Small * input_field,
1194d9fdb4Robert Mustacchi    int gnu_encoding,
1204d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr_end,
1214d9fdb4Robert Mustacchi    Dwarf_Half address_size,
1224d9fdb4Robert Mustacchi    Dwarf_Unsigned * addr,
1234d9fdb4Robert Mustacchi    Dwarf_Small ** input_field_out,
1244d9fdb4Robert Mustacchi    Dwarf_Error *error);
12507dc194Richard Lowe
12607dc194Richard Lowe
12707dc194Richard Lowe
1284d9fdb4Robert Mustacchi/*  Called by qsort to compare FDE entries.
1294d9fdb4Robert Mustacchi    Consumer code expects the array of FDE pointers to be
1304d9fdb4Robert Mustacchi    in address order.
1314d9fdb4Robert Mustacchi*/
1324d9fdb4Robert Mustacchistatic int
1334d9fdb4Robert Mustacchiqsort_compare(const void *elem1, const void *elem2)
1344d9fdb4Robert Mustacchi{
1354d9fdb4Robert Mustacchi    const Dwarf_Fde fde1 = *(const Dwarf_Fde *) elem1;
1364d9fdb4Robert Mustacchi    const Dwarf_Fde fde2 = *(const Dwarf_Fde *) elem2;
1374d9fdb4Robert Mustacchi    Dwarf_Addr addr1 = fde1->fd_initial_location;
1384d9fdb4Robert Mustacchi    Dwarf_Addr addr2 = fde2->fd_initial_location;
13907dc194Richard Lowe
1404d9fdb4Robert Mustacchi    if (addr1 < addr2) {
1414d9fdb4Robert Mustacchi        return -1;
1424d9fdb4Robert Mustacchi    } else if (addr1 > addr2) {
1434d9fdb4Robert Mustacchi        return 1;
1444d9fdb4Robert Mustacchi    }
1454d9fdb4Robert Mustacchi    return 0;
1464d9fdb4Robert Mustacchi}
14707dc194Richard Lowe
1484d9fdb4Robert Mustacchi/*  Adds 'newone' to the end of the list starting at 'head'
1494d9fdb4Robert Mustacchi    and makes the new one 'cur'rent. */
15007dc194Richard Lowestatic void
15107dc194Richard Lowechain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
15207dc194Richard Lowe{
15307dc194Richard Lowe    if (*head == NULL)
15407dc194Richard Lowe        *head = newone;
15507dc194Richard Lowe    else {
15607dc194Richard Lowe        (*cur)->fd_next = newone;
15707dc194Richard Lowe    }
15807dc194Richard Lowe    *cur = newone;
15907dc194Richard Lowe
16007dc194Richard Lowe}
16107dc194Richard Lowe
1624d9fdb4Robert Mustacchi/*  Adds 'newone' to the end of the list starting at 'head'
1634d9fdb4Robert Mustacchi    and makes the new one 'cur'rent. */
16407dc194Richard Lowestatic void
16507dc194Richard Lowechain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
16607dc194Richard Lowe{
16707dc194Richard Lowe    if (*head == NULL) {
16807dc194Richard Lowe        *head = newone;
16907dc194Richard Lowe    } else {
17007dc194Richard Lowe        (*cur)->ci_next = newone;
17107dc194Richard Lowe    }
17207dc194Richard Lowe    *cur = newone;
17307dc194Richard Lowe}
17407dc194Richard Lowe
1754d9fdb4Robert Mustacchi/*  The size of the length field plus the
1764d9fdb4Robert Mustacchi    value of length must be an integral
1774d9fdb4Robert Mustacchi    multiple of the address size.  Dwarf4 standard.
17807dc194Richard Lowe
1794d9fdb4Robert Mustacchi    A constant that gives the number of bytes of the CIE
1804d9fdb4Robert Mustacchi    structure, not including the length field itself
1814d9fdb4Robert Mustacchi    (where length mod <size of an address> == 0)
18207dc194Richard Lowe    (see Section 7.2.2). Dwarf3 standard.
1834d9fdb4Robert Mustacchi
1844d9fdb4Robert Mustacchi    A uword constant that gives the number of bytes of
18507dc194Richard Lowe    the CIE structure, not including the
18607dc194Richard Lowe    length field, itself (length mod <addressing unit size> == 0).
18707dc194Richard Lowe    Dwarf2 standard.*/
18807dc194Richard Lowestatic void
18907dc194Richard Lowevalidate_length(Dwarf_Debug dbg,
19007dc194Richard Lowe    Dwarf_Cie cieptr, Dwarf_Unsigned length,
19107dc194Richard Lowe    Dwarf_Unsigned length_size,
19207dc194Richard Lowe    Dwarf_Unsigned extension_size,
19307dc194Richard Lowe    Dwarf_Small * section_ptr,
19407dc194Richard Lowe    Dwarf_Small * ciefde_start,
19507dc194Richard Lowe    const char * cieorfde)
19607dc194Richard Lowe{
1974d9fdb4Robert Mustacchi    Dwarf_Unsigned address_size = 0;
19807dc194Richard Lowe    Dwarf_Unsigned length_field_summed = length_size + extension_size;
19907dc194Richard Lowe    Dwarf_Unsigned total_len = length + length_field_summed;
2004d9fdb4Robert Mustacchi    Dwarf_Unsigned mod = 0;
20107dc194Richard Lowe
2024d9fdb4Robert Mustacchi    if (cieptr) {
2034d9fdb4Robert Mustacchi        address_size = cieptr->ci_address_size;
2044d9fdb4Robert Mustacchi    } else {
2054d9fdb4Robert Mustacchi        address_size = dbg->de_pointer_size;
2064d9fdb4Robert Mustacchi    }
2074d9fdb4Robert Mustacchi    mod = total_len % address_size;
20807dc194Richard Lowe    if (mod != 0) {
2094d9fdb4Robert Mustacchi        dwarfstring  harm;
21007dc194Richard Lowe        Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
2114d9fdb4Robert Mustacchi
2124d9fdb4Robert Mustacchi        dwarfstring_constructor(&harm);
2134d9fdb4Robert Mustacchi        if (!cieorfde || (strlen(cieorfde) > 3)) {
2144d9fdb4Robert Mustacchi            /*  Coding error or memory corruption? */
2154d9fdb4Robert Mustacchi            cieorfde = "ERROR!";
2164d9fdb4Robert Mustacchi        }
2174d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
21807dc194Richard Lowe            "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
2194d9fdb4Robert Mustacchi            " len=0x%" DW_PR_XZEROS DW_PR_DUx,
2204d9fdb4Robert Mustacchi            length);
2214d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
2224d9fdb4Robert Mustacchi            ", len size=0x%"  DW_PR_XZEROS DW_PR_DUx,
2234d9fdb4Robert Mustacchi            length_size);
2244d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
2254d9fdb4Robert Mustacchi            ", extn size=0x%" DW_PR_XZEROS DW_PR_DUx,
2264d9fdb4Robert Mustacchi            extension_size);
2274d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
2284d9fdb4Robert Mustacchi            ", totl length=0x%" DW_PR_XZEROS DW_PR_DUx,
2294d9fdb4Robert Mustacchi            total_len);
2304d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
2314d9fdb4Robert Mustacchi            ", addr size=0x%" DW_PR_XZEROS DW_PR_DUx,
2324d9fdb4Robert Mustacchi            address_size);
2334d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
2344d9fdb4Robert Mustacchi            ", mod=0x%" DW_PR_XZEROS DW_PR_DUx " must be zero",
2354d9fdb4Robert Mustacchi            mod);
2364d9fdb4Robert Mustacchi        dwarfstring_append_printf_s(&harm,
2374d9fdb4Robert Mustacchi            " in %s",(char *)cieorfde);
2384d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&harm,
2394d9fdb4Robert Mustacchi            ", offset 0x%" DW_PR_XZEROS DW_PR_DUx ".",
24007dc194Richard Lowe            sectionoffset);
2414d9fdb4Robert Mustacchi        dwarf_insert_harmless_error(dbg,
2424d9fdb4Robert Mustacchi            dwarfstring_string(&harm));
2434d9fdb4Robert Mustacchi        dwarfstring_destructor(&harm);
24407dc194Richard Lowe    }
24507dc194Richard Lowe    return;
24607dc194Richard Lowe}
24707dc194Richard Lowe
24807dc194Richard Lowe
2494d9fdb4Robert Mustacchi#if 0 /* FOR DEBUGGING */
25007dc194Richard Lowe/* For debugging only. */
25107dc194Richard Lowestatic void
25207dc194Richard Loweprint_prefix(struct cie_fde_prefix_s *prefix, int line)
25307dc194Richard Lowe{
25407dc194Richard Lowe    printf("prefix-print, prefix at 0x%lx, line %d\n",
2554d9fdb4Robert Mustacchi        (unsigned long) prefix, line);
25607dc194Richard Lowe    printf("  start addr 0x%lx after prefix 0x%lx\n",
2574d9fdb4Robert Mustacchi        (unsigned long) prefix->cf_start_addr,
2584d9fdb4Robert Mustacchi        (unsigned long) prefix->cf_addr_after_prefix);
2594d9fdb4Robert Mustacchi    printf("  length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
2604d9fdb4Robert Mustacchi        (Dwarf_Unsigned) prefix->cf_length,
2614d9fdb4Robert Mustacchi        prefix->cf_local_length_size,
2624d9fdb4Robert Mustacchi        prefix->cf_local_extension_size);
26307dc194Richard Lowe    printf("  cie_id 0x%" DW_PR_DUx " cie_id  cie_id_addr 0x%lx\n",
2644d9fdb4Robert Mustacchi        (Dwarf_Unsigned) prefix->cf_cie_id,
2654d9fdb4Robert Mustacchi        (long) prefix->cf_cie_id_addr);
26607dc194Richard Lowe    printf
26707dc194Richard Lowe        ("  sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
2684d9fdb4Robert Mustacchi        (unsigned long) prefix->cf_section_ptr,
2694d9fdb4Robert Mustacchi        (Dwarf_Signed) prefix->cf_section_index,
2704d9fdb4Robert Mustacchi        (Dwarf_Unsigned) prefix->cf_section_length,
2714d9fdb4Robert Mustacchi        (unsigned long) prefix->cf_section_ptr +
2724d9fdb4Robert Mustacchi        (unsigned long)prefix->cf_section_length);
27307dc194Richard Lowe}
27407dc194Richard Lowe#endif
27507dc194Richard Lowe
2764d9fdb4Robert Mustacchi/*  Make the 'cieptr' consistent across .debug_frame and .eh_frame.
2774d9fdb4Robert Mustacchi    Calculate a pointer into section bytes given a cie_id in
2784d9fdb4Robert Mustacchi    an FDE header.
2794d9fdb4Robert Mustacchi
2804d9fdb4Robert Mustacchi    In .debug_frame, the CIE_pointer is an offset in .debug_frame.
2814d9fdb4Robert Mustacchi
2824d9fdb4Robert Mustacchi    In .eh_frame, the CIE Pointer is, when
2834d9fdb4Robert Mustacchi    cie_id_value subtracted from the
2844d9fdb4Robert Mustacchi    cie_id_addr, the address in memory of
2854d9fdb4Robert Mustacchi    a CIE length field.
2864d9fdb4Robert Mustacchi    Since cie_id_addr is the address of an FDE CIE_Pointer
2874d9fdb4Robert Mustacchi    field, cie_id_value for .eh_frame
2884d9fdb4Robert Mustacchi    has to account for the length-prefix.
2894d9fdb4Robert Mustacchi    so that the returned cieptr really points to
2904d9fdb4Robert Mustacchi    a  CIE length field. Whew!
2914d9fdb4Robert Mustacchi    Available documentation on this is just a bit
2924d9fdb4Robert Mustacchi    ambiguous, but this calculation is correct.
2934d9fdb4Robert Mustacchi*/
29407dc194Richard Lowe
2954d9fdb4Robert Mustacchistatic Dwarf_Small *
2964d9fdb4Robert Mustacchiget_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
2974d9fdb4Robert Mustacchi    int use_gnu_cie_calc,
2984d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr,
2994d9fdb4Robert Mustacchi    Dwarf_Small * cie_id_addr)
3004d9fdb4Robert Mustacchi{
3014d9fdb4Robert Mustacchi    Dwarf_Small *cieptr = 0;
30207dc194Richard Lowe
3034d9fdb4Robert Mustacchi    if (use_gnu_cie_calc) {
3044d9fdb4Robert Mustacchi        /*  cie_id value is offset, in section, of the cie_id itself, to
3054d9fdb4Robert Mustacchi            use vm ptr of the value, less the value, to get to the cie
3064d9fdb4Robert Mustacchi            header.  */
3074d9fdb4Robert Mustacchi        cieptr = cie_id_addr - cie_id_value;
3084d9fdb4Robert Mustacchi    } else {
3094d9fdb4Robert Mustacchi        /*  Traditional dwarf section offset is in cie_id */
3104d9fdb4Robert Mustacchi        cieptr = section_ptr + cie_id_value;
3114d9fdb4Robert Mustacchi    }
3124d9fdb4Robert Mustacchi    return cieptr;
3134d9fdb4Robert Mustacchi}
3144d9fdb4Robert Mustacchi
3154d9fdb4Robert Mustacchi
3164d9fdb4Robert Mustacchi
3174d9fdb4Robert Mustacchi/*  Internal function called from various places to create
3184d9fdb4Robert Mustacchi    lists of CIEs and FDEs.  Not directly called
3194d9fdb4Robert Mustacchi    by consumer code */
32007dc194Richard Loweint
32107dc194Richard Lowe_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
32207dc194Richard Lowe    Dwarf_Signed * cie_element_count,
32307dc194Richard Lowe    Dwarf_Fde ** fde_data,
32407dc194Richard Lowe    Dwarf_Signed * fde_element_count,
32507dc194Richard Lowe    Dwarf_Small * section_ptr,
32607dc194Richard Lowe    Dwarf_Unsigned section_index,
32707dc194Richard Lowe    Dwarf_Unsigned section_length,
32807dc194Richard Lowe    Dwarf_Unsigned cie_id_value,
32907dc194Richard Lowe    int use_gnu_cie_calc, Dwarf_Error * error)
33007dc194Richard Lowe{
33107dc194Richard Lowe    /* Scans the debug_frame section. */
33207dc194Richard Lowe    Dwarf_Small *frame_ptr = section_ptr;
3334d9fdb4Robert Mustacchi    Dwarf_Small *section_ptr_end = section_ptr + section_length;
33407dc194Richard Lowe
33507dc194Richard Lowe
33607dc194Richard Lowe
3374d9fdb4Robert Mustacchi    /*  New_cie points to the Cie being read, and head_cie_ptr and
3384d9fdb4Robert Mustacchi        cur_cie_ptr are used for chaining them up in sequence.
3394d9fdb4Robert Mustacchi        In case cie's are reused aggressively we need tail_cie_ptr
3404d9fdb4Robert Mustacchi        to add to the chain.  If we re-use an early cie
3414d9fdb4Robert Mustacchi        later on, that does not mean we chain a new cie to the early one,
3424d9fdb4Robert Mustacchi        we always chain it to the tail.  */
34307dc194Richard Lowe    Dwarf_Cie head_cie_ptr = NULL;
34407dc194Richard Lowe    Dwarf_Cie cur_cie_ptr = NULL;
34507dc194Richard Lowe    Dwarf_Cie tail_cie_ptr = NULL;
3464d9fdb4Robert Mustacchi    Dwarf_Unsigned cie_count = 0;
34707dc194Richard Lowe
3484d9fdb4Robert Mustacchi    /*  Points to a list of contiguous pointers to Dwarf_Cie structures.
3494d9fdb4Robert Mustacchi    */
35007dc194Richard Lowe    Dwarf_Cie *cie_list_ptr = 0;
35107dc194Richard Lowe
35207dc194Richard Lowe
3534d9fdb4Robert Mustacchi    /*  New_fde points to the Fde being created, and head_fde_ptr and
3544d9fdb4Robert Mustacchi        cur_fde_ptr are used to chain them up. */
35507dc194Richard Lowe    Dwarf_Fde head_fde_ptr = NULL;
35607dc194Richard Lowe    Dwarf_Fde cur_fde_ptr = NULL;
3574d9fdb4Robert Mustacchi    Dwarf_Unsigned fde_count = 0;
35807dc194Richard Lowe
3594d9fdb4Robert Mustacchi    /*  Points to a list of contiguous pointers to Dwarf_Fde structures.
3604d9fdb4Robert Mustacchi    */
36107dc194Richard Lowe    Dwarf_Fde *fde_list_ptr = NULL;
36207dc194Richard Lowe
3634d9fdb4Robert Mustacchi    Dwarf_Unsigned i = 0;
36407dc194Richard Lowe    int res = DW_DLV_ERROR;
36507dc194Richard Lowe
36607dc194Richard Lowe    if (frame_ptr == 0) {
36707dc194Richard Lowe        return DW_DLV_NO_ENTRY;
36807dc194Richard Lowe    }
36907dc194Richard Lowe
3704d9fdb4Robert Mustacchi    /*  We create the fde and cie arrays. Processing each CIE as we come
3714d9fdb4Robert Mustacchi        to it or as an FDE refers to it.  We cannot process 'late' CIEs
3724d9fdb4Robert Mustacchi        late as GNU .eh_frame complexities mean we need the whole CIE
3734d9fdb4Robert Mustacchi        before we can process the FDE correctly. */
3744d9fdb4Robert Mustacchi    while (frame_ptr < section_ptr_end) {
37507dc194Richard Lowe
37607dc194Richard Lowe        struct cie_fde_prefix_s prefix;
37707dc194Richard Lowe
3784d9fdb4Robert Mustacchi        /*  First read in the 'common prefix' to figure out what we are
3794d9fdb4Robert Mustacchi            to do with this entry. */
38007dc194Richard Lowe        memset(&prefix, 0, sizeof(prefix));
38107dc194Richard Lowe        res = dwarf_read_cie_fde_prefix(dbg,
3824d9fdb4Robert Mustacchi            frame_ptr, section_ptr,
3834d9fdb4Robert Mustacchi            section_index,
3844d9fdb4Robert Mustacchi            section_length, &prefix, error);
38507dc194Richard Lowe        if (res == DW_DLV_ERROR) {
3864d9fdb4Robert Mustacchi            dealloc_fde_cie_list_internal(head_fde_ptr,
3874d9fdb4Robert Mustacchi                head_cie_ptr);
38807dc194Richard Lowe            return res;
38907dc194Richard Lowe        }
3904d9fdb4Robert Mustacchi        if (res == DW_DLV_NO_ENTRY) {
39107dc194Richard Lowe            break;
3924d9fdb4Robert Mustacchi        }
39307dc194Richard Lowe        frame_ptr = prefix.cf_addr_after_prefix;
3944d9fdb4Robert Mustacchi        if (frame_ptr >= section_ptr_end) {
39507dc194Richard Lowe            dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
39607dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
39707dc194Richard Lowe            return DW_DLV_ERROR;
39807dc194Richard Lowe        }
39907dc194Richard Lowe
40007dc194Richard Lowe        if (prefix.cf_cie_id == cie_id_value) {
40107dc194Richard Lowe            /* This is a CIE.  */
40207dc194Richard Lowe            Dwarf_Cie cie_ptr_to_use = 0;
4034d9fdb4Robert Mustacchi            int resc = 0;
40407dc194Richard Lowe
4054d9fdb4Robert Mustacchi            resc = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
4064d9fdb4Robert Mustacchi                cur_cie_ptr,
4074d9fdb4Robert Mustacchi                &cie_ptr_to_use,
4084d9fdb4Robert Mustacchi                head_cie_ptr);
4094d9fdb4Robert Mustacchi            if (resc == DW_DLV_OK) {
41007dc194Richard Lowe                cur_cie_ptr = cie_ptr_to_use;
41107dc194Richard Lowe                /* Ok. Seen already. */
4124d9fdb4Robert Mustacchi            } else if (resc == DW_DLV_NO_ENTRY) {
41307dc194Richard Lowe                /* CIE before its FDE in this case. */
4144d9fdb4Robert Mustacchi                resc = dwarf_create_cie_from_after_start(dbg,
4154d9fdb4Robert Mustacchi                    &prefix,
4164d9fdb4Robert Mustacchi                    section_ptr,
4174d9fdb4Robert Mustacchi                    frame_ptr,
4184d9fdb4Robert Mustacchi                    section_ptr_end,
4194d9fdb4Robert Mustacchi                    cie_count,
4204d9fdb4Robert Mustacchi                    use_gnu_cie_calc,
4214d9fdb4Robert Mustacchi                    &cie_ptr_to_use,
4224d9fdb4Robert Mustacchi                    error);
4234d9fdb4Robert Mustacchi                if (resc != DW_DLV_OK) {
42407dc194Richard Lowe                    dealloc_fde_cie_list_internal(head_fde_ptr,
4254d9fdb4Robert Mustacchi                        head_cie_ptr);
4264d9fdb4Robert Mustacchi                    return resc;
42707dc194Richard Lowe                }
42807dc194Richard Lowe                cie_count++;
42907dc194Richard Lowe                chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
4304d9fdb4Robert Mustacchi                    &tail_cie_ptr);
43107dc194Richard Lowe                cur_cie_ptr = tail_cie_ptr;
43207dc194Richard Lowe            } else {            /* res == DW_DLV_ERROR */
43307dc194Richard Lowe
43407dc194Richard Lowe                dealloc_fde_cie_list_internal(head_fde_ptr,
4354d9fdb4Robert Mustacchi                    head_cie_ptr);
4364d9fdb4Robert Mustacchi                return resc;
43707dc194Richard Lowe            }
43807dc194Richard Lowe            frame_ptr = cie_ptr_to_use->ci_cie_start +
43907dc194Richard Lowe                cie_ptr_to_use->ci_length +
44007dc194Richard Lowe                cie_ptr_to_use->ci_length_size +
44107dc194Richard Lowe                cie_ptr_to_use->ci_extension_size;
44207dc194Richard Lowe            continue;
44307dc194Richard Lowe        } else {
4444d9fdb4Robert Mustacchi            /*  This is an FDE, Frame Description Entry, see the Dwarf
4454d9fdb4Robert Mustacchi                Spec, (section 6.4.1 in DWARF2, DWARF3, DWARF4, ...)
4464d9fdb4Robert Mustacchi                Or see the .eh_frame specification,
4474d9fdb4Robert Mustacchi                from the Linux Foundation (or other source).  */
4484d9fdb4Robert Mustacchi            int resf = DW_DLV_ERROR;
44907dc194Richard Lowe            Dwarf_Cie cie_ptr_to_use = 0;
45007dc194Richard Lowe            Dwarf_Fde fde_ptr_to_use = 0;
4514d9fdb4Robert Mustacchi            Dwarf_Small *cieptr_val = 0;
4524d9fdb4Robert Mustacchi
4534d9fdb4Robert Mustacchi            cieptr_val = get_cieptr_given_offset(prefix.cf_cie_id,
4544d9fdb4Robert Mustacchi                use_gnu_cie_calc,
4554d9fdb4Robert Mustacchi                section_ptr,
4564d9fdb4Robert Mustacchi                prefix.cf_cie_id_addr);
4574d9fdb4Robert Mustacchi            resf = dwarf_find_existing_cie_ptr(cieptr_val,
4584d9fdb4Robert Mustacchi                cur_cie_ptr,
4594d9fdb4Robert Mustacchi                &cie_ptr_to_use,
4604d9fdb4Robert Mustacchi                head_cie_ptr);
4614d9fdb4Robert Mustacchi            if (resf == DW_DLV_OK) {
46207dc194Richard Lowe                cur_cie_ptr = cie_ptr_to_use;
46307dc194Richard Lowe                /* Ok. Seen CIE already. */
4644d9fdb4Robert Mustacchi            } else if (resf == DW_DLV_NO_ENTRY) {
4654d9fdb4Robert Mustacchi                resf = dwarf_create_cie_from_start(dbg,
4664d9fdb4Robert Mustacchi                    cieptr_val,
4674d9fdb4Robert Mustacchi                    section_ptr,
4684d9fdb4Robert Mustacchi                    section_index,
4694d9fdb4Robert Mustacchi                    section_length,
4704d9fdb4Robert Mustacchi                    section_ptr_end,
4714d9fdb4Robert Mustacchi                    cie_id_value,
4724d9fdb4Robert Mustacchi                    cie_count,
4734d9fdb4Robert Mustacchi                    use_gnu_cie_calc,
4744d9fdb4Robert Mustacchi                    &cie_ptr_to_use,
4754d9fdb4Robert Mustacchi                    error);
4764d9fdb4Robert Mustacchi                if (resf == DW_DLV_ERROR) {
47707dc194Richard Lowe                    dealloc_fde_cie_list_internal(head_fde_ptr,
4784d9fdb4Robert Mustacchi                        head_cie_ptr);
4794d9fdb4Robert Mustacchi                    return resf;
4804d9fdb4Robert Mustacchi                } else if (resf == DW_DLV_NO_ENTRY) {
4814d9fdb4Robert Mustacchi                    return resf;
48207dc194Richard Lowe                }
48307dc194Richard Lowe                ++cie_count;
48407dc194Richard Lowe                chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
4854d9fdb4Robert Mustacchi                    &tail_cie_ptr);
48607dc194Richard Lowe                cur_cie_ptr = tail_cie_ptr;
48707dc194Richard Lowe
48807dc194Richard Lowe            } else {
48907dc194Richard Lowe                /* DW_DLV_ERROR */
4904d9fdb4Robert Mustacchi                return resf;
49107dc194Richard Lowe            }
49207dc194Richard Lowe
4934d9fdb4Robert Mustacchi            resf = dwarf_create_fde_from_after_start(dbg,
4944d9fdb4Robert Mustacchi                &prefix,
4954d9fdb4Robert Mustacchi                section_ptr,
4964d9fdb4Robert Mustacchi                frame_ptr,
4974d9fdb4Robert Mustacchi                section_ptr_end,
4984d9fdb4Robert Mustacchi                use_gnu_cie_calc,
4994d9fdb4Robert Mustacchi                cie_ptr_to_use,
5004d9fdb4Robert Mustacchi                &fde_ptr_to_use,
5014d9fdb4Robert Mustacchi                error);
5024d9fdb4Robert Mustacchi            if (resf == DW_DLV_ERROR) {
5034d9fdb4Robert Mustacchi                dealloc_fde_cie_list_internal(head_fde_ptr,
5044d9fdb4Robert Mustacchi                    head_cie_ptr);
5054d9fdb4Robert Mustacchi                return resf;
5064d9fdb4Robert Mustacchi            } else if (resf == DW_DLV_NO_ENTRY) {
5074d9fdb4Robert Mustacchi                /* impossible. */
5084d9fdb4Robert Mustacchi                return resf;
50907dc194Richard Lowe            }
51007dc194Richard Lowe            chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
51107dc194Richard Lowe            fde_count++;
51207dc194Richard Lowe            /* ASSERT: DW_DLV_OK. */
5134d9fdb4Robert Mustacchi            frame_ptr = cur_fde_ptr->fd_fde_start +
5144d9fdb4Robert Mustacchi                cur_fde_ptr->fd_length +
5154d9fdb4Robert Mustacchi                cur_fde_ptr->fd_length_size +
5164d9fdb4Robert Mustacchi                cur_fde_ptr->fd_extension_size;
5174d9fdb4Robert Mustacchi            if (frame_ptr  <  fde_ptr_to_use->fd_fde_instr_start) {
5184d9fdb4Robert Mustacchi                /*  Sanity check. With a really short fde instruction
5194d9fdb4Robert Mustacchi                    set and address_size we think is 8
5204d9fdb4Robert Mustacchi                    as it is ELF64 (but is
5214d9fdb4Robert Mustacchi                    really 4, as in DWARF{2,3} where we have
5224d9fdb4Robert Mustacchi                    no FDE address_size) we emit an error.
5234d9fdb4Robert Mustacchi                    This error means things will not go well. */
5244d9fdb4Robert Mustacchi                dealloc_fde_cie_list_internal(head_fde_ptr,
5254d9fdb4Robert Mustacchi                    head_cie_ptr);
5264d9fdb4Robert Mustacchi                _dwarf_error(dbg,error,
5274d9fdb4Robert Mustacchi                    DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH);
5284d9fdb4Robert Mustacchi                return DW_DLV_ERROR;
5294d9fdb4Robert Mustacchi            }
53007dc194Richard Lowe            continue;
53107dc194Richard Lowe        }
53207dc194Richard Lowe    }
5334d9fdb4Robert Mustacchi    /*  Now build list of CIEs from the list. If there are no CIEs
5344d9fdb4Robert Mustacchi        there should be no FDEs. */
53507dc194Richard Lowe    if (cie_count > 0) {
53607dc194Richard Lowe        cie_list_ptr = (Dwarf_Cie *)
53707dc194Richard Lowe            _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
53807dc194Richard Lowe    } else {
5394d9fdb4Robert Mustacchi        if (fde_count > 0) {
54007dc194Richard Lowe            dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
54107dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
54207dc194Richard Lowe            return DW_DLV_ERROR;
54307dc194Richard Lowe        }
54407dc194Richard Lowe        dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
54507dc194Richard Lowe        return DW_DLV_NO_ENTRY;
54607dc194Richard Lowe    }
54707dc194Richard Lowe    if (cie_list_ptr == NULL) {
54807dc194Richard Lowe        dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
54907dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
55007dc194Richard Lowe        return DW_DLV_ERROR;
55107dc194Richard Lowe    }
5524d9fdb4Robert Mustacchi    if (!head_cie_ptr) {
5534d9fdb4Robert Mustacchi        /*  Should be impossible. */
5544d9fdb4Robert Mustacchi        _dwarf_error(dbg, error,DW_DLE_DEBUGFRAME_ERROR);
5554d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
5564d9fdb4Robert Mustacchi    }
55707dc194Richard Lowe    cur_cie_ptr = head_cie_ptr;
55807dc194Richard Lowe    for (i = 0; i < cie_count; i++) {
55907dc194Richard Lowe        *(cie_list_ptr + i) = cur_cie_ptr;
56007dc194Richard Lowe        cur_cie_ptr = cur_cie_ptr->ci_next;
56107dc194Richard Lowe    }
56207dc194Richard Lowe
5634d9fdb4Robert Mustacchi    /*  Now build array of FDEs from the list.
5644d9fdb4Robert Mustacchi        With orphan CIEs (meaning no FDEs)
5654d9fdb4Robert Mustacchi        lets not return DW_DLV_NO_ENTRY */
56607dc194Richard Lowe    if (fde_count > 0) {
56707dc194Richard Lowe        fde_list_ptr = (Dwarf_Fde *)
56807dc194Richard Lowe            _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
56907dc194Richard Lowe    }
57007dc194Richard Lowe
57107dc194Richard Lowe    /* It is ok if fde_list_ptr is NULL, we just have no fdes. */
57207dc194Richard Lowe    cur_fde_ptr = head_fde_ptr;
57307dc194Richard Lowe    for (i = 0; i < fde_count; i++) {
57407dc194Richard Lowe        *(fde_list_ptr + i) = cur_fde_ptr;
57507dc194Richard Lowe        cur_fde_ptr = cur_fde_ptr->fd_next;
57607dc194Richard Lowe    }
57707dc194Richard Lowe
57807dc194Richard Lowe
57907dc194Richard Lowe    /* Return arguments. */
58007dc194Richard Lowe    *cie_data = cie_list_ptr;
58107dc194Richard Lowe    *cie_element_count = cie_count;
58207dc194Richard Lowe
58307dc194Richard Lowe    *fde_data = fde_list_ptr;
58407dc194Richard Lowe    *fde_element_count = fde_count;
5854d9fdb4Robert Mustacchi    if (use_gnu_cie_calc) {
5864d9fdb4Robert Mustacchi        dbg->de_fde_data_eh = fde_list_ptr;
5874d9fdb4Robert Mustacchi        dbg->de_fde_count_eh = fde_count;
5884d9fdb4Robert Mustacchi        dbg->de_cie_data_eh = cie_list_ptr;
5894d9fdb4Robert Mustacchi        dbg->de_cie_count_eh = cie_count;
59007dc194Richard Lowe    } else {
5914d9fdb4Robert Mustacchi        dbg->de_fde_data = fde_list_ptr;
5924d9fdb4Robert Mustacchi        dbg->de_fde_count = fde_count;
5934d9fdb4Robert Mustacchi        dbg->de_cie_data = cie_list_ptr;
5944d9fdb4Robert Mustacchi        dbg->de_cie_count = cie_count;
59507dc194Richard Lowe    }
59607dc194Richard Lowe
5974d9fdb4Robert Mustacchi    /*  Sort the list by the address so that dwarf_get_fde_at_pc() can
5984d9fdb4Robert Mustacchi        binary search this list.  */
5994d9fdb4Robert Mustacchi    if (fde_count > 0) {
60007dc194Richard Lowe        qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
6014d9fdb4Robert Mustacchi            qsort_compare);
60207dc194Richard Lowe    }
60307dc194Richard Lowe
60407dc194Richard Lowe    return (DW_DLV_OK);
60507dc194Richard Lowe}
60607dc194Richard Lowe
6074d9fdb4Robert Mustacchi/*  Internal function, not called by consumer code.
6084d9fdb4Robert Mustacchi    'prefix' has accumulated the info up thru the cie-id
6094d9fdb4Robert Mustacchi    and now we consume the rest and build a Dwarf_Cie_s structure.
61007dc194Richard Lowe*/
61107dc194Richard Loweint
61207dc194Richard Lowedwarf_create_cie_from_after_start(Dwarf_Debug dbg,
61307dc194Richard Lowe    struct cie_fde_prefix_s *prefix,
61407dc194Richard Lowe    Dwarf_Small * section_pointer,
61507dc194Richard Lowe    Dwarf_Small * frame_ptr,
6164d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr_end,
61707dc194Richard Lowe    Dwarf_Unsigned cie_count,
61807dc194Richard Lowe    int use_gnu_cie_calc,
61907dc194Richard Lowe    Dwarf_Cie * cie_ptr_out,
62007dc194Richard Lowe    Dwarf_Error * error)
62107dc194Richard Lowe{
62207dc194Richard Lowe    Dwarf_Cie new_cie = 0;
62307dc194Richard Lowe
6244d9fdb4Robert Mustacchi    /*  egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
6254d9fdb4Robert Mustacchi        -1 (in .debug_frame). .eh_frame not quite identical to
6264d9fdb4Robert Mustacchi        .debug_frame */
6274d9fdb4Robert Mustacchi    /*  We here default the address size as it is not present
6284d9fdb4Robert Mustacchi        in DWARF2 or DWARF3 cie data, below we set it right if
6294d9fdb4Robert Mustacchi        it is present. */
63007dc194Richard Lowe    Dwarf_Half address_size = dbg->de_pointer_size;
63107dc194Richard Lowe    Dwarf_Small *augmentation = 0;
63207dc194Richard Lowe    Dwarf_Half segment_size = 0;
6334d9fdb4Robert Mustacchi    Dwarf_Signed data_alignment_factor = -1;
6344d9fdb4Robert Mustacchi    Dwarf_Unsigned code_alignment_factor = 4;
63507dc194Richard Lowe    Dwarf_Unsigned return_address_register = 31;
63607dc194Richard Lowe    int local_length_size = 0;
6374d9fdb4Robert Mustacchi    Dwarf_Unsigned leb128_length = 0;
63807dc194Richard Lowe    Dwarf_Unsigned cie_aug_data_len = 0;
63907dc194Richard Lowe    Dwarf_Small *cie_aug_data = 0;
64007dc194Richard Lowe    Dwarf_Addr gnu_personality_handler_addr = 0;
64107dc194Richard Lowe    unsigned char gnu_personality_handler_encoding = 0;
64207dc194Richard Lowe    unsigned char gnu_lsda_encoding = 0;
64307dc194Richard Lowe    unsigned char gnu_fde_begin_encoding = 0;
6444d9fdb4Robert Mustacchi    int res = 0;
6454d9fdb4Robert Mustacchi    Dwarf_Small version = 0;
64607dc194Richard Lowe
64707dc194Richard Lowe
64807dc194Richard Lowe    enum Dwarf_augmentation_type augt = aug_unknown;
64907dc194Richard Lowe
6504d9fdb4Robert Mustacchi    /*  This is a CIE, Common Information Entry: See the dwarf spec,
6514d9fdb4Robert Mustacchi        section 6.4.1 */
6524d9fdb4Robert Mustacchi    if (frame_ptr >= section_ptr_end) {
6534d9fdb4Robert Mustacchi        _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
6544d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
6554d9fdb4Robert Mustacchi    }
6564d9fdb4Robert Mustacchi    version = *(Dwarf_Small *) frame_ptr;
65707dc194Richard Lowe
6584d9fdb4Robert Mustacchi    if ((frame_ptr+2) >= section_ptr_end) {
6594d9fdb4Robert Mustacchi        _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
6604d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
6614d9fdb4Robert Mustacchi    }
66207dc194Richard Lowe
66307dc194Richard Lowe    frame_ptr++;
66407dc194Richard Lowe    if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
6654d9fdb4Robert Mustacchi        version != DW_CIE_VERSION4 && version != DW_CIE_VERSION5) {
66607dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
66707dc194Richard Lowe        return (DW_DLV_ERROR);
66807dc194Richard Lowe    }
66907dc194Richard Lowe
67007dc194Richard Lowe    augmentation = frame_ptr;
6714d9fdb4Robert Mustacchi
6724d9fdb4Robert Mustacchi    res = _dwarf_check_string_valid(dbg,section_pointer,
6734d9fdb4Robert Mustacchi        frame_ptr,section_ptr_end,
6744d9fdb4Robert Mustacchi        DW_DLE_AUGMENTATION_STRING_OFF_END,error);
6754d9fdb4Robert Mustacchi    if (res != DW_DLV_OK) {
6764d9fdb4Robert Mustacchi        return res;
6774d9fdb4Robert Mustacchi    }
67807dc194Richard Lowe    frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
6794d9fdb4Robert Mustacchi    if (frame_ptr  >= section_ptr_end) {
6804d9fdb4Robert Mustacchi        _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
6814d9fdb4Robert Mustacchi            "DW_DLE_DEBUG_FRAME_LENGTH_BAD: following any "
6824d9fdb4Robert Mustacchi            "augmentation field we have run off the end of the section "
6834d9fdb4Robert Mustacchi            "with the CIE incomplete.  Corrupt Dwarf");
6844d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
6854d9fdb4Robert Mustacchi    }
68607dc194Richard Lowe    augt = _dwarf_get_augmentation_type(dbg,
6874d9fdb4Robert Mustacchi        augmentation, use_gnu_cie_calc);
68807dc194Richard Lowe    if (augt == aug_eh) {
68907dc194Richard Lowe        /* REFERENCED *//* Not used in this instance */
6904d9fdb4Robert Mustacchi        UNUSEDARG Dwarf_Unsigned exception_table_addr;
69107dc194Richard Lowe
6924d9fdb4Robert Mustacchi        if ((frame_ptr+local_length_size)  >= section_ptr_end) {
6934d9fdb4Robert Mustacchi            _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
6944d9fdb4Robert Mustacchi                "DW_DLE_DEBUG_FRAME_LENGTH_BAD: following "
6954d9fdb4Robert Mustacchi                "type field we have run off the end of the section "
6964d9fdb4Robert Mustacchi                "with the CIE incomplete.  Corrupt Dwarf");
6974d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
6984d9fdb4Robert Mustacchi        }
69907dc194Richard Lowe        /* this is per egcs-1.1.2 as on RH 6.0 */
7004d9fdb4Robert Mustacchi        READ_UNALIGNED_CK(dbg, exception_table_addr,
7014d9fdb4Robert Mustacchi            Dwarf_Unsigned, frame_ptr, local_length_size,
7024d9fdb4Robert Mustacchi            error,section_ptr_end);
70307dc194Richard Lowe        frame_ptr += local_length_size;
70407dc194Richard Lowe    }
70507dc194Richard Lowe    {
70607dc194Richard Lowe        Dwarf_Unsigned lreg = 0;
70707dc194Richard Lowe        unsigned long size = 0;
70807dc194Richard Lowe
7094d9fdb4Robert Mustacchi        if (version == DW_CIE_VERSION4) {
7104d9fdb4Robert Mustacchi            if ((frame_ptr+2)  >= section_ptr_end) {
7114d9fdb4Robert Mustacchi                _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
7124d9fdb4Robert Mustacchi                    "DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
7134d9fdb4Robert Mustacchi                    "We would run off the end of the section "
7144d9fdb4Robert Mustacchi                    "in a DWARF4 cie header.  Corrupt Dwarf");
7154d9fdb4Robert Mustacchi                return DW_DLV_ERROR;
7164d9fdb4Robert Mustacchi            }
71707dc194Richard Lowe            address_size = *((unsigned char *)frame_ptr);
7184d9fdb4Robert Mustacchi            if (address_size  <  1) {
7194d9fdb4Robert Mustacchi                _dwarf_error_string(dbg, error, DW_DLE_ADDRESS_SIZE_ZERO,
7204d9fdb4Robert Mustacchi                    "DW_DLE_ADDRESS_SIZE_ZERO: bad addres size "
7214d9fdb4Robert Mustacchi                    "for a DWARF4 cie header");
7224d9fdb4Robert Mustacchi                return (DW_DLV_ERROR);
7234d9fdb4Robert Mustacchi            }
7244d9fdb4Robert Mustacchi            if (address_size  > sizeof(Dwarf_Addr)) {
7254d9fdb4Robert Mustacchi                _dwarf_create_address_size_dwarf_error(dbg,
7264d9fdb4Robert Mustacchi                    error,address_size,
7274d9fdb4Robert Mustacchi                    DW_DLE_ADDRESS_SIZE_ERROR,
7284d9fdb4Robert Mustacchi                    "DW_DLE_ADDRESS_SIZE_ERROR..:");
7294d9fdb4Robert Mustacchi                return DW_DLV_ERROR;
7304d9fdb4Robert Mustacchi            }
7314d9fdb4Robert Mustacchi            if ((frame_ptr+2)  >= section_ptr_end) {
7324d9fdb4Robert Mustacchi                _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
7334d9fdb4Robert Mustacchi                    "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
7344d9fdb4Robert Mustacchi                    " of a CIE header. Corrupt DWARF4");
7354d9fdb4Robert Mustacchi                return DW_DLV_ERROR;
7364d9fdb4Robert Mustacchi            }
73707dc194Richard Lowe            ++frame_ptr;
73807dc194Richard Lowe            segment_size = *((unsigned char *)frame_ptr);
73907dc194Richard Lowe            ++frame_ptr;
7404d9fdb4Robert Mustacchi            if (segment_size  > sizeof(Dwarf_Addr)) {
7414d9fdb4Robert Mustacchi                _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
7424d9fdb4Robert Mustacchi                return (DW_DLV_ERROR);
7434d9fdb4Robert Mustacchi            }
74407dc194Richard Lowe        }
74507dc194Richard Lowe
7464d9fdb4Robert Mustacchi        /* Not a great test. But the DECODE* do checking so ok.  */
7474d9fdb4Robert Mustacchi        if ((frame_ptr+2)  >= section_ptr_end) {
7484d9fdb4Robert Mustacchi            _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
7494d9fdb4Robert Mustacchi                "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
7504d9fdb4Robert Mustacchi                " of a CIE header before the code alignment value "
7514d9fdb4Robert Mustacchi                "read. Corrupt DWARF");
7524d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
7534d9fdb4Robert Mustacchi        }
7544d9fdb4Robert Mustacchi        DECODE_LEB128_UWORD_CK(frame_ptr, lreg,dbg,error,section_ptr_end);
7554d9fdb4Robert Mustacchi        code_alignment_factor = (Dwarf_Unsigned) lreg;
7564d9fdb4Robert Mustacchi        res = (Dwarf_Signed) _dwarf_decode_s_leb128_chk(frame_ptr,
7574d9fdb4Robert Mustacchi            &leb128_length,&data_alignment_factor,section_ptr_end);
7584d9fdb4Robert Mustacchi        if(res != DW_DLV_OK) {
7594d9fdb4Robert Mustacchi            return res;
7604d9fdb4Robert Mustacchi        }
76107dc194Richard Lowe        frame_ptr = frame_ptr + leb128_length;
7624d9fdb4Robert Mustacchi        /* Not a great test. FIXME */
7634d9fdb4Robert Mustacchi        if ((frame_ptr+1)  >= section_ptr_end) {
7644d9fdb4Robert Mustacchi            _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
7654d9fdb4Robert Mustacchi                "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
7664d9fdb4Robert Mustacchi                "of a CIE header before the return address register "
7674d9fdb4Robert Mustacchi                "number read. Corrupt DWARF");
76807dc194Richard Lowe
7694d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
7704d9fdb4Robert Mustacchi        }
7714d9fdb4Robert Mustacchi        res = _dwarf_get_return_address_reg(frame_ptr, version,
7724d9fdb4Robert Mustacchi            dbg,section_ptr_end, &size,&return_address_register,error);
7734d9fdb4Robert Mustacchi        if(res != DW_DLV_OK) {
7744d9fdb4Robert Mustacchi            return res;
7754d9fdb4Robert Mustacchi        }
77607dc194Richard Lowe        if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
77707dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
77807dc194Richard Lowe            return (DW_DLV_ERROR);
77907dc194Richard Lowe        }
78007dc194Richard Lowe        frame_ptr += size;
7814d9fdb4Robert Mustacchi        if ((frame_ptr)  > section_ptr_end) {
7824d9fdb4Robert Mustacchi            _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
7834d9fdb4Robert Mustacchi                "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Past the end "
7844d9fdb4Robert Mustacchi                "of a CIE header before reading the augmentation string."
7854d9fdb4Robert Mustacchi                " Corrupt DWARF");
7864d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
7874d9fdb4Robert Mustacchi        }
78807dc194Richard Lowe    }
78907dc194Richard Lowe    switch (augt) {
79007dc194Richard Lowe    case aug_empty_string:
79107dc194Richard Lowe        break;
79207dc194Richard Lowe    case aug_irix_mti_v1:
79307dc194Richard Lowe        break;
79407dc194Richard Lowe    case aug_irix_exception_table:{
7954d9fdb4Robert Mustacchi        Dwarf_Unsigned lreg = 0;
7964d9fdb4Robert Mustacchi        Dwarf_Unsigned length_of_augmented_fields;
79707dc194Richard Lowe
7984d9fdb4Robert Mustacchi        /* Decode the length of augmented fields. */
7994d9fdb4Robert Mustacchi        DECODE_LEB128_UWORD_CK(frame_ptr, lreg,dbg,error,section_ptr_end);
8004d9fdb4Robert Mustacchi        length_of_augmented_fields = (Dwarf_Unsigned) lreg;
8014d9fdb4Robert Mustacchi        /* set the frame_ptr to point at the instruction start. */
8024d9fdb4Robert Mustacchi        frame_ptr += length_of_augmented_fields;
80307dc194Richard Lowe        }
80407dc194Richard Lowe        break;
80507dc194Richard Lowe
80607dc194Richard Lowe    case aug_eh:{
8074d9fdb4Robert Mustacchi        int err = 0;
8084d9fdb4Robert Mustacchi        unsigned long increment = 0;
80907dc194Richard Lowe
8104d9fdb4Robert Mustacchi        if (!use_gnu_cie_calc) {
8114d9fdb4Robert Mustacchi            /* This should be impossible. */
8124d9fdb4Robert Mustacchi            _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
8134d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
8144d9fdb4Robert Mustacchi        }
81507dc194Richard Lowe
8164d9fdb4Robert Mustacchi        err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
8174d9fdb4Robert Mustacchi            augt,
8184d9fdb4Robert Mustacchi            section_ptr_end,
8194d9fdb4Robert Mustacchi            (char *) augmentation,error);
8204d9fdb4Robert Mustacchi        if (err == DW_DLV_ERROR) {
8214d9fdb4Robert Mustacchi            _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
8224d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
8234d9fdb4Robert Mustacchi        }
8244d9fdb4Robert Mustacchi        frame_ptr += increment;
82507dc194Richard Lowe        }
8264d9fdb4Robert Mustacchi        break;
82707dc194Richard Lowe    case aug_gcc_eh_z:{
8284d9fdb4Robert Mustacchi        /*  Here we have Augmentation Data Length (uleb128) followed
8294d9fdb4Robert Mustacchi            by Augmentation Data bytes (not a string). */
8304d9fdb4Robert Mustacchi        int resz = DW_DLV_ERROR;
8314d9fdb4Robert Mustacchi        Dwarf_Unsigned adlen = 0;
8324d9fdb4Robert Mustacchi
8334d9fdb4Robert Mustacchi        /* Not a great test. FIXME */
8344d9fdb4Robert Mustacchi        if ((frame_ptr+1)  > section_ptr_end) {
8354d9fdb4Robert Mustacchi            _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
8364d9fdb4Robert Mustacchi                "DW_DLE_AUG_DATA_LENGTH_BAD: The "
8374d9fdb4Robert Mustacchi                "gcc .eh_frame augmentation data "
8384d9fdb4Robert Mustacchi                "cannot be read. Out of room in the section."
8394d9fdb4Robert Mustacchi                " Corrupt DWARF.");
8404d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
8414d9fdb4Robert Mustacchi        }
8424d9fdb4Robert Mustacchi        DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
8434d9fdb4Robert Mustacchi            dbg,error,section_ptr_end);
8444d9fdb4Robert Mustacchi        cie_aug_data_len = adlen;
8454d9fdb4Robert Mustacchi        cie_aug_data = frame_ptr;
8464d9fdb4Robert Mustacchi        if (adlen) {
8474d9fdb4Robert Mustacchi            Dwarf_Small *cie_aug_data_end = cie_aug_data+adlen;
8484d9fdb4Robert Mustacchi            if (cie_aug_data_end < cie_aug_data ||
8494d9fdb4Robert Mustacchi                cie_aug_data_end > section_ptr_end) {
8504d9fdb4Robert Mustacchi                dwarfstring m;
8514d9fdb4Robert Mustacchi
8524d9fdb4Robert Mustacchi                dwarfstring_constructor(&m);
8534d9fdb4Robert Mustacchi                dwarfstring_append_printf_u(&m,
8544d9fdb4Robert Mustacchi                    "DW_DLE_AUG_DATA_LENGTH_BAD: The "
8554d9fdb4Robert Mustacchi                    "gcc .eh_frame augmentation data "
8564d9fdb4Robert Mustacchi                    "length of %" DW_PR_DUu " is too long to"
8574d9fdb4Robert Mustacchi                    " fit in the section.",adlen);
8584d9fdb4Robert Mustacchi                _dwarf_error_string(dbg, error,
8594d9fdb4Robert Mustacchi                    DW_DLE_AUG_DATA_LENGTH_BAD,
8604d9fdb4Robert Mustacchi                    dwarfstring_string(&m));
8614d9fdb4Robert Mustacchi                dwarfstring_destructor(&m);
8624d9fdb4Robert Mustacchi                return DW_DLV_ERROR;
86307dc194Richard Lowe            }
86407dc194Richard Lowe        }
8654d9fdb4Robert Mustacchi        resz = gnu_aug_encodings(dbg,
8664d9fdb4Robert Mustacchi            (char *) augmentation,
8674d9fdb4Robert Mustacchi            cie_aug_data,
8684d9fdb4Robert Mustacchi            cie_aug_data_len,
8694d9fdb4Robert Mustacchi            address_size,
8704d9fdb4Robert Mustacchi            &gnu_personality_handler_encoding,
8714d9fdb4Robert Mustacchi            &gnu_lsda_encoding,
8724d9fdb4Robert Mustacchi            &gnu_fde_begin_encoding,
8734d9fdb4Robert Mustacchi            &gnu_personality_handler_addr,
8744d9fdb4Robert Mustacchi            error);
8754d9fdb4Robert Mustacchi        if (resz != DW_DLV_OK) {
8764d9fdb4Robert Mustacchi            _dwarf_error(dbg, error,
8774d9fdb4Robert Mustacchi                DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
8784d9fdb4Robert Mustacchi            return resz;
8794d9fdb4Robert Mustacchi        }
8804d9fdb4Robert Mustacchi        frame_ptr += adlen;
8814d9fdb4Robert Mustacchi        }
8824d9fdb4Robert Mustacchi        break;
88307dc194Richard Lowe    case aug_armcc:
88407dc194Richard Lowe        break;
88507dc194Richard Lowe    default:{
8864d9fdb4Robert Mustacchi        /*  We do not understand the augmentation string. No
8874d9fdb4Robert Mustacchi            assumption can be made about any fields other than what
8884d9fdb4Robert Mustacchi            we have already read. */
8894d9fdb4Robert Mustacchi        frame_ptr = prefix->cf_start_addr +
8904d9fdb4Robert Mustacchi            prefix->cf_length + prefix->cf_local_length_size
8914d9fdb4Robert Mustacchi            + prefix->cf_local_extension_size;
8924d9fdb4Robert Mustacchi        /*  FIX -- What are the values of data_alignment_factor,
8934d9fdb4Robert Mustacchi            code_alignement_factor, return_address_register and
8944d9fdb4Robert Mustacchi            instruction start? They were clearly uninitalized in the
8954d9fdb4Robert Mustacchi            previous version and I am leaving them the same way. */
8964d9fdb4Robert Mustacchi        }
8974d9fdb4Robert Mustacchi        if ((frame_ptr)  > section_ptr_end) {
8984d9fdb4Robert Mustacchi            _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
8994d9fdb4Robert Mustacchi                "DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
9004d9fdb4Robert Mustacchi                "Reading an unknown type of augmentation string "
9014d9fdb4Robert Mustacchi                "run off the end of the section. Corrupt DWARF.");
9024d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
90307dc194Richard Lowe        }
9044d9fdb4Robert Mustacchi        break;
90507dc194Richard Lowe    }                           /* End switch on augmentation type. */
90607dc194Richard Lowe
90707dc194Richard Lowe    new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
90807dc194Richard Lowe    if (new_cie == NULL) {
90907dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
91007dc194Richard Lowe        return (DW_DLV_ERROR);
91107dc194Richard Lowe    }
91207dc194Richard Lowe
91307dc194Richard Lowe    new_cie->ci_cie_version_number = version;
91407dc194Richard Lowe    new_cie->ci_initial_table = NULL;
9154d9fdb4Robert Mustacchi    new_cie->ci_length = (Dwarf_Unsigned) prefix->cf_length;
91607dc194Richard Lowe    new_cie->ci_length_size = prefix->cf_local_length_size;
91707dc194Richard Lowe    new_cie->ci_extension_size = prefix->cf_local_extension_size;
91807dc194Richard Lowe    new_cie->ci_augmentation = (char *) augmentation;
91907dc194Richard Lowe
92007dc194Richard Lowe    new_cie->ci_data_alignment_factor =
92107dc194Richard Lowe        (Dwarf_Sbyte) data_alignment_factor;
92207dc194Richard Lowe    new_cie->ci_code_alignment_factor =
92307dc194Richard Lowe        (Dwarf_Small) code_alignment_factor;
92407dc194Richard Lowe    new_cie->ci_return_address_register = return_address_register;
92507dc194Richard Lowe    new_cie->ci_cie_start = prefix->cf_start_addr;
9264d9fdb4Robert Mustacchi
9274d9fdb4Robert Mustacchi    if ( frame_ptr > section_ptr_end) {
9284d9fdb4Robert Mustacchi        _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
9294d9fdb4Robert Mustacchi        return (DW_DLV_ERROR);
9304d9fdb4Robert Mustacchi    }
93107dc194Richard Lowe    new_cie->ci_cie_instr_start = frame_ptr;
93207dc194Richard Lowe    new_cie->ci_dbg = dbg;
93307dc194Richard Lowe    new_cie->ci_augmentation_type = augt;
93407dc194Richard Lowe    new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
93507dc194Richard Lowe    new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
93607dc194Richard Lowe    new_cie->ci_gnu_personality_handler_encoding =
93707dc194Richard Lowe        gnu_personality_handler_encoding;
93807dc194Richard Lowe    new_cie->ci_gnu_personality_handler_addr =
93907dc194Richard Lowe        gnu_personality_handler_addr;
94007dc194Richard Lowe    new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
94107dc194Richard Lowe    new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
94207dc194Richard Lowe
94307dc194Richard Lowe    new_cie->ci_index = cie_count;
94407dc194Richard Lowe    new_cie->ci_section_ptr = prefix->cf_section_ptr;
9454d9fdb4Robert Mustacchi    new_cie->ci_section_end = section_ptr_end;
9464d9fdb4Robert Mustacchi    new_cie->ci_cie_end = new_cie->ci_cie_start + new_cie->ci_length +
9474d9fdb4Robert Mustacchi        new_cie->ci_length_size+ new_cie->ci_extension_size;
9484d9fdb4Robert Mustacchi    if ( new_cie->ci_cie_end > section_ptr_end) {
9494d9fdb4Robert Mustacchi        _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
9504d9fdb4Robert Mustacchi        return (DW_DLV_ERROR);
9514d9fdb4Robert Mustacchi    }
9524d9fdb4Robert Mustacchi
95307dc194Richard Lowe    /* The Following new in DWARF4 */
95407dc194Richard Lowe    new_cie->ci_address_size = address_size;
95507dc194Richard Lowe    new_cie->ci_segment_size = segment_size;
95607dc194Richard Lowe    validate_length(dbg,new_cie,new_cie->ci_length,
95707dc194Richard Lowe        new_cie->ci_length_size, new_cie->ci_extension_size,
95807dc194Richard Lowe        new_cie->ci_section_ptr,
95907dc194Richard Lowe        new_cie->ci_cie_start,"cie");
96007dc194Richard Lowe
96107dc194Richard Lowe    *cie_ptr_out = new_cie;
96207dc194Richard Lowe    return DW_DLV_OK;
96307dc194Richard Lowe
96407dc194Richard Lowe}
96507dc194Richard Lowe
96607dc194Richard Lowe
9674d9fdb4Robert Mustacchi/*  Internal function, not called by consumer code.
9684d9fdb4Robert Mustacchi    'prefix' has accumulated the info up thru the cie-id
9694d9fdb4Robert Mustacchi    and now we consume the rest and build a Dwarf_Fde_s structure.
9704d9fdb4Robert Mustacchi    Can be called with cie_ptr_in NULL from dwarf_frame.c  */
97107dc194Richard Lowe
97207dc194Richard Loweint
97307dc194Richard Lowedwarf_create_fde_from_after_start(Dwarf_Debug dbg,
97407dc194Richard Lowe    struct cie_fde_prefix_s *prefix,
97507dc194Richard Lowe    Dwarf_Small * section_pointer,
97607dc194Richard Lowe    Dwarf_Small * frame_ptr,
9774d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr_end,
97807dc194Richard Lowe    int use_gnu_cie_calc,
97907dc194Richard Lowe    Dwarf_Cie cie_ptr_in,
98007dc194Richard Lowe    Dwarf_Fde * fde_ptr_out,
98107dc194Richard Lowe    Dwarf_Error * error)
98207dc194Richard Lowe{
98307dc194Richard Lowe    Dwarf_Fde new_fde = 0;
9844d9fdb4Robert Mustacchi    Dwarf_Cie cieptr = 0;
98507dc194Richard Lowe    Dwarf_Small *saved_frame_ptr = 0;
98607dc194Richard Lowe
98707dc194Richard Lowe    Dwarf_Small *initloc = frame_ptr;
98807dc194Richard Lowe    Dwarf_Signed offset_into_exception_tables
98907dc194Richard Lowe        = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
99007dc194Richard Lowe    Dwarf_Small *fde_aug_data = 0;
99107dc194Richard Lowe    Dwarf_Unsigned fde_aug_data_len = 0;
99207dc194Richard Lowe    Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
99307dc194Richard Lowe    Dwarf_Addr initial_location = 0;    /* must be min de_pointer_size
9944d9fdb4Robert Mustacchi        bytes in size */
99507dc194Richard Lowe    Dwarf_Addr address_range = 0;       /* must be min de_pointer_size
9964d9fdb4Robert Mustacchi        bytes in size */
9974d9fdb4Robert Mustacchi    Dwarf_Half address_size = 0;
9984d9fdb4Robert Mustacchi    Dwarf_Unsigned eh_table_value = 0;
9994d9fdb4Robert Mustacchi    Dwarf_Bool eh_table_value_set = FALSE;
10004d9fdb4Robert Mustacchi    /* Temporary assumption.  */
10014d9fdb4Robert Mustacchi    enum Dwarf_augmentation_type augt = aug_empty_string;
10024d9fdb4Robert Mustacchi
10034d9fdb4Robert Mustacchi    if (cie_ptr_in) {
10044d9fdb4Robert Mustacchi        cieptr = cie_ptr_in;
10054d9fdb4Robert Mustacchi        address_size = cieptr->ci_address_size;
10064d9fdb4Robert Mustacchi        augt = cieptr->ci_augmentation_type;
10074d9fdb4Robert Mustacchi    }
100807dc194Richard Lowe
100907dc194Richard Lowe    if (augt == aug_gcc_eh_z) {
10104d9fdb4Robert Mustacchi        /*  If z augmentation this is eh_frame, and initial_location and
10114d9fdb4Robert Mustacchi            address_range in the FDE are read according to the CIE
10124d9fdb4Robert Mustacchi            augmentation string instructions.  */
101307dc194Richard Lowe
101407dc194Richard Lowe        {
101507dc194Richard Lowe            Dwarf_Small *fp_updated = 0;
101607dc194Richard Lowe            int res = read_encoded_ptr(dbg,
101707dc194Richard Lowe                section_pointer,
101807dc194Richard Lowe                frame_ptr,
101907dc194Richard Lowe                cieptr-> ci_gnu_fde_begin_encoding,
10204d9fdb4Robert Mustacchi                section_ptr_end,
102107dc194Richard Lowe                address_size,
102207dc194Richard Lowe                &initial_location,
10234d9fdb4Robert Mustacchi                &fp_updated,error);
102407dc194Richard Lowe            if (res != DW_DLV_OK) {
10254d9fdb4Robert Mustacchi                return res;
102607dc194Richard Lowe            }
102707dc194Richard Lowe            frame_ptr = fp_updated;
10284d9fdb4Robert Mustacchi            /*  For the address-range it makes no sense to be
10294d9fdb4Robert Mustacchi                pc-relative, so we turn it off with a section_pointer of
10304d9fdb4Robert Mustacchi                NULL. Masking off DW_EH_PE_pcrel from the
10314d9fdb4Robert Mustacchi                ci_gnu_fde_begin_encoding in this call would also work
10324d9fdb4Robert Mustacchi                to turn off DW_EH_PE_pcrel. */
103307dc194Richard Lowe            res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
10344d9fdb4Robert Mustacchi                frame_ptr,
10354d9fdb4Robert Mustacchi                cieptr->ci_gnu_fde_begin_encoding,
10364d9fdb4Robert Mustacchi                section_ptr_end,
10374d9fdb4Robert Mustacchi                address_size,
10384d9fdb4Robert Mustacchi                &address_range, &fp_updated,error);
103907dc194Richard Lowe            if (res != DW_DLV_OK) {
10404d9fdb4Robert Mustacchi                return res;
104107dc194Richard Lowe            }
104207dc194Richard Lowe            frame_ptr = fp_updated;
104307dc194Richard Lowe        }
104407dc194Richard Lowe        {
104507dc194Richard Lowe            Dwarf_Unsigned adlen = 0;
104607dc194Richard Lowe
10474d9fdb4Robert Mustacchi            DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
10484d9fdb4Robert Mustacchi                dbg,error,section_ptr_end);
104907dc194Richard Lowe            fde_aug_data_len = adlen;
105007dc194Richard Lowe            fde_aug_data = frame_ptr;
105107dc194Richard Lowe            frame_ptr += adlen;
10524d9fdb4Robert Mustacchi            if (adlen) {
10534d9fdb4Robert Mustacchi                if (frame_ptr < fde_aug_data ||
10544d9fdb4Robert Mustacchi                    frame_ptr >= section_ptr_end ) {
10554d9fdb4Robert Mustacchi                    dwarfstring m;
10564d9fdb4Robert Mustacchi
10574d9fdb4Robert Mustacchi                    dwarfstring_constructor(&m);
10584d9fdb4Robert Mustacchi                    dwarfstring_append_printf_u(&m,
10594d9fdb4Robert Mustacchi                        "DW_DLE_AUG_DATA_LENGTH_BAD: The "
10604d9fdb4Robert Mustacchi                        "gcc .eh_frame augmentation data "
10614d9fdb4Robert Mustacchi                        "length of %" DW_PR_DUu " is too long to"
10624d9fdb4Robert Mustacchi                        " fit in the section.",adlen);
10634d9fdb4Robert Mustacchi                    _dwarf_error_string(dbg, error,
10644d9fdb4Robert Mustacchi                        DW_DLE_AUG_DATA_LENGTH_BAD,
10654d9fdb4Robert Mustacchi                        dwarfstring_string(&m));
10664d9fdb4Robert Mustacchi                    dwarfstring_destructor(&m);
10674d9fdb4Robert Mustacchi                    return DW_DLV_ERROR;
10684d9fdb4Robert Mustacchi                }
10694d9fdb4Robert Mustacchi            }
107007dc194Richard Lowe        }
107107dc194Richard Lowe
107207dc194Richard Lowe    } else {
10734d9fdb4Robert Mustacchi        if ((frame_ptr + 2*address_size) > section_ptr_end) {
10744d9fdb4Robert Mustacchi            _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
10754d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
10764d9fdb4Robert Mustacchi        }
10774d9fdb4Robert Mustacchi        READ_UNALIGNED_CK(dbg, initial_location, Dwarf_Addr,
10784d9fdb4Robert Mustacchi            frame_ptr, address_size,
10794d9fdb4Robert Mustacchi            error,section_ptr_end);
108007dc194Richard Lowe        frame_ptr += address_size;
10814d9fdb4Robert Mustacchi        READ_UNALIGNED_CK(dbg, address_range, Dwarf_Addr,
10824d9fdb4Robert Mustacchi            frame_ptr, address_size,
10834d9fdb4Robert Mustacchi            error,section_ptr_end);
108407dc194Richard Lowe        frame_ptr += address_size;
108507dc194Richard Lowe    }
108607dc194Richard Lowe    switch (augt) {
108707dc194Richard Lowe    case aug_irix_mti_v1:
108807dc194Richard Lowe    case aug_empty_string:
108907dc194Richard Lowe        break;
109007dc194Richard Lowe    case aug_irix_exception_table:{
10914d9fdb4Robert Mustacchi        Dwarf_Unsigned lreg = 0;
10924d9fdb4Robert Mustacchi        Dwarf_Unsigned length_of_augmented_fields = 0;
10934d9fdb4Robert Mustacchi
10944d9fdb4Robert Mustacchi        DECODE_LEB128_UWORD_CK(frame_ptr, lreg,
10954d9fdb4Robert Mustacchi            dbg,error,section_ptr_end);
10964d9fdb4Robert Mustacchi        length_of_augmented_fields = (Dwarf_Unsigned) lreg;
10974d9fdb4Robert Mustacchi
10984d9fdb4Robert Mustacchi        saved_frame_ptr = frame_ptr;
10994d9fdb4Robert Mustacchi        /*  The first word is an offset into exception tables.
11004d9fdb4Robert Mustacchi            Defined as a 32bit offset even for CC -64. */
11014d9fdb4Robert Mustacchi        if ((frame_ptr + DWARF_32BIT_SIZE) > section_ptr_end) {
11024d9fdb4Robert Mustacchi            _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
11034d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
11044d9fdb4Robert Mustacchi        }
11054d9fdb4Robert Mustacchi        READ_UNALIGNED_CK(dbg, offset_into_exception_tables,
11064d9fdb4Robert Mustacchi            Dwarf_Addr, frame_ptr, DWARF_32BIT_SIZE,
11074d9fdb4Robert Mustacchi            error,section_ptr_end);
11084d9fdb4Robert Mustacchi        SIGN_EXTEND(offset_into_exception_tables,
11094d9fdb4Robert Mustacchi            DWARF_32BIT_SIZE);
11104d9fdb4Robert Mustacchi        frame_ptr = saved_frame_ptr + length_of_augmented_fields;
111107dc194Richard Lowe        }
111207dc194Richard Lowe        break;
111307dc194Richard Lowe    case aug_eh:{
111407dc194Richard Lowe
11154d9fdb4Robert Mustacchi        if (!use_gnu_cie_calc) {
11164d9fdb4Robert Mustacchi            /* This should be impossible. */
11174d9fdb4Robert Mustacchi            _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
11184d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
11194d9fdb4Robert Mustacchi        }
112007dc194Richard Lowe
11214d9fdb4Robert Mustacchi        /* gnu eh fde case. we do not need to do anything */
11224d9fdb4Robert Mustacchi        /*REFERENCED*/ /* Not used in this instance of the macro */
11234d9fdb4Robert Mustacchi        if ((frame_ptr + address_size) > section_ptr_end) {
11244d9fdb4Robert Mustacchi            _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
11254d9fdb4Robert Mustacchi            return DW_DLV_ERROR;
11264d9fdb4Robert Mustacchi        }
11274d9fdb4Robert Mustacchi        READ_UNALIGNED_CK(dbg, eh_table_value,
11284d9fdb4Robert Mustacchi            Dwarf_Unsigned, frame_ptr,
11294d9fdb4Robert Mustacchi            address_size,
11304d9fdb4Robert Mustacchi            error,section_ptr_end);
11314d9fdb4Robert Mustacchi        eh_table_value_set = TRUE;
11324d9fdb4Robert Mustacchi        frame_ptr += address_size;
113307dc194Richard Lowe        }
113407dc194Richard Lowe        break;
113507dc194Richard Lowe
113607dc194Richard Lowe    case aug_gcc_eh_z:{
11374d9fdb4Robert Mustacchi        /*  The Augmentation Data Length is here, followed by the
11384d9fdb4Robert Mustacchi            Augmentation Data bytes themselves. */
113907dc194Richard Lowe        }
114007dc194Richard Lowe        break;
114107dc194Richard Lowe    case aug_armcc:
114207dc194Richard Lowe        break;
114307dc194Richard Lowe    case aug_past_last:
114407dc194Richard Lowe        break;
11454d9fdb4Robert Mustacchi
11464d9fdb4Robert Mustacchi    case aug_metaware: /* No special fields. See dwarf_util.h */
11474d9fdb4Robert Mustacchi        break;
11484d9fdb4Robert Mustacchi
114907dc194Richard Lowe    case aug_unknown:
115007dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
115107dc194Richard Lowe        return DW_DLV_ERROR;
115207dc194Richard Lowe    }                           /* End switch on augmentation type */
11534d9fdb4Robert Mustacchi    if ( frame_ptr > section_ptr_end) {
11544d9fdb4Robert Mustacchi        _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
11554d9fdb4Robert Mustacchi        return (DW_DLV_ERROR);
11564d9fdb4Robert Mustacchi    }
11574d9fdb4Robert Mustacchi
115807dc194Richard Lowe    new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
115907dc194Richard Lowe    if (new_fde == NULL) {
116007dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
116107dc194Richard Lowe        return (DW_DLV_ERROR);
116207dc194Richard Lowe    }
116307dc194Richard Lowe
116407dc194Richard Lowe    new_fde->fd_length = prefix->cf_length;
116507dc194Richard Lowe    new_fde->fd_length_size = prefix->cf_local_length_size;
116607dc194Richard Lowe    new_fde->fd_extension_size = prefix->cf_local_extension_size;
116707dc194Richard Lowe    new_fde->fd_is_eh = use_gnu_cie_calc;
116807dc194Richard Lowe    new_fde->fd_cie_offset = cie_base_offset;
11694d9fdb4Robert Mustacchi    if (cieptr) {
11704d9fdb4Robert Mustacchi        new_fde->fd_cie_index = cieptr->ci_index;
11714d9fdb4Robert Mustacchi    }
117207dc194Richard Lowe    new_fde->fd_cie = cieptr;
117307dc194Richard Lowe    new_fde->fd_initial_location = initial_location;
117407dc194Richard Lowe    new_fde->fd_initial_loc_pos = initloc;
117507dc194Richard Lowe    new_fde->fd_address_range = address_range;
117607dc194Richard Lowe    new_fde->fd_fde_start = prefix->cf_start_addr;
11774d9fdb4Robert Mustacchi
117807dc194Richard Lowe    new_fde->fd_fde_instr_start = frame_ptr;
11794d9fdb4Robert Mustacchi    new_fde->fd_fde_end = prefix->cf_start_addr +
11804d9fdb4Robert Mustacchi        prefix->cf_length +  prefix->cf_local_length_size  +
11814d9fdb4Robert Mustacchi        prefix->cf_local_extension_size;
11824d9fdb4Robert Mustacchi    if ( new_fde->fd_fde_end > section_ptr_end) {
11834d9fdb4Robert Mustacchi        _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
11844d9fdb4Robert Mustacchi        return (DW_DLV_ERROR);
11854d9fdb4Robert Mustacchi    }
11864d9fdb4Robert Mustacchi
118707dc194Richard Lowe    new_fde->fd_dbg = dbg;
118807dc194Richard Lowe    new_fde->fd_offset_into_exception_tables =
118907dc194Richard Lowe        offset_into_exception_tables;
11904d9fdb4Robert Mustacchi    new_fde->fd_eh_table_value = eh_table_value;
11914d9fdb4Robert Mustacchi    new_fde->fd_eh_table_value_set = eh_table_value_set;
119207dc194Richard Lowe
119307dc194Richard Lowe    new_fde->fd_section_ptr = prefix->cf_section_ptr;
119407dc194Richard Lowe    new_fde->fd_section_index = prefix->cf_section_index;
119507dc194Richard Lowe    new_fde->fd_section_length = prefix->cf_section_length;
11964d9fdb4Robert Mustacchi    new_fde->fd_section_end = section_ptr_end;
119707dc194Richard Lowe
11984d9fdb4Robert Mustacchi    if (augt == aug_gcc_eh_z) {
11994d9fdb4Robert Mustacchi        new_fde->fd_gnu_eh_aug_present = TRUE;
12004d9fdb4Robert Mustacchi    }
120107dc194Richard Lowe    new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
120207dc194Richard Lowe    new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
120307dc194Richard Lowe    validate_length(dbg,cieptr,new_fde->fd_length,
120407dc194Richard Lowe        new_fde->fd_length_size, new_fde->fd_extension_size,
120507dc194Richard Lowe        new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
120607dc194Richard Lowe    *fde_ptr_out = new_fde;
120707dc194Richard Lowe    return DW_DLV_OK;
120807dc194Richard Lowe}
120907dc194Richard Lowe
12104d9fdb4Robert Mustacchi/*  Read in the common cie/fde prefix, including reading
12114d9fdb4Robert Mustacchi    the cie-value which shows which this is: cie or fde.  */
121207dc194Richard Loweint
121307dc194Richard Lowedwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
12144d9fdb4Robert Mustacchi    Dwarf_Small * frame_ptr_in,
12154d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr_in,
12164d9fdb4Robert Mustacchi    Dwarf_Unsigned section_index_in,
12174d9fdb4Robert Mustacchi    Dwarf_Unsigned section_length_in,
12184d9fdb4Robert Mustacchi    struct cie_fde_prefix_s *data_out,
12194d9fdb4Robert Mustacchi    Dwarf_Error * error)
122007dc194Richard Lowe{
122107dc194Richard Lowe    Dwarf_Unsigned length = 0;
122207dc194Richard Lowe    int local_length_size = 0;
122307dc194Richard Lowe    int local_extension_size = 0;
122407dc194Richard Lowe    Dwarf_Small *frame_ptr = frame_ptr_in;
122507dc194Richard Lowe    Dwarf_Small *cie_ptr_addr = 0;
122607dc194Richard Lowe    Dwarf_Unsigned cie_id = 0;
12274d9fdb4Robert Mustacchi    Dwarf_Small *section_end = section_ptr_in + section_length_in;
12284d9fdb4Robert Mustacchi
12294d9fdb4Robert Mustacchi    if(section_end < (frame_ptr +4)) {
12304d9fdb4Robert Mustacchi        dwarfstring m;
12314d9fdb4Robert Mustacchi        Dwarf_Unsigned u = (Dwarf_Unsigned)(uintptr_t)(frame_ptr+4) -
12324d9fdb4Robert Mustacchi            (Dwarf_Unsigned)(uintptr_t)section_end;
12334d9fdb4Robert Mustacchi
12344d9fdb4Robert Mustacchi        dwarfstring_constructor(&m);
12354d9fdb4Robert Mustacchi        dwarfstring_append_printf_u(&m,
12364d9fdb4Robert Mustacchi            "DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
12374d9fdb4Robert Mustacchi            "Reading the cie/fde prefix would "
12384d9fdb4Robert Mustacchi            "put us %u bytes past the end of the "
12394d9fdb4Robert Mustacchi            "frame section.  Corrupt Dwarf.",u);
12404d9fdb4Robert Mustacchi        _dwarf_error_string(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD,
12414d9fdb4Robert Mustacchi            dwarfstring_string(&m));
12424d9fdb4Robert Mustacchi        dwarfstring_destructor(&m);
12434d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
12444d9fdb4Robert Mustacchi    }
124507dc194Richard Lowe    /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
12464d9fdb4Robert Mustacchi    READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned,
12474d9fdb4Robert Mustacchi        frame_ptr, local_length_size,
12484d9fdb4Robert Mustacchi        local_extension_size,error,
12494d9fdb4Robert Mustacchi        section_length_in,section_end);
125007dc194Richard Lowe
125107dc194Richard Lowe    if (length == 0) {
12524d9fdb4Robert Mustacchi        /*  nul bytes at end of section, seen at end of egcs eh_frame
12534d9fdb4Robert Mustacchi            sections (in a.out). Take this as meaning no more CIE/FDE
12544d9fdb4Robert Mustacchi            data. We should be very close to end of section. */
125507dc194Richard Lowe        return DW_DLV_NO_ENTRY;
125607dc194Richard Lowe    }
12574d9fdb4Robert Mustacchi    if((frame_ptr + local_length_size) >= section_end) {
12584d9fdb4Robert Mustacchi        _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
12594d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
12604d9fdb4Robert Mustacchi    }
126107dc194Richard Lowe
126207dc194Richard Lowe    cie_ptr_addr = frame_ptr;
12634d9fdb4Robert Mustacchi    READ_UNALIGNED_CK(dbg, cie_id, Dwarf_Unsigned,
12644d9fdb4Robert Mustacchi        frame_ptr, local_length_size,error,section_end);
126507dc194Richard Lowe    SIGN_EXTEND(cie_id, local_length_size);
126607dc194Richard Lowe    frame_ptr += local_length_size;
126707dc194Richard Lowe
126807dc194Richard Lowe    data_out->cf_start_addr = frame_ptr_in;
126907dc194Richard Lowe    data_out->cf_addr_after_prefix = frame_ptr;
127007dc194Richard Lowe
127107dc194Richard Lowe    data_out->cf_length = length;
12724d9fdb4Robert Mustacchi    if (length > section_length_in) {
12734d9fdb4Robert Mustacchi        _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
12744d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
12754d9fdb4Robert Mustacchi    }
12764d9fdb4Robert Mustacchi    if (cie_ptr_addr+length > section_end) {
12774d9fdb4Robert Mustacchi        _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
12784d9fdb4Robert Mustacchi        return DW_DLV_ERROR;
12794d9fdb4Robert Mustacchi    }
128007dc194Richard Lowe    data_out->cf_local_length_size = local_length_size;
128107dc194Richard Lowe    data_out->cf_local_extension_size = local_extension_size;
12824d9fdb4Robert Mustacchi
12834d9fdb4Robert Mustacchi    /*  We do not know if it is a CIE or FDE id yet.
12844d9fdb4Robert Mustacchi        How we check and what it means
12854d9fdb4Robert Mustacchi        depends whether it is .debug_frame
12864d9fdb4Robert Mustacchi        or .eh_frame. */
128707dc194Richard Lowe    data_out->cf_cie_id = cie_id;
12884d9fdb4Robert Mustacchi
12894d9fdb4Robert Mustacchi    /*  The address of the CIE_id  or FDE_id value in memory.  */
129007dc194Richard Lowe    data_out->cf_cie_id_addr = cie_ptr_addr;
12914d9fdb4Robert Mustacchi
129207dc194Richard Lowe    data_out->cf_section_ptr = section_ptr_in;
129307dc194Richard Lowe    data_out->cf_section_index = section_index_in;
129407dc194Richard Lowe    data_out->cf_section_length = section_length_in;
129507dc194Richard Lowe    return DW_DLV_OK;
129607dc194Richard Lowe}
129707dc194Richard Lowe
12984d9fdb4Robert Mustacchi/*  On various errors previously-allocated CIEs and FDEs
12994d9fdb4Robert Mustacchi    must be cleaned up.
13004d9fdb4Robert Mustacchi    This helps avoid leaks in case of errors.
130107dc194Richard Lowe*/
130207dc194Richard Lowestatic void
130307dc194Richard Lowedealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
130407dc194Richard Lowe    Dwarf_Cie head_cie_ptr)
130507dc194Richard Lowe{
130607dc194Richard Lowe    Dwarf_Fde curfde = 0;
130707dc194Richard Lowe    Dwarf_Cie curcie = 0;
130807dc194Richard Lowe    Dwarf_Fde nextfde = 0;
130907dc194Richard Lowe    Dwarf_Cie nextcie = 0;
131007dc194Richard Lowe
131107dc194Richard Lowe    for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
131207dc194Richard Lowe        nextfde = curfde->fd_next;
131307dc194Richard Lowe        dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
131407dc194Richard Lowe    }
131507dc194Richard Lowe    for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
131607dc194Richard Lowe        Dwarf_Frame frame = curcie->ci_initial_table;
131707dc194Richard Lowe
131807dc194Richard Lowe        nextcie = curcie->ci_next;
131907dc194Richard Lowe        if (frame)
132007dc194Richard Lowe            dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
132107dc194Richard Lowe        dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
132207dc194Richard Lowe    }
132307dc194Richard Lowe}
132407dc194Richard Lowe
13254d9fdb4Robert Mustacchi/*  Find the cie whose id value is given: the id
13264d9fdb4Robert Mustacchi    value is, per DWARF2/3, an offset in the section.
13274d9fdb4Robert Mustacchi    For .debug_frame, zero is a legal offset. For
13284d9fdb4Robert Mustacchi    GNU .eh_frame it is not a legal offset.
13294d9fdb4Robert Mustacchi    'cie_ptr' is a pointer into our section, not an offset. */
133007dc194Richard Lowestatic int
133107dc194Richard Lowedwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
13324d9fdb4Robert Mustacchi    Dwarf_Cie cur_cie_ptr,
13334d9fdb4Robert Mustacchi    Dwarf_Cie * cie_ptr_to_use_out,
13344d9fdb4Robert Mustacchi    Dwarf_Cie head_cie_ptr)
133507dc194Richard Lowe{
133607dc194Richard Lowe    Dwarf_Cie next = 0;
133707dc194Richard Lowe
133807dc194Richard Lowe    if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
133907dc194Richard Lowe        /* Usually, we use the same cie again and again. */
134007dc194Richard Lowe        *cie_ptr_to_use_out = cur_cie_ptr;
134107dc194Richard Lowe        return DW_DLV_OK;
134207dc194Richard Lowe    }
134307dc194Richard Lowe    for (next = head_cie_ptr; next; next = next->ci_next) {
134407dc194Richard Lowe        if (cie_ptr == next->ci_cie_start) {
134507dc194Richard Lowe            *cie_ptr_to_use_out = next;
134607dc194Richard Lowe            return DW_DLV_OK;
134707dc194Richard Lowe        }
134807dc194Richard Lowe    }
134907dc194Richard Lowe    return DW_DLV_NO_ENTRY;
135007dc194Richard Lowe}
135107dc194Richard Lowe
135207dc194Richard Lowe
13534d9fdb4Robert Mustacchi/*  We have a valid cie_ptr_val that has not been
13544d9fdb4Robert Mustacchi    turned into an internal Cie yet. Do so now.
13554d9fdb4Robert Mustacchi    Returns DW_DLV_OK or DW_DLV_ERROR, never
13564d9fdb4Robert Mustacchi    DW_DLV_NO_ENTRY.
135707dc194Richard Lowe
13584d9fdb4Robert Mustacchi    'section_ptr'    - Points to first byte of section data.
13594d9fdb4Robert Mustacchi    'section_length' - Length of the section, in bytes.
13604d9fdb4Robert Mustacchi    'section_ptr_end'  - Points 1-past last byte of section data.  */
136107dc194Richard Lowestatic int
136207dc194Richard Lowedwarf_create_cie_from_start(Dwarf_Debug dbg,
136307dc194Richard Lowe    Dwarf_Small * cie_ptr_val,
136407dc194Richard Lowe    Dwarf_Small * section_ptr,
136507dc194Richard Lowe    Dwarf_Unsigned section_index,
136607dc194Richard Lowe    Dwarf_Unsigned section_length,
13674d9fdb4Robert Mustacchi    Dwarf_Small * section_ptr_end,
136807dc194Richard Lowe    Dwarf_Unsigned cie_id_value,
136907dc194Richard Lowe    Dwarf_Unsigned cie_count,
137007dc194Richard Lowe    int use_gnu_cie_calc,
137107dc194Richard Lowe    Dwarf_Cie * cie_ptr_to_use_out,
137207dc194Richard Lowe    Dwarf_Error * error)
137307dc194Richard Lowe{
137407dc194Richard Lowe    struct cie_fde_prefix_s prefix;
137507dc194Richard Lowe    int res = DW_DLV_ERROR;
137607dc194Richard Lowe    Dwarf_Small *frame_ptr = cie_ptr_val;
137707dc194Richard Lowe
13784d9fdb4Robert Mustacchi    if (frame_ptr < section_ptr || frame_ptr >= section_ptr_end) {
137907dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
138007dc194Richard Lowe        return DW_DLV_ERROR;
138107dc194Richard Lowe    }
13824d9fdb4Robert Mustacchi    /*  First read in the 'common prefix' to figure out what * we are to
13834d9fdb4Robert Mustacchi        do with this entry. If it is not a cie * we are in big trouble. */
138407dc194Richard Lowe    memset(&prefix, 0, sizeof(prefix));
138507dc194Richard Lowe    res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
138607dc194Richard Lowe        section_index, section_length,
138707dc194Richard Lowe        &prefix, error);
138807dc194Richard Lowe    if (res == DW_DLV_ERROR) {
138907dc194Richard Lowe        return res;
139007dc194Richard Lowe    }
139107dc194Richard Lowe    if (res == DW_DLV_NO_ENTRY) {
139207dc194Richard Lowe        /* error. */
139307dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
139407dc194Richard Lowe        return DW_DLV_ERROR;
139507dc194Richard Lowe
139607dc194Richard Lowe    }
139707dc194Richard Lowe
139807dc194Richard Lowe    if (prefix.cf_cie_id != cie_id_value) {
139907dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
140007dc194Richard Lowe        return DW_DLV_ERROR;
140107dc194Richard Lowe    }
140207dc194Richard Lowe    frame_ptr = prefix.cf_addr_after_prefix;
140307dc194Richard Lowe    res = dwarf_create_cie_from_after_start(dbg,
140407dc194Richard Lowe        &prefix,
140507dc194Richard Lowe        section_ptr,
140607dc194Richard Lowe        frame_ptr,
14074d9fdb4Robert Mustacchi        section_ptr_end,
140807dc194Richard Lowe        cie_count,
140907dc194Richard Lowe        use_gnu_cie_calc,
141007dc194Richard Lowe        cie_ptr_to_use_out, error);
141107dc194Richard Lowe    return res;
141207dc194Richard Lowe
141307dc194Richard Lowe}
141407dc194Richard Lowe
141507dc194Richard Lowe
141607dc194Richard Lowe/* This is for gnu eh frames, the 'z' case.
141707dc194Richard Lowe   We find the letter involved
141807dc194Richard Lowe   Return the augmentation character and, if applicable,
141907dc194Richard Lowe   the personality routine address.
142007dc194Richard Lowe
14214d9fdb4Robert Mustacchi   personality_routine_out -
14224d9fdb4Robert Mustacchi        if 'P' is augchar, is personality handler addr.
142307dc194Richard Lowe        Otherwise is not set.
142407dc194Richard Lowe   aug_data  - if 'P' points  to data space of the
142507dc194Richard Lowe   aug_data_len - length of areas aug_data points to.
142607dc194Richard Lowe
14274d9fdb4Robert Mustacchi*/
142807dc194Richard Lowe
14294d9fdb4Robert Mustacchi/*  It is not clear if this is entirely correct. */
143007dc194Richard Lowestatic int
143107dc194Richard Lowegnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
143207dc194Richard Lowe    Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
143307dc194Richard Lowe    Dwarf_Half address_size,
143407dc194Richard Lowe    unsigned char *pers_hand_enc_out,
143507dc194Richard Lowe    unsigned char *lsda_enc_out,
143607dc194Richard Lowe    unsigned char *fde_begin_enc_out,
14374d9fdb4Robert Mustacchi    Dwarf_Addr * gnu_pers_addr_out,
14384d9fdb4Robert Mustacchi    Dwarf_Error * error)
143907dc194Richard Lowe{
144007dc194Richard Lowe    char *nc = 0;
144107dc194Richard Lowe    Dwarf_Small *cur_aug_p = aug_data;
144207dc194Richard Lowe    Dwarf_Small *end_aug_p = aug_data + aug_data_len;
144307dc194Richard Lowe
144407dc194Richard Lowe    for (nc = augmentation; *nc; ++nc) {
144507dc194Richard Lowe        char c = *nc;
144607dc194Richard Lowe
144707dc194Richard Lowe        switch (c) {
144807dc194Richard Lowe        case 'z':
144907dc194Richard Lowe            /* Means that the augmentation data is present. */
145007dc194Richard Lowe            continue;
145107dc194Richard Lowe
145207dc194Richard Lowe        case 'S':
14534d9fdb4Robert Mustacchi            /*  Indicates this is a signal stack frame.
14544d9fdb4Robert Mustacchi                Debuggers have to do
14554d9fdb4Robert Mustacchi                special handling.  We don't need to do more than
14564d9fdb4Robert Mustacchi                print this flag at the right time, though
14574d9fdb4Robert Mustacchi                (see dwarfdump where it prints the augmentation
14584d9fdb4Robert Mustacchi                string).
14594d9fdb4Robert Mustacchi                A signal stack frame (in some OS's) can only be
14604d9fdb4Robert Mustacchi                unwound (backtraced) by knowing it is a signal
14614d9fdb4Robert Mustacchi                stack frame (perhaps by noticing the name of the
14624d9fdb4Robert Mustacchi                function for the stack frame if the name can be
14634d9fdb4Robert Mustacchi                found somehow) and figuring
14644d9fdb4Robert Mustacchi                out (or knowing) how the kernel and libc
14654d9fdb4Robert Mustacchi                pushed a structure
14664d9fdb4Robert Mustacchi                onto the stack and loading registers from that structure.
14674d9fdb4Robert Mustacchi                Totally different from normal stack unwinding.
14684d9fdb4Robert Mustacchi                This flag gives an unwinder a big leg up by
14694d9fdb4Robert Mustacchi                decoupling the 'hint: this is a stack frame'
14704d9fdb4Robert Mustacchi                from knowledge like
14714d9fdb4Robert Mustacchi                the function name (the name might be
14724d9fdb4Robert Mustacchi                unavailable at unwind time).
147307dc194Richard Lowe            */
147407dc194Richard Lowe            break;
14754d9fdb4Robert Mustacchi
147607dc194Richard Lowe        case 'L':
147707dc194Richard Lowe            if (cur_aug_p > end_aug_p) {
14784d9fdb4Robert Mustacchi                _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
147907dc194Richard Lowe                return DW_DLV_ERROR;
148007dc194Richard Lowe            }
148107dc194Richard Lowe            *lsda_enc_out = *(unsigned char *) cur_aug_p;
148207dc194Richard Lowe            ++cur_aug_p;
148307dc194Richard Lowe            break;
148407dc194Richard Lowe        case 'R':
14854d9fdb4Robert Mustacchi            /*  Followed by a one byte argument giving the
14864d9fdb4Robert Mustacchi                pointer encoding for the address pointers in the fde. */
148707dc194Richard Lowe            if (cur_aug_p >= end_aug_p) {
14884d9fdb4Robert Mustacchi                _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
148907dc194Richard Lowe                return DW_DLV_ERROR;
149007dc194Richard Lowe            }
149107dc194Richard Lowe            *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
149207dc194Richard Lowe            ++cur_aug_p;
149307dc194Richard Lowe            break;
149407dc194Richard Lowe        case 'P':{
14954d9fdb4Robert Mustacchi            int res = DW_DLV_ERROR;
14964d9fdb4Robert Mustacchi            Dwarf_Small *updated_aug_p = 0;
14974d9fdb4Robert Mustacchi            unsigned char encoding = 0;
149807dc194Richard Lowe
14994d9fdb4Robert Mustacchi            if (cur_aug_p >= end_aug_p) {
15004d9fdb4Robert Mustacchi                _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
15014d9fdb4Robert Mustacchi                return DW_DLV_ERROR;
15024d9fdb4Robert Mustacchi            }
15034d9fdb4Robert Mustacchi            encoding = *(unsigned char *) cur_aug_p;
15044d9fdb4Robert Mustacchi            *pers_hand_enc_out = encoding;
15054d9fdb4Robert Mustacchi            ++cur_aug_p;
15064d9fdb4Robert Mustacchi            if (cur_aug_p > end_aug_p) {
15074d9fdb4Robert Mustacchi                _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);