107dc194Richard Lowe/*
207dc194Richard Lowe
307dc194Richard Lowe  Copyright (C) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
407dc194Richard Lowe  Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
507dc194Richard Lowe
607dc194Richard Lowe  This program is free software; you can redistribute it and/or modify it
707dc194Richard Lowe  under the terms of version 2.1 of the GNU Lesser General Public License
807dc194Richard Lowe  as published by the Free Software Foundation.
907dc194Richard Lowe
1007dc194Richard Lowe  This program is distributed in the hope that it would be useful, but
1107dc194Richard Lowe  WITHOUT ANY WARRANTY; without even the implied warranty of
1207dc194Richard Lowe  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1307dc194Richard Lowe
1407dc194Richard Lowe  Further, this software is distributed without any warranty that it is
1507dc194Richard Lowe  free of the rightful claim of any third person regarding infringement
1607dc194Richard Lowe  or the like.  Any license provided herein, whether implied or
1707dc194Richard Lowe  otherwise, applies only to this software file.  Patent licenses, if
1807dc194Richard Lowe  any, provided herein do not apply to combinations of this program with
1907dc194Richard Lowe  other software, or any other product whatsoever.
2007dc194Richard Lowe
2107dc194Richard Lowe  You should have received a copy of the GNU Lesser General Public
2207dc194Richard Lowe  License along with this program; if not, write the Free Software
2307dc194Richard Lowe  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2407dc194Richard Lowe  USA.
2507dc194Richard Lowe
2607dc194Richard Lowe  Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
2707dc194Richard Lowe  Mountain View, CA 94043, or:
2807dc194Richard Lowe
2907dc194Richard Lowe  http://www.sgi.com
3007dc194Richard Lowe
3107dc194Richard Lowe  For further information regarding this notice, see:
3207dc194Richard Lowe
3307dc194Richard Lowe  http://oss.sgi.com/projects/GenInfo/NoticeExplan
3407dc194Richard Lowe
3507dc194Richard Lowe*/
3607dc194Richard Lowe/* The address of the Free Software Foundation is
3707dc194Richard Lowe   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
3807dc194Richard Lowe   Boston, MA 02110-1301, USA.
3907dc194Richard Lowe   SGI has moved from the Crittenden Lane address.
4007dc194Richard Lowe*/
4107dc194Richard Lowe
4207dc194Richard Lowe
4307dc194Richard Lowe/*
4407dc194Richard Lowe        This  implements _dwarf_get_fde_list_internal()
4507dc194Richard Lowe        and related helper functions for reading cie/fde data.
4607dc194Richard Lowe*/
4707dc194Richard Lowe
4807dc194Richard Lowe
4907dc194Richard Lowe
5007dc194Richard Lowe#include "config.h"
5107dc194Richard Lowe#include "dwarf_incl.h"
5207dc194Richard Lowe#include <stdio.h>
5307dc194Richard Lowe#include <stdlib.h>
5407dc194Richard Lowe#include <sys/types.h>
5507dc194Richard Lowe#include "dwarf_frame.h"
5607dc194Richard Lowe#include "dwarf_arange.h"       /* using Arange as a way to build a
5707dc194Richard Lowe                                   list */
5807dc194Richard Lowe
5907dc194Richard Lowe
6007dc194Richard Lowestatic int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
6107dc194Richard Lowe                                       Dwarf_Cie cur_cie_ptr,
6207dc194Richard Lowe                                       Dwarf_Cie * cie_ptr_to_use_out,
6307dc194Richard Lowe                                       Dwarf_Cie head_cie_ptr);
6407dc194Richard Lowestatic void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
6507dc194Richard Lowe                                          Dwarf_Cie head_cie_ptr);
6607dc194Richard Lowestatic int dwarf_create_cie_from_start(Dwarf_Debug dbg,
6707dc194Richard Lowe                                       Dwarf_Small * cie_ptr_val,
6807dc194Richard Lowe                                       Dwarf_Small * section_ptr,
6907dc194Richard Lowe                                       Dwarf_Unsigned section_index,
7007dc194Richard Lowe                                       Dwarf_Unsigned section_length,
7107dc194Richard Lowe                                       Dwarf_Small * frame_ptr_end,
7207dc194Richard Lowe                                       Dwarf_Unsigned cie_id_value,
7307dc194Richard Lowe                                       Dwarf_Unsigned cie_count,
7407dc194Richard Lowe                                       int use_gnu_cie_calc,
7507dc194Richard Lowe                                       Dwarf_Cie * cie_ptr_to_use_out,
7607dc194Richard Lowe                                       Dwarf_Error * error);
7707dc194Richard Lowe
7807dc194Richard Lowestatic Dwarf_Small *get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
7907dc194Richard Lowe                                            int use_gnu_cie_calc,
8007dc194Richard Lowe                                            Dwarf_Small * section_ptr,
8107dc194Richard Lowe                                            Dwarf_Small * cie_id_addr);
8207dc194Richard Lowestatic int get_gcc_eh_augmentation(Dwarf_Debug dbg,
8307dc194Richard Lowe                                   Dwarf_Small * frame_ptr,
8407dc194Richard Lowe                                   unsigned long
8507dc194Richard Lowe                                   *size_of_augmentation_data,
8607dc194Richard Lowe                                   enum Dwarf_augmentation_type augtype,
8707dc194Richard Lowe                                   Dwarf_Small * section_pointer,
8807dc194Richard Lowe                                   Dwarf_Small * fde_eh_encoding_out,
8907dc194Richard Lowe                                   char *augmentation);
9007dc194Richard Lowe
9107dc194Richard Lowestatic int
9207dc194Richard Lowe  gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
9307dc194Richard Lowe                    Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
9407dc194Richard Lowe                    Dwarf_Half address_size,
9507dc194Richard Lowe                    unsigned char *pers_hand_enc_out,
9607dc194Richard Lowe                    unsigned char *lsda_enc_out,
9707dc194Richard Lowe                    unsigned char *fde_begin_enc_out,
9807dc194Richard Lowe                    Dwarf_Addr * gnu_pers_addr_out);
9907dc194Richard Lowe
10007dc194Richard Lowe
10107dc194Richard Lowestatic int read_encoded_ptr(Dwarf_Debug dbg,
10207dc194Richard Lowe                            Dwarf_Small * section_pointer,
10307dc194Richard Lowe                            Dwarf_Small * input_field,
10407dc194Richard Lowe                            int gnu_encoding,
10507dc194Richard Lowe                            Dwarf_Half address_size,
10607dc194Richard Lowe                            Dwarf_Unsigned * addr,
10707dc194Richard Lowe                            Dwarf_Small ** input_field_out);
10807dc194Richard Lowe
10907dc194Richard Lowe
11007dc194Richard Lowe
11107dc194Richard Lowestatic int qsort_compare(const void *elem1, const void *elem2);
11207dc194Richard Lowe
11307dc194Richard Lowe
11407dc194Richard Lowe/* Adds 'newone' to the end of the list starting at 'head'
11507dc194Richard Lowe   and makes the new one 'cur'rent. */
11607dc194Richard Lowestatic void
11707dc194Richard Lowechain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
11807dc194Richard Lowe{
11907dc194Richard Lowe    if (*head == NULL)
12007dc194Richard Lowe        *head = newone;
12107dc194Richard Lowe    else {
12207dc194Richard Lowe        (*cur)->fd_next = newone;
12307dc194Richard Lowe    }
12407dc194Richard Lowe    *cur = newone;
12507dc194Richard Lowe
12607dc194Richard Lowe}
12707dc194Richard Lowe
12807dc194Richard Lowe/* Adds 'newone' to the end of the list starting at 'head'
12907dc194Richard Lowe   and makes the new one 'cur'rent. */
13007dc194Richard Lowestatic void
13107dc194Richard Lowechain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
13207dc194Richard Lowe{
13307dc194Richard Lowe    if (*head == NULL) {
13407dc194Richard Lowe        *head = newone;
13507dc194Richard Lowe    } else {
13607dc194Richard Lowe        (*cur)->ci_next = newone;
13707dc194Richard Lowe    }
13807dc194Richard Lowe    *cur = newone;
13907dc194Richard Lowe}
14007dc194Richard Lowe
14107dc194Richard Lowe/* The size of the length field plus the
14207dc194Richard Lowe    value of length must be an integral
14307dc194Richard Lowe    multiple of the address size.  Dwarf4 standard.
14407dc194Richard Lowe
14507dc194Richard Lowe    A constant that gives the number of bytes of the CIE
14607dc194Richard Lowe    structure, not including the length field itself
14707dc194Richard Lowe    (where length mod <size of an address> == 0)
14807dc194Richard Lowe    (see Section 7.2.2). Dwarf3 standard.
14907dc194Richard Lowe
15007dc194Richard Lowe    A uword constant that gives the number of bytes of
15107dc194Richard Lowe    the CIE structure, not including the
15207dc194Richard Lowe    length field, itself (length mod <addressing unit size> == 0).
15307dc194Richard Lowe    Dwarf2 standard.*/
15407dc194Richard Lowestatic void
15507dc194Richard Lowevalidate_length(Dwarf_Debug dbg,
15607dc194Richard Lowe    Dwarf_Cie cieptr, Dwarf_Unsigned length,
15707dc194Richard Lowe    Dwarf_Unsigned length_size,
15807dc194Richard Lowe    Dwarf_Unsigned extension_size,
15907dc194Richard Lowe    Dwarf_Small * section_ptr,
16007dc194Richard Lowe    Dwarf_Small * ciefde_start,
16107dc194Richard Lowe    const char * cieorfde)
16207dc194Richard Lowe{
16307dc194Richard Lowe    Dwarf_Unsigned address_size = cieptr->ci_address_size;
16407dc194Richard Lowe    Dwarf_Unsigned length_field_summed = length_size + extension_size;
16507dc194Richard Lowe    Dwarf_Unsigned total_len = length + length_field_summed;
16607dc194Richard Lowe    Dwarf_Unsigned mod = total_len % address_size;
16707dc194Richard Lowe
16807dc194Richard Lowe    if (mod != 0) {
16907dc194Richard Lowe        char msg[DW_HARMLESS_ERROR_MSG_STRING_SIZE];
17007dc194Richard Lowe        Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
17107dc194Richard Lowe        snprintf(msg,sizeof(msg),
17207dc194Richard Lowe            "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
17307dc194Richard Lowe            " len=0x%" DW_PR_DUx
17407dc194Richard Lowe            ", len size=0x%" DW_PR_DUx
17507dc194Richard Lowe            ", extn size=0x%" DW_PR_DUx
17607dc194Richard Lowe            ", totl length=0x%" DW_PR_DUx
17707dc194Richard Lowe            ", addr size=0x%" DW_PR_DUx
17807dc194Richard Lowe            ", mod=0x%" DW_PR_DUx " must be zero"
17907dc194Richard Lowe            " in %s"
18007dc194Richard Lowe            ", offset 0x%" DW_PR_DUx ".",
18107dc194Richard Lowe            length,
18207dc194Richard Lowe            length_size,
18307dc194Richard Lowe            extension_size,
18407dc194Richard Lowe            total_len,address_size, mod,
18507dc194Richard Lowe            cieorfde,
18607dc194Richard Lowe            sectionoffset);
18707dc194Richard Lowe        dwarf_insert_harmless_error(dbg,msg);
18807dc194Richard Lowe    }
18907dc194Richard Lowe    return;
19007dc194Richard Lowe}
19107dc194Richard Lowe
19207dc194Richard Lowe
19307dc194Richard Lowe#if 0
19407dc194Richard Lowe/* For debugging only. */
19507dc194Richard Lowestatic void
19607dc194Richard Loweprint_prefix(struct cie_fde_prefix_s *prefix, int line)
19707dc194Richard Lowe{
19807dc194Richard Lowe    printf("prefix-print, prefix at 0x%lx, line %d\n",
19907dc194Richard Lowe           (long) prefix, line);
20007dc194Richard Lowe    printf("  start addr 0x%lx after prefix 0x%lx\n",
20107dc194Richard Lowe           (long) prefix->cf_start_addr,
20207dc194Richard Lowe           (long) prefix->cf_addr_after_prefix);
20307dc194Richard Lowe    printf("  length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
20407dc194Richard Lowe           (Dwarf_Unsigned) prefix->cf_length,
20507dc194Richard Lowe           prefix->cf_local_length_size,
20607dc194Richard Lowe           prefix->cf_local_extension_size);
20707dc194Richard Lowe    printf("  cie_id 0x%" DW_PR_DUx " cie_id  cie_id_addr 0x%lx\n",
20807dc194Richard Lowe           (Dwarf_Unsigned) prefix->cf_cie_id,
20907dc194Richard Lowe           (long) prefix->cf_cie_id_addr);
21007dc194Richard Lowe    printf
21107dc194Richard Lowe        ("  sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
21207dc194Richard Lowe         (long) prefix->cf_section_ptr,
21307dc194Richard Lowe         (Dwarf_Signed) prefix->cf_section_index,
21407dc194Richard Lowe         (Dwarf_Unsigned) prefix->cf_section_length,
21507dc194Richard Lowe         (long) prefix->cf_section_ptr + prefix->cf_section_length);
21607dc194Richard Lowe}
21707dc194Richard Lowe#endif
21807dc194Richard Lowe
21907dc194Richard Lowe
22007dc194Richard Lowe
22107dc194Richard Lowe/* Internal function called from various places to create
22207dc194Richard Lowe   lists of CIEs and FDEs.  Not directly called
22307dc194Richard Lowe   by consumer code */
22407dc194Richard Loweint
22507dc194Richard Lowe_dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
22607dc194Richard Lowe    Dwarf_Signed * cie_element_count,
22707dc194Richard Lowe    Dwarf_Fde ** fde_data,
22807dc194Richard Lowe    Dwarf_Signed * fde_element_count,
22907dc194Richard Lowe    Dwarf_Small * section_ptr,
23007dc194Richard Lowe    Dwarf_Unsigned section_index,
23107dc194Richard Lowe    Dwarf_Unsigned section_length,
23207dc194Richard Lowe    Dwarf_Unsigned cie_id_value,
23307dc194Richard Lowe    int use_gnu_cie_calc, Dwarf_Error * error)
23407dc194Richard Lowe{
23507dc194Richard Lowe    /* Scans the debug_frame section. */
23607dc194Richard Lowe    Dwarf_Small *frame_ptr = section_ptr;
23707dc194Richard Lowe    Dwarf_Small *frame_ptr_end = section_ptr + section_length;
23807dc194Richard Lowe
23907dc194Richard Lowe
24007dc194Richard Lowe
24107dc194Richard Lowe    /*
24207dc194Richard Lowe       New_cie points to the Cie being read, and head_cie_ptr and
24307dc194Richard Lowe       cur_cie_ptr are used for chaining them up in sequence.
24407dc194Richard Lowe       In case cie's are reused aggressively we need tail_cie_ptr
24507dc194Richard Lowe       to add to the chain.  If we re-use an early cie
24607dc194Richard Lowe       later on, that does not mean we chain a new cie to the early one,
24707dc194Richard Lowe       we always chain it to the tail.  */
24807dc194Richard Lowe    Dwarf_Cie head_cie_ptr = NULL;
24907dc194Richard Lowe    Dwarf_Cie cur_cie_ptr = NULL;
25007dc194Richard Lowe    Dwarf_Cie tail_cie_ptr = NULL;
25107dc194Richard Lowe    Dwarf_Word cie_count = 0;
25207dc194Richard Lowe
25307dc194Richard Lowe    /*
25407dc194Richard Lowe       Points to a list of contiguous pointers to Dwarf_Cie structures.
25507dc194Richard Lowe     */
25607dc194Richard Lowe    Dwarf_Cie *cie_list_ptr = 0;
25707dc194Richard Lowe
25807dc194Richard Lowe
25907dc194Richard Lowe    /*
26007dc194Richard Lowe       New_fde points to the Fde being created, and head_fde_ptr and
26107dc194Richard Lowe       cur_fde_ptr are used to chain them up. */
26207dc194Richard Lowe    Dwarf_Fde head_fde_ptr = NULL;
26307dc194Richard Lowe    Dwarf_Fde cur_fde_ptr = NULL;
26407dc194Richard Lowe    Dwarf_Word fde_count = 0;
26507dc194Richard Lowe
26607dc194Richard Lowe    /*
26707dc194Richard Lowe       Points to a list of contiguous pointers to Dwarf_Fde structures.
26807dc194Richard Lowe     */
26907dc194Richard Lowe    Dwarf_Fde *fde_list_ptr = NULL;
27007dc194Richard Lowe
27107dc194Richard Lowe    Dwarf_Word i = 0;
27207dc194Richard Lowe    int res = DW_DLV_ERROR;
27307dc194Richard Lowe
27407dc194Richard Lowe    if (frame_ptr == 0) {
27507dc194Richard Lowe        return DW_DLV_NO_ENTRY;
27607dc194Richard Lowe    }
27707dc194Richard Lowe
27807dc194Richard Lowe    /* We create the fde and cie arrays. Processing each CIE as we come
27907dc194Richard Lowe       to it or as an FDE refers to it.  We cannot process 'late' CIEs
28007dc194Richard Lowe       late as GNU .eh_frame complexities mean we need the whole CIE
28107dc194Richard Lowe       before we can process the FDE correctly. */
28207dc194Richard Lowe    while (frame_ptr < frame_ptr_end) {
28307dc194Richard Lowe
28407dc194Richard Lowe        struct cie_fde_prefix_s prefix;
28507dc194Richard Lowe
28607dc194Richard Lowe        /* First read in the 'common prefix' to figure out what we are
28707dc194Richard Lowe           to do with this entry. */
28807dc194Richard Lowe        memset(&prefix, 0, sizeof(prefix));
28907dc194Richard Lowe        res = dwarf_read_cie_fde_prefix(dbg,
29007dc194Richard Lowe                                        frame_ptr, section_ptr,
29107dc194Richard Lowe                                        section_index,
29207dc194Richard Lowe                                        section_length, &prefix, error);
29307dc194Richard Lowe        if (res == DW_DLV_ERROR) {
29407dc194Richard Lowe            dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
29507dc194Richard Lowe            return res;
29607dc194Richard Lowe        }
29707dc194Richard Lowe        if (res == DW_DLV_NO_ENTRY)
29807dc194Richard Lowe            break;
29907dc194Richard Lowe        frame_ptr = prefix.cf_addr_after_prefix;
30007dc194Richard Lowe        if (frame_ptr >= frame_ptr_end) {
30107dc194Richard Lowe            dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
30207dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
30307dc194Richard Lowe            return DW_DLV_ERROR;
30407dc194Richard Lowe
30507dc194Richard Lowe        }
30607dc194Richard Lowe
30707dc194Richard Lowe        if (prefix.cf_cie_id == cie_id_value) {
30807dc194Richard Lowe            /* This is a CIE.  */
30907dc194Richard Lowe            Dwarf_Cie cie_ptr_to_use = 0;
31007dc194Richard Lowe
31107dc194Richard Lowe            int res = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
31207dc194Richard Lowe                                                  cur_cie_ptr,
31307dc194Richard Lowe                                                  &cie_ptr_to_use,
31407dc194Richard Lowe                                                  head_cie_ptr);
31507dc194Richard Lowe
31607dc194Richard Lowe            if (res == DW_DLV_OK) {
31707dc194Richard Lowe                cur_cie_ptr = cie_ptr_to_use;
31807dc194Richard Lowe                /* Ok. Seen already. */
31907dc194Richard Lowe            } else if (res == DW_DLV_NO_ENTRY) {
32007dc194Richard Lowe                /* CIE before its FDE in this case. */
32107dc194Richard Lowe                res = dwarf_create_cie_from_after_start(dbg,
32207dc194Richard Lowe                                                        &prefix,
32307dc194Richard Lowe                                                        section_ptr,
32407dc194Richard Lowe                                                        frame_ptr,
32507dc194Richard Lowe                                                        cie_count,
32607dc194Richard Lowe                                                        use_gnu_cie_calc,
32707dc194Richard Lowe                                                        &cie_ptr_to_use,
32807dc194Richard Lowe                                                        error);
32907dc194Richard Lowe                /* ASSERT: res==DW_DLV_NO_ENTRY impossible. */
33007dc194Richard Lowe                if (res == DW_DLV_ERROR) {
33107dc194Richard Lowe                    dealloc_fde_cie_list_internal(head_fde_ptr,
33207dc194Richard Lowe                                                  head_cie_ptr);
33307dc194Richard Lowe                    return res;
33407dc194Richard Lowe                }
33507dc194Richard Lowe                /* ASSERT res != DW_DLV_NO_ENTRY */
33607dc194Richard Lowe                cie_count++;
33707dc194Richard Lowe                chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
33807dc194Richard Lowe                             &tail_cie_ptr);
33907dc194Richard Lowe                cur_cie_ptr = tail_cie_ptr;
34007dc194Richard Lowe            } else {            /* res == DW_DLV_ERROR */
34107dc194Richard Lowe
34207dc194Richard Lowe                dealloc_fde_cie_list_internal(head_fde_ptr,
34307dc194Richard Lowe                                              head_cie_ptr);
34407dc194Richard Lowe                return res;
34507dc194Richard Lowe            }
34607dc194Richard Lowe            frame_ptr = cie_ptr_to_use->ci_cie_start +
34707dc194Richard Lowe                cie_ptr_to_use->ci_length +
34807dc194Richard Lowe                cie_ptr_to_use->ci_length_size +
34907dc194Richard Lowe                cie_ptr_to_use->ci_extension_size;
35007dc194Richard Lowe            continue;
35107dc194Richard Lowe        } else {
35207dc194Richard Lowe            /* this is an FDE, Frame Description Entry, see the Dwarf
35307dc194Richard Lowe               Spec, section 6.4.1 */
35407dc194Richard Lowe            int res = DW_DLV_ERROR;
35507dc194Richard Lowe            Dwarf_Cie cie_ptr_to_use = 0;
35607dc194Richard Lowe            Dwarf_Fde fde_ptr_to_use = 0;
35707dc194Richard Lowe
35807dc194Richard Lowe            /* Do not call this twice on one prefix, as
35907dc194Richard Lowe               prefix.cf_cie_id_addr is altered as a side effect. */
36007dc194Richard Lowe            Dwarf_Small *cieptr_val =
36107dc194Richard Lowe                get_cieptr_given_offset(prefix.cf_cie_id,
36207dc194Richard Lowe                                        use_gnu_cie_calc,
36307dc194Richard Lowe                                        section_ptr,
36407dc194Richard Lowe                                        prefix.cf_cie_id_addr);
36507dc194Richard Lowe
36607dc194Richard Lowe            res = dwarf_find_existing_cie_ptr(cieptr_val,
36707dc194Richard Lowe                                              cur_cie_ptr,
36807dc194Richard Lowe                                              &cie_ptr_to_use,
36907dc194Richard Lowe                                              head_cie_ptr);
37007dc194Richard Lowe            if (res == DW_DLV_OK) {
37107dc194Richard Lowe                cur_cie_ptr = cie_ptr_to_use;
37207dc194Richard Lowe                /* Ok. Seen CIE already. */
37307dc194Richard Lowe            } else if (res == DW_DLV_NO_ENTRY) {
37407dc194Richard Lowe                res = dwarf_create_cie_from_start(dbg,
37507dc194Richard Lowe                                                  cieptr_val,
37607dc194Richard Lowe                                                  section_ptr,
37707dc194Richard Lowe                                                  section_index,
37807dc194Richard Lowe                                                  section_length,
37907dc194Richard Lowe                                                  frame_ptr_end,
38007dc194Richard Lowe                                                  cie_id_value,
38107dc194Richard Lowe                                                  cie_count,
38207dc194Richard Lowe                                                  use_gnu_cie_calc,
38307dc194Richard Lowe                                                  &cie_ptr_to_use,
38407dc194Richard Lowe                                                  error);
38507dc194Richard Lowe                if (res == DW_DLV_ERROR) {
38607dc194Richard Lowe                    dealloc_fde_cie_list_internal(head_fde_ptr,
38707dc194Richard Lowe                                                  head_cie_ptr);
38807dc194Richard Lowe                    return res;
38907dc194Richard Lowe                } else if (res == DW_DLV_NO_ENTRY) {
39007dc194Richard Lowe                    return res;
39107dc194Richard Lowe                }
39207dc194Richard Lowe                ++cie_count;
39307dc194Richard Lowe                chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
39407dc194Richard Lowe                             &tail_cie_ptr);
39507dc194Richard Lowe                cur_cie_ptr = tail_cie_ptr;
39607dc194Richard Lowe
39707dc194Richard Lowe            } else {
39807dc194Richard Lowe                /* DW_DLV_ERROR */
39907dc194Richard Lowe                return res;
40007dc194Richard Lowe            }
40107dc194Richard Lowe
40207dc194Richard Lowe            res = dwarf_create_fde_from_after_start(dbg,
40307dc194Richard Lowe                                                    &prefix,
40407dc194Richard Lowe                                                    section_ptr,
40507dc194Richard Lowe                                                    frame_ptr,
40607dc194Richard Lowe                                                    use_gnu_cie_calc,
40707dc194Richard Lowe                                                    cie_ptr_to_use,
40807dc194Richard Lowe                                                    &fde_ptr_to_use,
40907dc194Richard Lowe                                                    error);
41007dc194Richard Lowe            if (res == DW_DLV_ERROR) {
41107dc194Richard Lowe                return res;
41207dc194Richard Lowe            }
41307dc194Richard Lowe            chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
41407dc194Richard Lowe            fde_count++;
41507dc194Richard Lowe            /* ASSERT: DW_DLV_OK. */
41607dc194Richard Lowe            frame_ptr = fde_ptr_to_use->fd_fde_start +
41707dc194Richard Lowe                fde_ptr_to_use->fd_length +
41807dc194Richard Lowe                fde_ptr_to_use->fd_length_size +
41907dc194Richard Lowe                fde_ptr_to_use->fd_extension_size;
42007dc194Richard Lowe            continue;
42107dc194Richard Lowe
42207dc194Richard Lowe        }
42307dc194Richard Lowe
42407dc194Richard Lowe    }
42507dc194Richard Lowe
42607dc194Richard Lowe    /* Now build list of CIEs from the list. If there are no CIEs
42707dc194Richard Lowe       there should be no FDEs. */
42807dc194Richard Lowe    if (cie_count > 0) {
42907dc194Richard Lowe        cie_list_ptr = (Dwarf_Cie *)
43007dc194Richard Lowe            _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
43107dc194Richard Lowe    } else {
43207dc194Richard Lowe        if(fde_count > 0) {
43307dc194Richard Lowe            dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
43407dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
43507dc194Richard Lowe            return DW_DLV_ERROR;
43607dc194Richard Lowe        }
43707dc194Richard Lowe        dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
43807dc194Richard Lowe        return DW_DLV_NO_ENTRY;
43907dc194Richard Lowe    }
44007dc194Richard Lowe    if (cie_list_ptr == NULL) {
44107dc194Richard Lowe        dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
44207dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
44307dc194Richard Lowe        return DW_DLV_ERROR;
44407dc194Richard Lowe    }
44507dc194Richard Lowe    cur_cie_ptr = head_cie_ptr;
44607dc194Richard Lowe    for (i = 0; i < cie_count; i++) {
44707dc194Richard Lowe        *(cie_list_ptr + i) = cur_cie_ptr;
44807dc194Richard Lowe        cur_cie_ptr = cur_cie_ptr->ci_next;
44907dc194Richard Lowe    }
45007dc194Richard Lowe
45107dc194Richard Lowe
45207dc194Richard Lowe
45307dc194Richard Lowe    /* Now build array of FDEs from the list.
45407dc194Richard Lowe       With orphan CIEs (meaning no FDEs) lets not return DW_DLV_NO_ENTRY */
45507dc194Richard Lowe    if (fde_count > 0) {
45607dc194Richard Lowe        fde_list_ptr = (Dwarf_Fde *)
45707dc194Richard Lowe            _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
45807dc194Richard Lowe    }
45907dc194Richard Lowe
46007dc194Richard Lowe    /* It is ok if fde_list_ptr is NULL, we just have no fdes. */
46107dc194Richard Lowe    cur_fde_ptr = head_fde_ptr;
46207dc194Richard Lowe    for (i = 0; i < fde_count; i++) {
46307dc194Richard Lowe        *(fde_list_ptr + i) = cur_fde_ptr;
46407dc194Richard Lowe        cur_fde_ptr = cur_fde_ptr->fd_next;
46507dc194Richard Lowe    }
46607dc194Richard Lowe
46707dc194Richard Lowe
46807dc194Richard Lowe    /* Return arguments. */
46907dc194Richard Lowe    *cie_data = cie_list_ptr;
47007dc194Richard Lowe    *cie_element_count = cie_count;
47107dc194Richard Lowe
47207dc194Richard Lowe    *fde_data = fde_list_ptr;
47307dc194Richard Lowe    *fde_element_count = fde_count;
47407dc194Richard Lowe    if(use_gnu_cie_calc) {
47507dc194Richard Lowe      dbg->de_fde_data_eh = fde_list_ptr;
47607dc194Richard Lowe      dbg->de_fde_count_eh = fde_count;
47707dc194Richard Lowe      dbg->de_cie_data_eh = cie_list_ptr;
47807dc194Richard Lowe      dbg->de_cie_count_eh = cie_count;
47907dc194Richard Lowe    } else {
48007dc194Richard Lowe      dbg->de_fde_data = fde_list_ptr;
48107dc194Richard Lowe      dbg->de_fde_count = fde_count;
48207dc194Richard Lowe      dbg->de_cie_data = cie_list_ptr;
48307dc194Richard Lowe      dbg->de_cie_count = cie_count;
48407dc194Richard Lowe    }
48507dc194Richard Lowe
48607dc194Richard Lowe    /* Sort the list by the address so that dwarf_get_fde_at_pc() can
48707dc194Richard Lowe       binary search this list.  */
48807dc194Richard Lowe    if(fde_count > 0) {
48907dc194Richard Lowe        qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
49007dc194Richard Lowe           qsort_compare);
49107dc194Richard Lowe    }
49207dc194Richard Lowe
49307dc194Richard Lowe    return (DW_DLV_OK);
49407dc194Richard Lowe}
49507dc194Richard Lowe
49607dc194Richard Lowe/* Internal function, not called by consumer code.
49707dc194Richard Lowe   'prefix' has accumulated the info up thru the cie-id
49807dc194Richard Lowe   and now we consume the rest and build a Dwarf_Cie_s structure.
49907dc194Richard Lowe*/
50007dc194Richard Loweint
50107dc194Richard Lowedwarf_create_cie_from_after_start(Dwarf_Debug dbg,
50207dc194Richard Lowe    struct cie_fde_prefix_s *prefix,
50307dc194Richard Lowe    Dwarf_Small * section_pointer,
50407dc194Richard Lowe    Dwarf_Small * frame_ptr,
50507dc194Richard Lowe    Dwarf_Unsigned cie_count,
50607dc194Richard Lowe    int use_gnu_cie_calc,
50707dc194Richard Lowe    Dwarf_Cie * cie_ptr_out,
50807dc194Richard Lowe    Dwarf_Error * error)
50907dc194Richard Lowe{
51007dc194Richard Lowe    Dwarf_Cie new_cie = 0;
51107dc194Richard Lowe
51207dc194Richard Lowe    /* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
51307dc194Richard Lowe       -1 (in .debug_frame). .eh_frame not quite identical to
51407dc194Richard Lowe       .debug_frame */
51507dc194Richard Lowe    /* We here default the address size as it is not present
51607dc194Richard Lowe       in DWARF2 or DWARF3 cie data, below we set it right if
51707dc194Richard Lowe       it is present. */
51807dc194Richard Lowe    Dwarf_Half address_size = dbg->de_pointer_size;
51907dc194Richard Lowe    Dwarf_Small eh_fde_encoding = 0;
52007dc194Richard Lowe    Dwarf_Small *augmentation = 0;
52107dc194Richard Lowe    Dwarf_Half segment_size = 0;
52207dc194Richard Lowe    Dwarf_Sword data_alignment_factor = -1;
52307dc194Richard Lowe    Dwarf_Word code_alignment_factor = 4;
52407dc194Richard Lowe    Dwarf_Unsigned return_address_register = 31;
52507dc194Richard Lowe    int local_length_size = 0;
52607dc194Richard Lowe    Dwarf_Word leb128_length = 0;
52707dc194Richard Lowe    Dwarf_Unsigned cie_aug_data_len = 0;
52807dc194Richard Lowe    Dwarf_Small *cie_aug_data = 0;
52907dc194Richard Lowe    Dwarf_Addr gnu_personality_handler_addr = 0;
53007dc194Richard Lowe    unsigned char gnu_personality_handler_encoding = 0;
53107dc194Richard Lowe    unsigned char gnu_lsda_encoding = 0;
53207dc194Richard Lowe    unsigned char gnu_fde_begin_encoding = 0;
53307dc194Richard Lowe
53407dc194Richard Lowe
53507dc194Richard Lowe    enum Dwarf_augmentation_type augt = aug_unknown;
53607dc194Richard Lowe
53707dc194Richard Lowe
53807dc194Richard Lowe    /* this is a CIE, Common Information Entry: See the dwarf spec,
53907dc194Richard Lowe       section 6.4.1 */
54007dc194Richard Lowe    Dwarf_Small version = *(Dwarf_Small *) frame_ptr;
54107dc194Richard Lowe
54207dc194Richard Lowe    frame_ptr++;
54307dc194Richard Lowe    if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
54407dc194Richard Lowe        version != DW_CIE_VERSION4) {
54507dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
54607dc194Richard Lowe        return (DW_DLV_ERROR);
54707dc194Richard Lowe    }
54807dc194Richard Lowe
54907dc194Richard Lowe    augmentation = frame_ptr;
55007dc194Richard Lowe    frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
55107dc194Richard Lowe    augt = _dwarf_get_augmentation_type(dbg,
55207dc194Richard Lowe                                        augmentation, use_gnu_cie_calc);
55307dc194Richard Lowe    if (augt == aug_eh) {
55407dc194Richard Lowe        /* REFERENCED *//* Not used in this instance */
55507dc194Richard Lowe        Dwarf_Unsigned exception_table_addr;
55607dc194Richard Lowe
55707dc194Richard Lowe        /* this is per egcs-1.1.2 as on RH 6.0 */
55807dc194Richard Lowe        READ_UNALIGNED(dbg, exception_table_addr,
55907dc194Richard Lowe                       Dwarf_Unsigned, frame_ptr, local_length_size);
56007dc194Richard Lowe        frame_ptr += local_length_size;
56107dc194Richard Lowe    }
56207dc194Richard Lowe    {
56307dc194Richard Lowe        Dwarf_Unsigned lreg = 0;
56407dc194Richard Lowe        unsigned long size = 0;
56507dc194Richard Lowe
56607dc194Richard Lowe        if( version == DW_CIE_VERSION4) {
56707dc194Richard Lowe            address_size = *((unsigned char *)frame_ptr);
56807dc194Richard Lowe            ++frame_ptr;
56907dc194Richard Lowe            segment_size = *((unsigned char *)frame_ptr);
57007dc194Richard Lowe            ++frame_ptr;
57107dc194Richard Lowe        }
57207dc194Richard Lowe
57307dc194Richard Lowe        DECODE_LEB128_UWORD(frame_ptr, lreg);
57407dc194Richard Lowe        code_alignment_factor = (Dwarf_Word) lreg;
57507dc194Richard Lowe
57607dc194Richard Lowe        data_alignment_factor =
57707dc194Richard Lowe            (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
57807dc194Richard Lowe                                                 &leb128_length);
57907dc194Richard Lowe
58007dc194Richard Lowe        frame_ptr = frame_ptr + leb128_length;
58107dc194Richard Lowe
58207dc194Richard Lowe        return_address_register =
58307dc194Richard Lowe            _dwarf_get_return_address_reg(frame_ptr, version, &size);
58407dc194Richard Lowe        if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
58507dc194Richard Lowe            _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
58607dc194Richard Lowe            return (DW_DLV_ERROR);
58707dc194Richard Lowe        }
58807dc194Richard Lowe        frame_ptr += size;
58907dc194Richard Lowe    }
59007dc194Richard Lowe    switch (augt) {
59107dc194Richard Lowe    case aug_empty_string:
59207dc194Richard Lowe        break;
59307dc194Richard Lowe    case aug_irix_mti_v1:
59407dc194Richard Lowe        break;
59507dc194Richard Lowe    case aug_irix_exception_table:{
59607dc194Richard Lowe            Dwarf_Unsigned lreg = 0;
59707dc194Richard Lowe            Dwarf_Word length_of_augmented_fields;
59807dc194Richard Lowe
59907dc194Richard Lowe            /* Decode the length of augmented fields. */
60007dc194Richard Lowe            DECODE_LEB128_UWORD(frame_ptr, lreg);
60107dc194Richard Lowe            length_of_augmented_fields = (Dwarf_Word) lreg;
60207dc194Richard Lowe
60307dc194Richard Lowe
60407dc194Richard Lowe            /* set the frame_ptr to point at the instruction start. */
60507dc194Richard Lowe            frame_ptr += length_of_augmented_fields;
60607dc194Richard Lowe        }
60707dc194Richard Lowe        break;
60807dc194Richard Lowe
60907dc194Richard Lowe    case aug_eh:{
61007dc194Richard Lowe
61107dc194Richard Lowe            int err = 0;
61207dc194Richard Lowe            unsigned long increment = 0;
61307dc194Richard Lowe
61407dc194Richard Lowe            if (!use_gnu_cie_calc) {
61507dc194Richard Lowe                /* This should be impossible. */
61607dc194Richard Lowe                _dwarf_error(dbg, error,
61707dc194Richard Lowe                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
61807dc194Richard Lowe                return DW_DLV_ERROR;
61907dc194Richard Lowe            }
62007dc194Richard Lowe
62107dc194Richard Lowe            err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
62207dc194Richard Lowe                                          augt,
62307dc194Richard Lowe                                          prefix->cf_section_ptr,
62407dc194Richard Lowe                                          &eh_fde_encoding,
62507dc194Richard Lowe                                          (char *) augmentation);
62607dc194Richard Lowe            if (err == DW_DLV_ERROR) {
62707dc194Richard Lowe                _dwarf_error(dbg, error,
62807dc194Richard Lowe                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
62907dc194Richard Lowe                return DW_DLV_ERROR;
63007dc194Richard Lowe            }
63107dc194Richard Lowe            frame_ptr += increment;
63207dc194Richard Lowe            break;
63307dc194Richard Lowe        }
63407dc194Richard Lowe    case aug_gcc_eh_z:{
63507dc194Richard Lowe            /* Here we have Augmentation Data Length (uleb128) followed
63607dc194Richard Lowe               by Augmentation Data bytes. */
63707dc194Richard Lowe            int res = DW_DLV_ERROR;
63807dc194Richard Lowe            Dwarf_Unsigned adlen = 0;
63907dc194Richard Lowe
64007dc194Richard Lowe            DECODE_LEB128_UWORD(frame_ptr, adlen);
64107dc194Richard Lowe            cie_aug_data_len = adlen;
64207dc194Richard Lowe            cie_aug_data = frame_ptr;
64307dc194Richard Lowe            res = gnu_aug_encodings(dbg,
64407dc194Richard Lowe                                    (char *) augmentation,
64507dc194Richard Lowe                                    cie_aug_data,
64607dc194Richard Lowe                                    cie_aug_data_len,
64707dc194Richard Lowe                                    address_size,
64807dc194Richard Lowe                                    &gnu_personality_handler_encoding,
64907dc194Richard Lowe                                    &gnu_lsda_encoding,
65007dc194Richard Lowe                                    &gnu_fde_begin_encoding,
65107dc194Richard Lowe                                    &gnu_personality_handler_addr);
65207dc194Richard Lowe            if (res != DW_DLV_OK) {
65307dc194Richard Lowe                _dwarf_error(dbg, error,
65407dc194Richard Lowe                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
65507dc194Richard Lowe                return res;
65607dc194Richard Lowe            }
65707dc194Richard Lowe
65807dc194Richard Lowe
65907dc194Richard Lowe            frame_ptr += adlen;
66007dc194Richard Lowe            break;
66107dc194Richard Lowe        }
66207dc194Richard Lowe    case aug_armcc:
66307dc194Richard Lowe        break;
66407dc194Richard Lowe    default:{
66507dc194Richard Lowe            /* We do not understand the augmentation string. No
66607dc194Richard Lowe               assumption can be made about any fields other than what
66707dc194Richard Lowe               we have already read. */
66807dc194Richard Lowe            frame_ptr = prefix->cf_start_addr +
66907dc194Richard Lowe                prefix->cf_length + prefix->cf_local_length_size
67007dc194Richard Lowe                + prefix->cf_local_extension_size;
67107dc194Richard Lowe            /* FIX -- What are the values of data_alignment_factor,
67207dc194Richard Lowe               code_alignement_factor, return_address_register and
67307dc194Richard Lowe               instruction start? They were clearly uninitalized in the
67407dc194Richard Lowe               previous version and I am leaving them the same way. */
67507dc194Richard Lowe            break;
67607dc194Richard Lowe        }
67707dc194Richard Lowe    }                           /* End switch on augmentation type. */
67807dc194Richard Lowe
67907dc194Richard Lowe    new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
68007dc194Richard Lowe    if (new_cie == NULL) {
68107dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
68207dc194Richard Lowe        return (DW_DLV_ERROR);
68307dc194Richard Lowe    }
68407dc194Richard Lowe
68507dc194Richard Lowe    new_cie->ci_cie_version_number = version;
68607dc194Richard Lowe    new_cie->ci_initial_table = NULL;
68707dc194Richard Lowe    new_cie->ci_length = (Dwarf_Word) prefix->cf_length;
68807dc194Richard Lowe    new_cie->ci_length_size = prefix->cf_local_length_size;
68907dc194Richard Lowe    new_cie->ci_extension_size = prefix->cf_local_extension_size;
69007dc194Richard Lowe    new_cie->ci_augmentation = (char *) augmentation;
69107dc194Richard Lowe
69207dc194Richard Lowe    new_cie->ci_data_alignment_factor =
69307dc194Richard Lowe        (Dwarf_Sbyte) data_alignment_factor;
69407dc194Richard Lowe    new_cie->ci_code_alignment_factor =
69507dc194Richard Lowe        (Dwarf_Small) code_alignment_factor;
69607dc194Richard Lowe    new_cie->ci_return_address_register = return_address_register;
69707dc194Richard Lowe    new_cie->ci_cie_start = prefix->cf_start_addr;
69807dc194Richard Lowe    new_cie->ci_cie_instr_start = frame_ptr;
69907dc194Richard Lowe    new_cie->ci_dbg = dbg;
70007dc194Richard Lowe    new_cie->ci_augmentation_type = augt;
70107dc194Richard Lowe    new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
70207dc194Richard Lowe    new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
70307dc194Richard Lowe    new_cie->ci_gnu_personality_handler_encoding =
70407dc194Richard Lowe        gnu_personality_handler_encoding;
70507dc194Richard Lowe    new_cie->ci_gnu_personality_handler_addr =
70607dc194Richard Lowe        gnu_personality_handler_addr;
70707dc194Richard Lowe    new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
70807dc194Richard Lowe    new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
70907dc194Richard Lowe
71007dc194Richard Lowe    new_cie->ci_index = cie_count;
71107dc194Richard Lowe    new_cie->ci_section_ptr = prefix->cf_section_ptr;
71207dc194Richard Lowe    /* The Following new in DWARF4 */
71307dc194Richard Lowe    new_cie->ci_address_size = address_size;
71407dc194Richard Lowe    new_cie->ci_segment_size = segment_size;
71507dc194Richard Lowe    validate_length(dbg,new_cie,new_cie->ci_length,
71607dc194Richard Lowe        new_cie->ci_length_size, new_cie->ci_extension_size,
71707dc194Richard Lowe        new_cie->ci_section_ptr,
71807dc194Richard Lowe        new_cie->ci_cie_start,"cie");
71907dc194Richard Lowe
72007dc194Richard Lowe    *cie_ptr_out = new_cie;
72107dc194Richard Lowe    return DW_DLV_OK;
72207dc194Richard Lowe
72307dc194Richard Lowe}
72407dc194Richard Lowe
72507dc194Richard Lowe
72607dc194Richard Lowe/* Internal function, not called by consumer code.
72707dc194Richard Lowe   'prefix' has accumulated the info up thru the cie-id
72807dc194Richard Lowe   and now we consume the rest and build a Dwarf_Fde_s structure.
72907dc194Richard Lowe*/
73007dc194Richard Lowe
73107dc194Richard Loweint
73207dc194Richard Lowedwarf_create_fde_from_after_start(Dwarf_Debug dbg,
73307dc194Richard Lowe    struct cie_fde_prefix_s *prefix,
73407dc194Richard Lowe    Dwarf_Small * section_pointer,
73507dc194Richard Lowe    Dwarf_Small * frame_ptr,
73607dc194Richard Lowe    int use_gnu_cie_calc,
73707dc194Richard Lowe    Dwarf_Cie cie_ptr_in,
73807dc194Richard Lowe    Dwarf_Fde * fde_ptr_out,
73907dc194Richard Lowe    Dwarf_Error * error)
74007dc194Richard Lowe{
74107dc194Richard Lowe    Dwarf_Fde new_fde = 0;
74207dc194Richard Lowe    Dwarf_Cie cieptr = cie_ptr_in;
74307dc194Richard Lowe    Dwarf_Small *saved_frame_ptr = 0;
74407dc194Richard Lowe
74507dc194Richard Lowe    Dwarf_Small *initloc = frame_ptr;
74607dc194Richard Lowe    Dwarf_Signed offset_into_exception_tables
74707dc194Richard Lowe        /* must be min dwarf_sfixed in size */
74807dc194Richard Lowe        = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
74907dc194Richard Lowe    Dwarf_Small *fde_aug_data = 0;
75007dc194Richard Lowe    Dwarf_Unsigned fde_aug_data_len = 0;
75107dc194Richard Lowe    Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
75207dc194Richard Lowe    Dwarf_Addr initial_location = 0;    /* must be min de_pointer_size
75307dc194Richard Lowe                                           bytes in size */
75407dc194Richard Lowe    Dwarf_Addr address_range = 0;       /* must be min de_pointer_size
75507dc194Richard Lowe                                           bytes in size */
75607dc194Richard Lowe    Dwarf_Half address_size = cie_ptr_in->ci_address_size;
75707dc194Richard Lowe
75807dc194Richard Lowe    enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type;
75907dc194Richard Lowe
76007dc194Richard Lowe    if (augt == aug_gcc_eh_z) {
76107dc194Richard Lowe        /* If z augmentation this is eh_frame, and initial_location and
76207dc194Richard Lowe           address_range in the FDE are read according to the CIE
76307dc194Richard Lowe           augmentation string instructions.  */
76407dc194Richard Lowe
76507dc194Richard Lowe        {
76607dc194Richard Lowe            Dwarf_Small *fp_updated = 0;
76707dc194Richard Lowe            int res = read_encoded_ptr(dbg,
76807dc194Richard Lowe                section_pointer,
76907dc194Richard Lowe                frame_ptr,
77007dc194Richard Lowe                cieptr-> ci_gnu_fde_begin_encoding,
77107dc194Richard Lowe                address_size,
77207dc194Richard Lowe                &initial_location,
77307dc194Richard Lowe                &fp_updated);
77407dc194Richard Lowe            if (res != DW_DLV_OK) {
77507dc194Richard Lowe                _dwarf_error(dbg, error,
77607dc194Richard Lowe                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
77707dc194Richard Lowe                return DW_DLV_ERROR;
77807dc194Richard Lowe            }
77907dc194Richard Lowe            frame_ptr = fp_updated;
78007dc194Richard Lowe            /* For the address-range it makes no sense to be
78107dc194Richard Lowe               pc-relative, so we turn it off with a section_pointer of
78207dc194Richard Lowe               NULL. Masking off DW_EH_PE_pcrel from the
78307dc194Richard Lowe               ci_gnu_fde_begin_encoding in this call would also work
78407dc194Richard Lowe               to turn off DW_EH_PE_pcrel. */
78507dc194Richard Lowe            res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
78607dc194Richard Lowe                                   frame_ptr,
78707dc194Richard Lowe                                   cieptr->ci_gnu_fde_begin_encoding,
78807dc194Richard Lowe                                   address_size,
78907dc194Richard Lowe                                   &address_range, &fp_updated);
79007dc194Richard Lowe            if (res != DW_DLV_OK) {
79107dc194Richard Lowe                _dwarf_error(dbg, error,
79207dc194Richard Lowe                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
79307dc194Richard Lowe                return DW_DLV_ERROR;
79407dc194Richard Lowe            }
79507dc194Richard Lowe            frame_ptr = fp_updated;
79607dc194Richard Lowe        }
79707dc194Richard Lowe        {
79807dc194Richard Lowe            Dwarf_Unsigned adlen = 0;
79907dc194Richard Lowe
80007dc194Richard Lowe            DECODE_LEB128_UWORD(frame_ptr, adlen);
80107dc194Richard Lowe            fde_aug_data_len = adlen;
80207dc194Richard Lowe            fde_aug_data = frame_ptr;
80307dc194Richard Lowe            frame_ptr += adlen;
80407dc194Richard Lowe        }
80507dc194Richard Lowe
80607dc194Richard Lowe    } else {
80707dc194Richard Lowe        READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
80807dc194Richard Lowe                       frame_ptr, address_size);
80907dc194Richard Lowe        frame_ptr += address_size;
81007dc194Richard Lowe
81107dc194Richard Lowe        READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
81207dc194Richard Lowe                       frame_ptr, address_size);
81307dc194Richard Lowe        frame_ptr += address_size;
81407dc194Richard Lowe    }
81507dc194Richard Lowe
81607dc194Richard Lowe
81707dc194Richard Lowe
81807dc194Richard Lowe
81907dc194Richard Lowe
82007dc194Richard Lowe    switch (augt) {
82107dc194Richard Lowe    case aug_irix_mti_v1:
82207dc194Richard Lowe    case aug_empty_string:
82307dc194Richard Lowe        break;
82407dc194Richard Lowe    case aug_irix_exception_table:{
82507dc194Richard Lowe            Dwarf_Unsigned lreg = 0;
82607dc194Richard Lowe            Dwarf_Word length_of_augmented_fields = 0;
82707dc194Richard Lowe
82807dc194Richard Lowe            DECODE_LEB128_UWORD(frame_ptr, lreg);
82907dc194Richard Lowe            length_of_augmented_fields = (Dwarf_Word) lreg;
83007dc194Richard Lowe
83107dc194Richard Lowe            saved_frame_ptr = frame_ptr;
83207dc194Richard Lowe            /* The first word is an offset into exception tables.
83307dc194Richard Lowe               Defined as a 32bit offset even for CC -64. */
83407dc194Richard Lowe            READ_UNALIGNED(dbg, offset_into_exception_tables,
83507dc194Richard Lowe                           Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed));
83607dc194Richard Lowe            SIGN_EXTEND(offset_into_exception_tables,
83707dc194Richard Lowe                        sizeof(Dwarf_sfixed));
83807dc194Richard Lowe            frame_ptr = saved_frame_ptr + length_of_augmented_fields;
83907dc194Richard Lowe        }
84007dc194Richard Lowe        break;
84107dc194Richard Lowe    case aug_eh:{
84207dc194Richard Lowe            Dwarf_Unsigned eh_table_value = 0;
84307dc194Richard Lowe
84407dc194Richard Lowe            if (!use_gnu_cie_calc) {
84507dc194Richard Lowe                /* This should be impossible. */
84607dc194Richard Lowe                _dwarf_error(dbg, error,
84707dc194Richard Lowe                             DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
84807dc194Richard Lowe                return DW_DLV_ERROR;
84907dc194Richard Lowe            }
85007dc194Richard Lowe
85107dc194Richard Lowe            /* gnu eh fde case. we do not need to do anything */
85207dc194Richard Lowe             /*REFERENCED*/     /* Not used in this instance of the
85307dc194Richard Lowe                                   macro */
85407dc194Richard Lowe                READ_UNALIGNED(dbg, eh_table_value,
85507dc194Richard Lowe                               Dwarf_Unsigned, frame_ptr,
85607dc194Richard Lowe                               address_size);
85707dc194Richard Lowe            frame_ptr += address_size;
85807dc194Richard Lowe        }
85907dc194Richard Lowe        break;
86007dc194Richard Lowe
86107dc194Richard Lowe    case aug_gcc_eh_z:{
86207dc194Richard Lowe            /* The Augmentation Data Length is here, followed by the
86307dc194Richard Lowe               Augmentation Data bytes themselves. */
86407dc194Richard Lowe        }
86507dc194Richard Lowe        break;
86607dc194Richard Lowe    case aug_armcc:
86707dc194Richard Lowe        break;
86807dc194Richard Lowe    case aug_past_last:
86907dc194Richard Lowe        break;
87007dc194Richard Lowe    case aug_unknown:
87107dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
87207dc194Richard Lowe        return DW_DLV_ERROR;
87307dc194Richard Lowe    }                           /* End switch on augmentation type */
87407dc194Richard Lowe    new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
87507dc194Richard Lowe    if (new_fde == NULL) {
87607dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
87707dc194Richard Lowe        return (DW_DLV_ERROR);
87807dc194Richard Lowe    }
87907dc194Richard Lowe
88007dc194Richard Lowe    new_fde->fd_length = prefix->cf_length;
88107dc194Richard Lowe    new_fde->fd_length_size = prefix->cf_local_length_size;
88207dc194Richard Lowe    new_fde->fd_extension_size = prefix->cf_local_extension_size;
88307dc194Richard Lowe    new_fde->fd_is_eh = use_gnu_cie_calc;
88407dc194Richard Lowe    new_fde->fd_cie_offset = cie_base_offset;
88507dc194Richard Lowe    new_fde->fd_cie_index = cieptr->ci_index;
88607dc194Richard Lowe    new_fde->fd_cie = cieptr;
88707dc194Richard Lowe    new_fde->fd_initial_location = initial_location;
88807dc194Richard Lowe    new_fde->fd_initial_loc_pos = initloc;
88907dc194Richard Lowe    new_fde->fd_address_range = address_range;
89007dc194Richard Lowe    new_fde->fd_fde_start = prefix->cf_start_addr;
89107dc194Richard Lowe    new_fde->fd_fde_instr_start = frame_ptr;
89207dc194Richard Lowe    new_fde->fd_dbg = dbg;
89307dc194Richard Lowe    new_fde->fd_offset_into_exception_tables =
89407dc194Richard Lowe        offset_into_exception_tables;
89507dc194Richard Lowe
89607dc194Richard Lowe    new_fde->fd_section_ptr = prefix->cf_section_ptr;
89707dc194Richard Lowe    new_fde->fd_section_index = prefix->cf_section_index;
89807dc194Richard Lowe    new_fde->fd_section_length = prefix->cf_section_length;
89907dc194Richard Lowe
90007dc194Richard Lowe    new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
90107dc194Richard Lowe    new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
90207dc194Richard Lowe    validate_length(dbg,cieptr,new_fde->fd_length,
90307dc194Richard Lowe        new_fde->fd_length_size, new_fde->fd_extension_size,
90407dc194Richard Lowe        new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
90507dc194Richard Lowe
90607dc194Richard Lowe
90707dc194Richard Lowe    *fde_ptr_out = new_fde;
90807dc194Richard Lowe    return DW_DLV_OK;
90907dc194Richard Lowe}
91007dc194Richard Lowe
91107dc194Richard Lowe/* called by qsort to compare FDE entries.
91207dc194Richard Lowe   Consumer code expects the array of FDE pointers to be in address order.
91307dc194Richard Lowe*/
91407dc194Richard Lowestatic int
91507dc194Richard Loweqsort_compare(const void *elem1, const void *elem2)
91607dc194Richard Lowe{
91707dc194Richard Lowe    Dwarf_Fde fde1 = *(Dwarf_Fde *) elem1;
91807dc194Richard Lowe    Dwarf_Fde fde2 = *(Dwarf_Fde *) elem2;
91907dc194Richard Lowe    Dwarf_Addr addr1 = fde1->fd_initial_location;
92007dc194Richard Lowe    Dwarf_Addr addr2 = fde2->fd_initial_location;
92107dc194Richard Lowe
92207dc194Richard Lowe    if (addr1 < addr2) {
92307dc194Richard Lowe        return -1;
92407dc194Richard Lowe    } else if (addr1 > addr2) {
92507dc194Richard Lowe        return 1;
92607dc194Richard Lowe    }
92707dc194Richard Lowe    return 0;
92807dc194Richard Lowe}
92907dc194Richard Lowe
93007dc194Richard Lowe
93107dc194Richard Lowe/* Read in the common cie/fde prefix, including reading
93207dc194Richard Lowe * the cie-value which shows which this is: cie or fde.
93307dc194Richard Lowe * */
93407dc194Richard Loweint
93507dc194Richard Lowedwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
93607dc194Richard Lowe                          Dwarf_Small * frame_ptr_in,
93707dc194Richard Lowe                          Dwarf_Small * section_ptr_in,
93807dc194Richard Lowe                          Dwarf_Unsigned section_index_in,
93907dc194Richard Lowe                          Dwarf_Unsigned section_length_in,
94007dc194Richard Lowe                          struct cie_fde_prefix_s *data_out,
94107dc194Richard Lowe                          Dwarf_Error * error)
94207dc194Richard Lowe{
94307dc194Richard Lowe    Dwarf_Unsigned length = 0;
94407dc194Richard Lowe    int local_length_size = 0;
94507dc194Richard Lowe    int local_extension_size = 0;
94607dc194Richard Lowe    Dwarf_Small *frame_ptr = frame_ptr_in;
94707dc194Richard Lowe    Dwarf_Small *cie_ptr_addr = 0;
94807dc194Richard Lowe    Dwarf_Unsigned cie_id = 0;
94907dc194Richard Lowe
95007dc194Richard Lowe    /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
95107dc194Richard Lowe    READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
95207dc194Richard Lowe                     frame_ptr, local_length_size,
95307dc194Richard Lowe                     local_extension_size);
95407dc194Richard Lowe
95507dc194Richard Lowe    if (length == 0) {
95607dc194Richard Lowe        /* nul bytes at end of section, seen at end of egcs eh_frame
95707dc194Richard Lowe           sections (in a.out). Take this as meaning no more CIE/FDE
95807dc194Richard Lowe           data. We should be very close to end of section. */
95907dc194Richard Lowe        return DW_DLV_NO_ENTRY;
96007dc194Richard Lowe    }
96107dc194Richard Lowe
96207dc194Richard Lowe    cie_ptr_addr = frame_ptr;
96307dc194Richard Lowe    READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
96407dc194Richard Lowe                   frame_ptr, local_length_size);
96507dc194Richard Lowe    SIGN_EXTEND(cie_id, local_length_size);
96607dc194Richard Lowe    frame_ptr += local_length_size;
96707dc194Richard Lowe
96807dc194Richard Lowe    data_out->cf_start_addr = frame_ptr_in;
96907dc194Richard Lowe    data_out->cf_addr_after_prefix = frame_ptr;
97007dc194Richard Lowe
97107dc194Richard Lowe    data_out->cf_length = length;
97207dc194Richard Lowe    data_out->cf_local_length_size = local_length_size;
97307dc194Richard Lowe    data_out->cf_local_extension_size = local_extension_size;
97407dc194Richard Lowe    data_out->cf_cie_id = cie_id;
97507dc194Richard Lowe    data_out->cf_cie_id_addr = cie_ptr_addr;
97607dc194Richard Lowe    data_out->cf_section_ptr = section_ptr_in;
97707dc194Richard Lowe    data_out->cf_section_index = section_index_in;
97807dc194Richard Lowe    data_out->cf_section_length = section_length_in;
97907dc194Richard Lowe    return DW_DLV_OK;
98007dc194Richard Lowe}
98107dc194Richard Lowe
98207dc194Richard Lowe/* On various errors previously-allocated CIEs and FDEs
98307dc194Richard Lowe   must be cleaned up.
98407dc194Richard Lowe   This helps avoid leaks in case of errors.
98507dc194Richard Lowe*/
98607dc194Richard Lowestatic void
98707dc194Richard Lowedealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
98807dc194Richard Lowe    Dwarf_Cie head_cie_ptr)
98907dc194Richard Lowe{
99007dc194Richard Lowe    Dwarf_Fde curfde = 0;
99107dc194Richard Lowe    Dwarf_Cie curcie = 0;
99207dc194Richard Lowe    Dwarf_Fde nextfde = 0;
99307dc194Richard Lowe    Dwarf_Cie nextcie = 0;
99407dc194Richard Lowe
99507dc194Richard Lowe    for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
99607dc194Richard Lowe        nextfde = curfde->fd_next;
99707dc194Richard Lowe        dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
99807dc194Richard Lowe    }
99907dc194Richard Lowe    for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
100007dc194Richard Lowe        Dwarf_Frame frame = curcie->ci_initial_table;
100107dc194Richard Lowe
100207dc194Richard Lowe        nextcie = curcie->ci_next;
100307dc194Richard Lowe        if (frame)
100407dc194Richard Lowe            dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
100507dc194Richard Lowe        dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
100607dc194Richard Lowe    }
100707dc194Richard Lowe}
100807dc194Richard Lowe
100907dc194Richard Lowe/* Find the cie whose id value is given: the id
101007dc194Richard Lowe * value is, per DWARF2/3, an offset in the section.
101107dc194Richard Lowe * For .debug_frame, zero is a legal offset. For
101207dc194Richard Lowe * GNU .eh_frame it is not a legal offset.
101307dc194Richard Lowe * 'cie_ptr' is a pointer into our section, not an offset. */
101407dc194Richard Lowestatic int
101507dc194Richard Lowedwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
101607dc194Richard Lowe                            Dwarf_Cie cur_cie_ptr,
101707dc194Richard Lowe                            Dwarf_Cie * cie_ptr_to_use_out,
101807dc194Richard Lowe                            Dwarf_Cie head_cie_ptr)
101907dc194Richard Lowe{
102007dc194Richard Lowe    Dwarf_Cie next = 0;
102107dc194Richard Lowe
102207dc194Richard Lowe    if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
102307dc194Richard Lowe        /* Usually, we use the same cie again and again. */
102407dc194Richard Lowe        *cie_ptr_to_use_out = cur_cie_ptr;
102507dc194Richard Lowe        return DW_DLV_OK;
102607dc194Richard Lowe    }
102707dc194Richard Lowe    for (next = head_cie_ptr; next; next = next->ci_next) {
102807dc194Richard Lowe        if (cie_ptr == next->ci_cie_start) {
102907dc194Richard Lowe            *cie_ptr_to_use_out = next;
103007dc194Richard Lowe            return DW_DLV_OK;
103107dc194Richard Lowe        }
103207dc194Richard Lowe    }
103307dc194Richard Lowe    return DW_DLV_NO_ENTRY;
103407dc194Richard Lowe}
103507dc194Richard Lowe
103607dc194Richard Lowe
103707dc194Richard Lowe/* We have a valid cie_ptr_val that has not been
103807dc194Richard Lowe * turned into an internal Cie yet. Do so now.
103907dc194Richard Lowe * Returns DW_DLV_OK or DW_DLV_ERROR, never
104007dc194Richard Lowe * DW_DLV_NO_ENTRY.
104107dc194Richard Lowe
104207dc194Richard Lowe 'section_ptr'    - Points to first byte of section data.
104307dc194Richard Lowe 'section_length' - Length of the section, in bytes.
104407dc194Richard Lowe 'frame_ptr_end'  - Points 1-past last byte of section data.
104507dc194Richard Lowe * */
104607dc194Richard Lowestatic int
104707dc194Richard Lowedwarf_create_cie_from_start(Dwarf_Debug dbg,
104807dc194Richard Lowe    Dwarf_Small * cie_ptr_val,
104907dc194Richard Lowe    Dwarf_Small * section_ptr,
105007dc194Richard Lowe    Dwarf_Unsigned section_index,
105107dc194Richard Lowe    Dwarf_Unsigned section_length,
105207dc194Richard Lowe    Dwarf_Small * frame_ptr_end,
105307dc194Richard Lowe    Dwarf_Unsigned cie_id_value,
105407dc194Richard Lowe    Dwarf_Unsigned cie_count,
105507dc194Richard Lowe    int use_gnu_cie_calc,
105607dc194Richard Lowe    Dwarf_Cie * cie_ptr_to_use_out,
105707dc194Richard Lowe    Dwarf_Error * error)
105807dc194Richard Lowe{
105907dc194Richard Lowe    struct cie_fde_prefix_s prefix;
106007dc194Richard Lowe    int res = DW_DLV_ERROR;
106107dc194Richard Lowe    Dwarf_Small *frame_ptr = cie_ptr_val;
106207dc194Richard Lowe
106307dc194Richard Lowe    if (frame_ptr < section_ptr || frame_ptr > frame_ptr_end) {
106407dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
106507dc194Richard Lowe        return DW_DLV_ERROR;
106607dc194Richard Lowe    }
106707dc194Richard Lowe    /* First read in the 'common prefix' to figure out what * we are to
106807dc194Richard Lowe       do with this entry. If it is not a cie * we are in big trouble. */
106907dc194Richard Lowe    memset(&prefix, 0, sizeof(prefix));
107007dc194Richard Lowe    res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
107107dc194Richard Lowe        section_index, section_length,
107207dc194Richard Lowe        &prefix, error);
107307dc194Richard Lowe    if (res == DW_DLV_ERROR) {
107407dc194Richard Lowe        return res;
107507dc194Richard Lowe    }
107607dc194Richard Lowe    if (res == DW_DLV_NO_ENTRY) {
107707dc194Richard Lowe        /* error. */
107807dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
107907dc194Richard Lowe        return DW_DLV_ERROR;
108007dc194Richard Lowe
108107dc194Richard Lowe    }
108207dc194Richard Lowe
108307dc194Richard Lowe    if (prefix.cf_cie_id != cie_id_value) {
108407dc194Richard Lowe        _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
108507dc194Richard Lowe        return DW_DLV_ERROR;
108607dc194Richard Lowe    }
108707dc194Richard Lowe    frame_ptr = prefix.cf_addr_after_prefix;
108807dc194Richard Lowe    res = dwarf_create_cie_from_after_start(dbg,
108907dc194Richard Lowe        &prefix,
109007dc194Richard Lowe        section_ptr,
109107dc194Richard Lowe        frame_ptr,
109207dc194Richard Lowe        cie_count,
109307dc194Richard Lowe        use_gnu_cie_calc,
109407dc194Richard Lowe        cie_ptr_to_use_out, error);
109507dc194Richard Lowe    return res;
109607dc194Richard Lowe
109707dc194Richard Lowe}
109807dc194Richard Lowe
109907dc194Richard Lowe
110007dc194Richard Lowe/* This is for gnu eh frames, the 'z' case.
110107dc194Richard Lowe   We find the letter involved
110207dc194Richard Lowe   Return the augmentation character and, if applicable,
110307dc194Richard Lowe   the personality routine address.
110407dc194Richard Lowe
110507dc194Richard Lowe   personality_routine_out -
110607dc194Richard Lowe        if 'P' is augchar, is personality handler addr.
110707dc194Richard Lowe        Otherwise is not set.
110807dc194Richard Lowe   aug_data  - if 'P' points  to data space of the
110907dc194Richard Lowe   aug_data_len - length of areas aug_data points to.
111007dc194Richard Lowe
111107dc194Richard Lowe*/
111207dc194Richard Lowe#if 0
111307dc194Richard Lowe/* For debugging only. */
111407dc194Richard Lowevoid
111507dc194Richard Lowedump_bytes(Dwarf_Small * start, long len)
111607dc194Richard Lowe{
111707dc194Richard Lowe    Dwarf_Small *end = start + len;
111807dc194Richard Lowe    Dwarf_Small *cur = start;
111907dc194Richard Lowe
112007dc194Richard Lowe    for (; cur < end; cur++) {
112107dc194Richard Lowe        printf(" byte %d, data %02x\n", (int) (cur - start), *cur);
112207dc194Richard Lowe    }
112307dc194Richard Lowe
112407dc194Richard Lowe}
112507dc194Richard Lowe#endif
112607dc194Richard Lowestatic int
112707dc194Richard Lowegnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
112807dc194Richard Lowe    Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
112907dc194Richard Lowe    Dwarf_Half address_size,
113007dc194Richard Lowe    unsigned char *pers_hand_enc_out,
113107dc194Richard Lowe    unsigned char *lsda_enc_out,
113207dc194Richard Lowe    unsigned char *fde_begin_enc_out,
113307dc194Richard Lowe    Dwarf_Addr * gnu_pers_addr_out)
113407dc194Richard Lowe{
113507dc194Richard Lowe    char *nc = 0;
113607dc194Richard Lowe    Dwarf_Small *cur_aug_p = aug_data;
113707dc194Richard Lowe    Dwarf_Small *end_aug_p = aug_data + aug_data_len;
113807dc194Richard Lowe
113907dc194Richard Lowe    for (nc = augmentation; *nc; ++nc) {
114007dc194Richard Lowe        char c = *nc;
114107dc194Richard Lowe
114207dc194Richard Lowe        switch (c) {
114307dc194Richard Lowe        case 'z':
114407dc194Richard Lowe            /* Means that the augmentation data is present. */
114507dc194Richard Lowe            continue;
114607dc194Richard Lowe
114707dc194Richard Lowe        case 'S':
114807dc194Richard Lowe            /* Indicates this is a signal stack frame.  Debuggers have to do
114907dc194Richard Lowe               special handling.  We don't need to do more than print this flag at
115007dc194Richard Lowe               the right time, though (see dwarfdump where it prints the augmentation
115107dc194Richard Lowe               string).
115207dc194Richard Lowe               A signal stack frame (in some OS's) can only be
115307dc194Richard Lowe               unwound (backtraced) by knowing it is a signal stack frame
115407dc194Richard Lowe               (perhaps by noticing the name of the function for the stack frame
115507dc194Richard Lowe               if the name can be found somehow) and figuring
115607dc194Richard Lowe               out (or knowing) how the kernel and libc pushed a structure
115707dc194Richard Lowe               onto the stack and loading registers from that structure.
115807dc194Richard Lowe               Totally different from normal stack unwinding.
115907dc194Richard Lowe               This flag gives an unwinder a big leg up by decoupling the
116007dc194Richard Lowe               'hint: this is a stack frame' from knowledge like
116107dc194Richard Lowe               the function name (the name might be unavailable at unwind time).
116207dc194Richard Lowe            */
116307dc194Richard Lowe            break;
116407dc194Richard Lowe
116507dc194Richard Lowe        case 'L':
116607dc194Richard Lowe            if (cur_aug_p > end_aug_p) {
116707dc194Richard Lowe                return DW_DLV_ERROR;
116807dc194Richard Lowe            }
116907dc194Richard Lowe            *lsda_enc_out = *(unsigned char *) cur_aug_p;
117007dc194Richard Lowe            ++cur_aug_p;
117107dc194Richard Lowe            break;
117207dc194Richard Lowe        case 'R':
117307dc194Richard Lowe            /* Followed by a one byte argument giving the
117407dc194Richard Lowe               pointer encoding for the address pointers in the fde. */
117507dc194Richard Lowe            if (cur_aug_p >= end_aug_p) {
117607dc194Richard Lowe                return DW_DLV_ERROR;
117707dc194Richard Lowe            }
117807dc194Richard Lowe            *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
117907dc194Richard Lowe            ++cur_aug_p;
118007dc194Richard Lowe            break;
118107dc194Richard Lowe        case 'P':{
118207dc194Richard Lowe                int res = DW_DLV_ERROR;
118307dc194Richard Lowe                Dwarf_Small *updated_aug_p = 0;
118407dc194Richard Lowe                unsigned char encoding = 0;
118507dc194Richard Lowe
118607dc194Richard Lowe                if (cur_aug_p >= end_aug_p) {
118707dc194Richard Lowe                    return DW_DLV_ERROR;
118807dc194Richard Lowe                }
118907dc194Richard Lowe                encoding = *(unsigned char *) cur_aug_p;
119007dc194Richard Lowe                *pers_hand_enc_out = encoding;
119107dc194Richard Lowe                ++cur_aug_p;
119207dc194Richard Lowe                if (cur_aug_p > end_aug_p) {
119307dc194Richard Lowe                    return DW_DLV_ERROR;
119407dc194Richard Lowe                }
119507dc194Richard Lowe                /* DW_EH_PE_pcrel makes no sense here, so we turn it
119607dc194Richard Lowe                   off via a section pointer of NULL. */
119707dc194Richard Lowe                res = read_encoded_ptr(dbg,
119807dc194Richard Lowe                                       (Dwarf_Small *) NULL,
119907dc194Richard Lowe                                       cur_aug_p,
120007dc194Richard Lowe                                       encoding,
120107dc194Richard Lowe                                       address_size,
120207dc194Richard Lowe                                       gnu_pers_addr_out,
120307dc194Richard Lowe                                       &updated_aug_p);
120407dc194Richard Lowe                if (res != DW_DLV_OK) {
120507dc194Richard Lowe                    return res;
120607dc194Richard Lowe                }
120707dc194Richard Lowe                cur_aug_p = updated_aug_p;
120807dc194Richard Lowe                if (cur_aug_p > end_aug_p) {
120907dc194Richard Lowe                    return DW_DLV_ERROR;
121007dc194Richard Lowe                }
121107dc194Richard Lowe            }
121207dc194Richard Lowe            break;
121307dc194Richard Lowe        default:
121407dc194Richard Lowe            return DW_DLV_ERROR;
121507dc194Richard Lowe
121607dc194Richard Lowe        }
121707dc194Richard Lowe    }
121807dc194Richard Lowe
121907dc194Richard Lowe    return DW_DLV_OK;
122007dc194Richard Lowe}
122107dc194Richard Lowe
122207dc194Richard Lowe/* Given augmentation character (the encoding) giving the
122307dc194Richard Loweaddress format, read the address from input_field
122407dc194Richard Loweand return an incremented value 1 past the input bytes of the
122507dc194Richard Loweaddress.
122607dc194Richard LowePush the address read back thru the *addr pointer.
122707dc194Richard LoweSee LSB (Linux Standar Base)  exception handling documents.
122807dc194Richard Lowe*/
122907dc194Richard Lowestatic int
123007dc194Richard Loweread_encoded_ptr(Dwarf_Debug dbg,
123107dc194Richard Lowe    Dwarf_Small * section_pointer,
123207dc194Richard Lowe    Dwarf_Small * input_field,
123307dc194Richard Lowe    int gnu_encoding,
123407dc194Richard Lowe    Dwarf_Half address_size,
123507dc194Richard Lowe    Dwarf_Unsigned * addr,
123607dc194Richard Lowe    Dwarf_Small ** input_field_updated)
123707dc194Richard Lowe{
123807dc194Richard Lowe    Dwarf_Word length = 0;
123907dc194Richard Lowe    int value_type = gnu_encoding & 0xf;
124007dc194Richard Lowe    Dwarf_Small *input_field_original = input_field;
124107dc194Richard Lowe
124207dc194Richard Lowe    if (gnu_encoding == 0xff) {
124307dc194Richard Lowe        /* There is no data here. */
124407dc194Richard Lowe
124507dc194Richard Lowe        *addr = 0;
124607dc194Richard Lowe        *input_field_updated = input_field;
124707dc194Richard Lowe        /* Should we return DW_DLV_NO_ENTRY? */
124807dc194Richard Lowe        return DW_DLV_OK;
124907dc194Richard Lowe    }
125007dc194Richard Lowe    switch (value_type) {
125107dc194Richard Lowe    case DW_EH_PE_absptr:{
125207dc194Richard Lowe            /* value_type is zero. Treat as pointer size of the object.
125307dc194Richard Lowe             */
125407dc194Richard Lowe            Dwarf_Unsigned ret_value = 0;
125507dc194Richard Lowe
125607dc194Richard Lowe            READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
125707dc194Richard Lowe                           input_field, address_size);
125807dc194Richard Lowe            *addr = ret_value;
125907dc194Richard Lowe            *input_field_updated = input_field + address_size;
126007dc194Richard Lowe        }
126107dc194Richard Lowe        break;
126207dc194Richard Lowe    case DW_EH_PE_uleb128:{
126307dc194Richard Lowe            Dwarf_Unsigned val = _dwarf_decode_u_leb128(input_field,
126407dc194Richard Lowe                                                        &length);
126507dc194Richard Lowe
126607dc194Richard Lowe            *addr = val;
126707dc194Richard Lowe            *input_field_updated = input_field + length;
126807dc194Richard Lowe        }
126907dc194Richard Lowe        break;
127007dc194Richard Lowe    case DW_EH_PE_udata2:{
127107dc194Richard Lowe            Dwarf_Unsigned ret_value = 0;
127207dc194Richard Lowe
127307dc194Richard Lowe            READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
127407dc194Richard Lowe                           input_field, 2);
127507dc194Richard Lowe            *addr = ret_value;
127607dc194Richard Lowe            *input_field_updated = input_field + 2;
127707dc194Richard Lowe        }
127807dc194Richard Lowe        break;
127907dc194Richard Lowe
128007dc194Richard Lowe    case DW_EH_PE_udata4:{
128107dc194Richard Lowe
128207dc194Richard Lowe            Dwarf_Unsigned ret_value = 0;
128307dc194Richard Lowe
128407dc194Richard Lowe            /* ASSERT: sizeof(Dwarf_ufixed) == 4 */
128507dc194Richard Lowe            READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
128607dc194Richard Lowe                           input_field, sizeof(Dwarf_ufixed));
128707dc194Richard Lowe            *addr = ret_value;
128807dc194Richard Lowe            *input_field_updated = input_field + sizeof(Dwarf_ufixed);
128907dc194Richard Lowe        }
129007dc194Richard Lowe        break;
129107dc194Richard Lowe
129207dc194Richard Lowe    case DW_EH_PE_udata8:{
129307dc194Richard Lowe            Dwarf_Unsigned ret_value = 0;
129407dc194Richard Lowe
129507dc194Richard Lowe            /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
129607dc194Richard Lowe            READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
129707dc194Richard Lowe                           input_field, sizeof(Dwarf_Unsigned));
129807dc194Richard Lowe            *addr = ret_value;
129907dc194Richard Lowe            *input_field_updated = input_field + sizeof(Dwarf_Unsigned);
130007dc194Richard Lowe        }
130107dc194Richard Lowe        break;
130207dc194Richard Lowe
130307dc194Richard Lowe    case DW_EH_PE_sleb128:{
130407dc194Richard Lowe            Dwarf_Signed val = _dwarf_decode_s_leb128(input_field,
130507dc194Richard Lowe                                                      &length);
130607dc194Richard Lowe
130707dc194Richard Lowe            *addr = (Dwarf_Unsigned) val;
130807dc194Richard Lowe            *input_field_updated = input_field + length;
130907dc194Richard Lowe        }
131007dc194Richard Lowe        break;
131107dc194Richard Lowe    case DW_EH_PE_sdata2:{
131207dc194Richard Lowe            Dwarf_Unsigned val = 0;
131307dc194Richard Lowe
131407dc194Richard Lowe            READ_UNALIGNED(dbg, val, Dwarf_Unsigned, input_field, 2);
131507dc194Richard Lowe            SIGN_EXTEND(val, 2);
131607dc194Richard Lowe            *addr = (Dwarf_Unsigned) val;
131707dc194Richard Lowe            *input_field_updated = input_field + 2;
131807dc194Richard Lowe        }
131907dc194Richard Lowe        break;
132007dc194Richard Lowe
132107dc194Richard Lowe    case DW_EH_PE_sdata4:{
132207dc194Richard Lowe            Dwarf_Unsigned val = 0;
132307dc194Richard Lowe
132407dc194Richard Lowe            /* ASSERT: sizeof(Dwarf_ufixed) == 4 */
132507dc194Richard Lowe            READ_UNALIGNED(dbg, val,
132607dc194Richard Lowe                           Dwarf_Unsigned, input_field,
132707dc194Richard Lowe                           sizeof(Dwarf_ufixed));
132807dc194Richard Lowe            SIGN_EXTEND(val, sizeof(Dwarf_ufixed));
132907dc194Richard Lowe            *addr = (Dwarf_Unsigned) val;
133007dc194Richard Lowe            *input_field_updated = input_field + sizeof(Dwarf_ufixed);
133107dc194Richard Lowe        }
133207dc194Richard Lowe        break;
133307dc194Richard Lowe    case DW_EH_PE_sdata8:{
133407dc194Richard Lowe            Dwarf_Unsigned val = 0;
133507dc194Richard Lowe
133607dc194Richard Lowe            /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
133707dc194Richard Lowe            READ_UNALIGNED(dbg, val,
133807dc194Richard Lowe                           Dwarf_Unsigned, input_field,
133907dc194Richard Lowe                           sizeof(Dwarf_Unsigned));
134007dc194Richard Lowe            *addr = (Dwarf_Unsigned) val;
134107dc194Richard Lowe            *input_field_updated = input_field + sizeof(Dwarf_Unsigned);
134207dc194Richard Lowe        }
134307dc194Richard Lowe        break;
134407dc194Richard Lowe    default:
134507dc194Richard Lowe        return DW_DLV_ERROR;
134607dc194Richard Lowe
134707dc194Richard Lowe    };
134807dc194Richard Lowe    /* The ELF ABI for gnu does not document the meaning of
134907dc194Richard Lowe       DW_EH_PE_pcrel, which is awkward.  It apparently means the value
135007dc194Richard Lowe       we got above is pc-relative (meaning section-relative), so we
135107dc194Richard Lowe       adjust the value. Section_pointer may be null if it is known
135207dc194Richard Lowe       DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an
135307dc194Richard Lowe       address-range value. */
135407dc194Richard Lowe    if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
135507dc194Richard Lowe        /* Address (*addr) above is pc relative with respect to a
135607dc194Richard Lowe           section. Add to the offset the base address (from elf) of
135707dc194Richard Lowe           section and the distance of the field we are reading from
135807dc194Richard Lowe           the section-beginning to get the actual address. */
135907dc194Richard Lowe        /* ASSERT: input_field_original >= section_pointer */
136007dc194Richard Lowe        Dwarf_Unsigned distance =
136107dc194Richard Lowe            input_field_original - section_pointer;
136207dc194Richard Lowe        *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
136307dc194Richard Lowe    }
136407dc194Richard Lowe
136507dc194Richard Lowe    return DW_DLV_OK;
136607dc194Richard Lowe}
136707dc194Richard Lowe
136807dc194Richard Lowe
136907dc194Richard Lowe
137007dc194Richard Lowe
137107dc194Richard Lowe/*
137207dc194Richard Lowe        All augmentation string checking done here now.
137307dc194Richard Lowe
137407dc194Richard Lowe        For .eh_frame, gcc from 3.3 uses the z style, earlier used
137507dc194Richard Lowe        only "eh" as augmentation.  We don't yet handle
137607dc194Richard Lowe        decoding .eh_frame with the z style extensions like L P.
137707dc194Richard Lowe
137807dc194Richard Lowe        These are nasty heuristics, but then that's life
137907dc194Richard Lowe        as augmentations are implementation specific.
138007dc194Richard Lowe*/
138107dc194Richard Lowe/* ARGSUSED */
138207dc194Richard Loweenum Dwarf_augmentation_type
138307dc194Richard Lowe_dwarf_get_augmentation_type(Dwarf_Debug dbg,
138407dc194Richard Lowe    Dwarf_Small * augmentation_string,
138507dc194Richard Lowe    int is_gcc_eh_frame)
138607dc194Richard Lowe{
138707dc194Richard Lowe    enum Dwarf_augmentation_type t = aug_unknown;
138807dc194Richard Lowe    char *ag_string = (char *) augmentation_string;
138907dc194Richard Lowe
139007dc194Richard Lowe    if (ag_string[0] == 0) {
139107dc194Richard Lowe        /* Empty string. We'll just guess that we know what this means:
139207dc194Richard Lowe           standard dwarf2/3 with no implementation-defined fields.  */
139307dc194Richard Lowe        t = aug_empty_string;
139407dc194Richard Lowe    } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
139507dc194Richard Lowe        /* The string is "mti v1". Used internally at SGI, probably
139607dc194Richard Lowe           never shipped. Replaced by "z". Treat like 'nothing
139707dc194Richard Lowe           special'.  */
139807dc194Richard Lowe        t = aug_irix_mti_v1;
139907dc194Richard Lowe    } else if (ag_string[0] == 'z') {
140007dc194Richard Lowe        /* If it's IRIX cc, z means aug_irix_exception_table. z1 z2
140107dc194Richard Lowe           were designed as for IRIX CC, but never implemented */
140207dc194Richard Lowe        /* If it's gcc, z may be any of several things. "z" or z
140307dc194Richard Lowe           followed optionally followed by one or more of L R P, each
140407dc194Richard Lowe           of which means a value may be present. Should be in eh_frame
140507dc194Richard Lowe           only, I think. */
140607dc194Richard Lowe        if (is_gcc_eh_frame) {
140707dc194Richard Lowe            t = aug_gcc_eh_z;
140807dc194Richard Lowe        } else if (ag_string[1] == 0) {
140907dc194Richard Lowe            /* This is the normal IRIX C++ case, where there is an
141007dc194Richard Lowe               offset into a table in each fde. The table being for
141107dc194Richard Lowe               IRIX CC exception handling.  */
141207dc194Richard Lowe            /* DW_CIE_AUGMENTER_STRING_V0 "z" */
141307dc194Richard Lowe            t = aug_irix_exception_table;
141407dc194Richard Lowe        }                       /* Else unknown. */
141507dc194Richard Lowe    } else if (strncmp(ag_string, "eh", 2) == 0) {
141607dc194Richard Lowe        /* gcc .eh_frame augmentation for egcs and gcc 2.x, at least
141707dc194Richard Lowe           for x86. */
141807dc194Richard Lowe        t = aug_eh;
141907dc194Richard Lowe    } else if (strcmp(ag_string, "armcc+") == 0) {
142007dc194Richard Lowe        /* Arm  uses this string to mean a bug in
142107dc194Richard Lowe           in Arm compilers was fixed, changing to the standard
142207dc194Richard Lowe           calculation of the CFA.  See
142307dc194Richard Lowe           http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
142407dc194Richard Lowe           for details. */
142507dc194Richard Lowe        t = aug_armcc;
142607dc194Richard Lowe    } else {
142707dc194Richard Lowe
142807dc194Richard Lowe    }
142907dc194Richard Lowe    return t;
143007dc194Richard Lowe}
143107dc194Richard Lowe
143207dc194Richard Lowe/* Using augmentation, and version
143307dc194Richard Lowe   read in the augmentation data for GNU eh.
143407dc194Richard Lowe
143507dc194Richard Lowe   Return DW_DLV_OK if we succeeded,
143607dc194Richard Lowe   DW_DLV_ERR if we fail.
143707dc194Richard Lowe
143807dc194Richard Lowe   On success, update  'size_of_augmentation_data' with
143907dc194Richard Lowe   the length of the fields that are part of augmentation (so the
144007dc194Richard Lowe   caller can increment frame_ptr appropriately).
144107dc194Richard Lowe
144207dc194Richard Lowe   'frame_ptr' points within section.
144307dc194Richard Lowe   'section_pointer' points to section base address in memory.
144407dc194Richard Lowe*/
144507dc194Richard Lowe/* ARGSUSED */
144607dc194Richard Lowestatic int
144707dc194Richard Loweget_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
144807dc194Richard Lowe    unsigned long *size_of_augmentation_data,
144907dc194Richard Lowe    enum Dwarf_augmentation_type augtype,
145007dc194Richard Lowe    Dwarf_Small * section_pointer,
145107dc194Richard Lowe    Dwarf_Small * fde_eh_encoding_out,
145207dc194Richard Lowe    char *augmentation)
145307dc194Richard Lowe{
145407dc194Richard Lowe    char *suffix = 0;
145507dc194Richard Lowe    unsigned long augdata_size = 0;
145607dc194Richard Lowe
145707dc194Richard Lowe    if (augtype == aug_gcc_eh_z) {
145807dc194Richard Lowe        /* Has leading 'z'. */
145907dc194Richard Lowe        Dwarf_Word leb128_length = 0;
146007dc194Richard Lowe
146107dc194Richard Lowe        /* Dwarf_Unsigned eh_value = */
146207dc194Richard Lowe        _dwarf_decode_u_leb128(frame_ptr, &leb128_length);
146307dc194Richard Lowe        augdata_size += leb128_length;
146407dc194Richard Lowe        frame_ptr += leb128_length;
146507dc194Richard Lowe        suffix = augmentation + 1;
146607dc194Richard Lowe    } else {
146707dc194Richard Lowe        /* Prefix is 'eh'.  As in gcc 3.2. No suffix present
146807dc194Richard Lowe           apparently. */
146907dc194Richard Lowe        suffix = augmentation + 2;
147007dc194Richard Lowe    }
147107dc194Richard Lowe    for (; *suffix; ++suffix) {
147207dc194Richard Lowe        /* We have no idea what this is as yet. Some extensions beyond
147307dc194Richard Lowe           dwarf exist which we do not yet handle. */
147407dc194Richard Lowe        return DW_DLV_ERROR;
147507dc194Richard Lowe
147607dc194Richard Lowe    }
147707dc194Richard Lowe
147807dc194Richard Lowe    *size_of_augmentation_data = augdata_size;
147907dc194Richard Lowe    return DW_DLV_OK;
148007dc194Richard Lowe}
148107dc194Richard Lowe
148207dc194Richard Lowe
148307dc194Richard Lowe/* Make the 'cie_id_addr' consistent across .debug_frame and .eh_frame.
148407dc194Richard Lowe   Calculate a pointer into section bytes given a cie_id, which is
148507dc194Richard Lowe   trivial for .debug_frame, but a bit more work for .eh_frame.
148607dc194Richard Lowe*/
148707dc194Richard Lowestatic Dwarf_Small *
148807dc194Richard Loweget_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
148907dc194Richard Lowe    int use_gnu_cie_calc,
149007dc194Richard Lowe    Dwarf_Small * section_ptr,
149107dc194Richard Lowe    Dwarf_Small * cie_id_addr)
149207dc194Richard Lowe{
149307dc194Richard Lowe    Dwarf_Small *cieptr = 0;
149407dc194Richard Lowe
149507dc194Richard Lowe    if (use_gnu_cie_calc) {
149607dc194Richard Lowe        /* cie_id value is offset, in section, of the cie_id itself, to
149707dc194Richard Lowe           use vm ptr of the value, less the value, to get to the cie
149807dc194Richard Lowe           itself. In addition, munge *cie_id_addr to look *as if* it
149907dc194Richard Lowe           was from real dwarf. */
150007dc194Richard Lowe        cieptr = (Dwarf_Small *)(uintptr_t)
150107dc194Richard Lowe          ((Dwarf_Unsigned)(uintptr_t)cie_id_addr) -
150207dc194Richard Lowe          ((Dwarf_Unsigned) cie_id_value);
150307dc194Richard Lowe    } else {
150407dc194Richard Lowe        /* Traditional dwarf section offset is in cie_id */
150507dc194Richard Lowe        cieptr = (section_ptr + cie_id_value);
150607dc194Richard Lowe    }
150707dc194Richard Lowe    return cieptr;
150807dc194Richard Lowe}
150907dc194Richard Lowe
151007dc194Richard Lowe/* To properly release all spaced used.
151107dc194Richard Lowe   Earlier approaches (before July 15, 2005)
151207dc194Richard Lowe   letting client do the dealloc directly left
151307dc194Richard Lowe   some data allocated.
151407dc194Richard Lowe   This is directly called by consumer code.
151507dc194Richard Lowe*/
151607dc194Richard Lowevoid
151707dc194Richard Lowedwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
151807dc194Richard Lowe    Dwarf_Cie * cie_data,
151907dc194Richard Lowe    Dwarf_Signed cie_element_count,
152007dc194Richard Lowe    Dwarf_Fde * fde_data,
152107dc194Richard Lowe    Dwarf_Signed fde_element_count)
152207dc194Richard Lowe{
152307dc194Richard Lowe    Dwarf_Signed i = 0;
152407dc194Richard Lowe
152507dc194Richard Lowe    for (i = 0; i < cie_element_count; ++i) {
152607dc194Richard Lowe        Dwarf_Frame frame = cie_data[i]->ci_initial_table;
152707dc194Richard Lowe
152807dc194Richard Lowe        if (frame)
152907dc194Richard Lowe            dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
153007dc194Richard Lowe        dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
153107dc194Richard Lowe    }
153207dc194Richard Lowe    for (i = 0; i < fde_element_count; ++i) {
153307dc194Richard Lowe        dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
153407dc194Richard Lowe    }
153507dc194Richard Lowe    if (cie_data)
153607dc194Richard Lowe        dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
153707dc194Richard Lowe    if (fde_data)
153807dc194Richard Lowe        dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
153907dc194Richard Lowe
154007dc194Richard Lowe}
1541