107dc1947SRichard Lowe /*
207dc1947SRichard Lowe   Copyright (C) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
3*4d9fdb46SRobert Mustacchi   Portions Copyright (C) 2007-2020 David Anderson. All Rights Reserved.
4*4d9fdb46SRobert Mustacchi   Portions Copyright (C) 2010-2012 SN Systems Ltd. All Rights Reserved.
5*4d9fdb46SRobert Mustacchi 
6*4d9fdb46SRobert Mustacchi   This program is free software; you can redistribute it
7*4d9fdb46SRobert Mustacchi   and/or modify it under the terms of version 2.1 of the
8*4d9fdb46SRobert Mustacchi   GNU Lesser General Public License as published by the Free
9*4d9fdb46SRobert Mustacchi   Software Foundation.
10*4d9fdb46SRobert Mustacchi 
11*4d9fdb46SRobert Mustacchi   This program is distributed in the hope that it would be
12*4d9fdb46SRobert Mustacchi   useful, but WITHOUT ANY WARRANTY; without even the implied
13*4d9fdb46SRobert Mustacchi   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14*4d9fdb46SRobert Mustacchi   PURPOSE.
15*4d9fdb46SRobert Mustacchi 
16*4d9fdb46SRobert Mustacchi   Further, this software is distributed without any warranty
17*4d9fdb46SRobert Mustacchi   that it is free of the rightful claim of any third person
18*4d9fdb46SRobert Mustacchi   regarding infringement or the like.  Any license provided
19*4d9fdb46SRobert Mustacchi   herein, whether implied or otherwise, applies only to this
20*4d9fdb46SRobert Mustacchi   software file.  Patent licenses, if any, provided herein
21*4d9fdb46SRobert Mustacchi   do not apply to combinations of this program with other
22*4d9fdb46SRobert Mustacchi   software, or any other product whatsoever.
23*4d9fdb46SRobert Mustacchi 
24*4d9fdb46SRobert Mustacchi   You should have received a copy of the GNU Lesser General
25*4d9fdb46SRobert Mustacchi   Public License along with this program; if not, write the
26*4d9fdb46SRobert Mustacchi   Free Software Foundation, Inc., 51 Franklin Street - Fifth
27*4d9fdb46SRobert Mustacchi   Floor, Boston MA 02110-1301, USA.
2807dc1947SRichard Lowe 
29*4d9fdb46SRobert Mustacchi */
3007dc1947SRichard Lowe 
31*4d9fdb46SRobert Mustacchi /*  This  implements _dwarf_get_fde_list_internal()
32*4d9fdb46SRobert Mustacchi     and related helper functions for reading cie/fde data.  */
3307dc1947SRichard Lowe 
34*4d9fdb46SRobert Mustacchi #include "config.h"
35*4d9fdb46SRobert Mustacchi #include <stdio.h>
36*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDLIB_H
37*4d9fdb46SRobert Mustacchi #include <stdlib.h>
38*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDLIB_H */
39*4d9fdb46SRobert Mustacchi #include "dwarf_incl.h"
40*4d9fdb46SRobert Mustacchi #include "dwarf_alloc.h"
41*4d9fdb46SRobert Mustacchi #include "dwarf_error.h"
42*4d9fdb46SRobert Mustacchi #include "dwarf_util.h"
43*4d9fdb46SRobert Mustacchi #include "dwarf_frame.h"
44*4d9fdb46SRobert Mustacchi #include "dwarf_arange.h" /* using Arange as a way to build a list */
45*4d9fdb46SRobert Mustacchi #include "dwarfstring.h"
4607dc1947SRichard Lowe 
47*4d9fdb46SRobert Mustacchi /*  For a little information about .eh_frame see
48*4d9fdb46SRobert Mustacchi     https://stackoverflow.com/questions/14091231/what-do-the-eh-frame-and-eh-frame-hdr-sections-store-exactly
49*4d9fdb46SRobert Mustacchi     http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
50*4d9fdb46SRobert Mustacchi     The above give information about fields and sizes but
51*4d9fdb46SRobert Mustacchi     very very little about content.
5207dc1947SRichard Lowe 
53*4d9fdb46SRobert Mustacchi     .eh_frame_hdr contains data for C++ unwinding. Namely
54*4d9fdb46SRobert Mustacchi     tables for fast access into .eh_frame.
5507dc1947SRichard Lowe */
5607dc1947SRichard Lowe 
5707dc1947SRichard Lowe 
5807dc1947SRichard Lowe 
59*4d9fdb46SRobert Mustacchi #define TRUE 1
60*4d9fdb46SRobert Mustacchi #define FALSE 0
6107dc1947SRichard Lowe 
62*4d9fdb46SRobert Mustacchi #if 0  /* FOR DEBUGGING */
63*4d9fdb46SRobert Mustacchi /* For debugging only. */
64*4d9fdb46SRobert Mustacchi static void
65*4d9fdb46SRobert Mustacchi dump_bytes(const char *msg,Dwarf_Small * start, long len)
66*4d9fdb46SRobert Mustacchi {
67*4d9fdb46SRobert Mustacchi     Dwarf_Small *end = start + len;
68*4d9fdb46SRobert Mustacchi     Dwarf_Small *cur = start;
69*4d9fdb46SRobert Mustacchi     printf("%s (0x%lx) ",msg,(unsigned long)start);
70*4d9fdb46SRobert Mustacchi     for (; cur < end; cur++) {
71*4d9fdb46SRobert Mustacchi         printf("%02x", *cur);
72*4d9fdb46SRobert Mustacchi     }
73*4d9fdb46SRobert Mustacchi     printf("\n");
74*4d9fdb46SRobert Mustacchi }
7507dc1947SRichard Lowe 
76*4d9fdb46SRobert Mustacchi #endif
7707dc1947SRichard Lowe 
7807dc1947SRichard Lowe static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
79*4d9fdb46SRobert Mustacchi     Dwarf_Cie cur_cie_ptr,
80*4d9fdb46SRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
81*4d9fdb46SRobert Mustacchi     Dwarf_Cie head_cie_ptr);
8207dc1947SRichard Lowe static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
83*4d9fdb46SRobert Mustacchi     Dwarf_Cie head_cie_ptr);
8407dc1947SRichard Lowe static int dwarf_create_cie_from_start(Dwarf_Debug dbg,
85*4d9fdb46SRobert Mustacchi     Dwarf_Small * cie_ptr_val,
86*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr,
87*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned section_index,
88*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned section_length,
89*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
90*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned cie_id_value,
91*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned cie_count,
92*4d9fdb46SRobert Mustacchi     int use_gnu_cie_calc,
93*4d9fdb46SRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
94*4d9fdb46SRobert Mustacchi     Dwarf_Error * error);
95*4d9fdb46SRobert Mustacchi 
9607dc1947SRichard Lowe static int get_gcc_eh_augmentation(Dwarf_Debug dbg,
97*4d9fdb46SRobert Mustacchi     Dwarf_Small * frame_ptr,
98*4d9fdb46SRobert Mustacchi     unsigned long
99*4d9fdb46SRobert Mustacchi     *size_of_augmentation_data,
100*4d9fdb46SRobert Mustacchi     enum Dwarf_augmentation_type augtype,
101*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_end_pointer,
102*4d9fdb46SRobert Mustacchi     char *augmentation,
103*4d9fdb46SRobert Mustacchi     Dwarf_Error *error);
10407dc1947SRichard Lowe 
10507dc1947SRichard Lowe static int
106*4d9fdb46SRobert Mustacchi gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
107*4d9fdb46SRobert Mustacchi     Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
108*4d9fdb46SRobert Mustacchi     Dwarf_Half address_size,
109*4d9fdb46SRobert Mustacchi     unsigned char *pers_hand_enc_out,
110*4d9fdb46SRobert Mustacchi     unsigned char *lsda_enc_out,
111*4d9fdb46SRobert Mustacchi     unsigned char *fde_begin_enc_out,
112*4d9fdb46SRobert Mustacchi     Dwarf_Addr * gnu_pers_addr_out,
113*4d9fdb46SRobert Mustacchi     Dwarf_Error *error);
11407dc1947SRichard Lowe 
11507dc1947SRichard Lowe 
11607dc1947SRichard Lowe static int read_encoded_ptr(Dwarf_Debug dbg,
117*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_pointer,
118*4d9fdb46SRobert Mustacchi     Dwarf_Small * input_field,
119*4d9fdb46SRobert Mustacchi     int gnu_encoding,
120*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
121*4d9fdb46SRobert Mustacchi     Dwarf_Half address_size,
122*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned * addr,
123*4d9fdb46SRobert Mustacchi     Dwarf_Small ** input_field_out,
124*4d9fdb46SRobert Mustacchi     Dwarf_Error *error);
12507dc1947SRichard Lowe 
12607dc1947SRichard Lowe 
12707dc1947SRichard Lowe 
128*4d9fdb46SRobert Mustacchi /*  Called by qsort to compare FDE entries.
129*4d9fdb46SRobert Mustacchi     Consumer code expects the array of FDE pointers to be
130*4d9fdb46SRobert Mustacchi     in address order.
131*4d9fdb46SRobert Mustacchi */
132*4d9fdb46SRobert Mustacchi static int
qsort_compare(const void * elem1,const void * elem2)133*4d9fdb46SRobert Mustacchi qsort_compare(const void *elem1, const void *elem2)
134*4d9fdb46SRobert Mustacchi {
135*4d9fdb46SRobert Mustacchi     const Dwarf_Fde fde1 = *(const Dwarf_Fde *) elem1;
136*4d9fdb46SRobert Mustacchi     const Dwarf_Fde fde2 = *(const Dwarf_Fde *) elem2;
137*4d9fdb46SRobert Mustacchi     Dwarf_Addr addr1 = fde1->fd_initial_location;
138*4d9fdb46SRobert Mustacchi     Dwarf_Addr addr2 = fde2->fd_initial_location;
13907dc1947SRichard Lowe 
140*4d9fdb46SRobert Mustacchi     if (addr1 < addr2) {
141*4d9fdb46SRobert Mustacchi         return -1;
142*4d9fdb46SRobert Mustacchi     } else if (addr1 > addr2) {
143*4d9fdb46SRobert Mustacchi         return 1;
144*4d9fdb46SRobert Mustacchi     }
145*4d9fdb46SRobert Mustacchi     return 0;
146*4d9fdb46SRobert Mustacchi }
14707dc1947SRichard Lowe 
148*4d9fdb46SRobert Mustacchi /*  Adds 'newone' to the end of the list starting at 'head'
149*4d9fdb46SRobert Mustacchi     and makes the new one 'cur'rent. */
15007dc1947SRichard Lowe static void
chain_up_fde(Dwarf_Fde newone,Dwarf_Fde * head,Dwarf_Fde * cur)15107dc1947SRichard Lowe chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
15207dc1947SRichard Lowe {
15307dc1947SRichard Lowe     if (*head == NULL)
15407dc1947SRichard Lowe         *head = newone;
15507dc1947SRichard Lowe     else {
15607dc1947SRichard Lowe         (*cur)->fd_next = newone;
15707dc1947SRichard Lowe     }
15807dc1947SRichard Lowe     *cur = newone;
15907dc1947SRichard Lowe 
16007dc1947SRichard Lowe }
16107dc1947SRichard Lowe 
162*4d9fdb46SRobert Mustacchi /*  Adds 'newone' to the end of the list starting at 'head'
163*4d9fdb46SRobert Mustacchi     and makes the new one 'cur'rent. */
16407dc1947SRichard Lowe static void
chain_up_cie(Dwarf_Cie newone,Dwarf_Cie * head,Dwarf_Cie * cur)16507dc1947SRichard Lowe chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
16607dc1947SRichard Lowe {
16707dc1947SRichard Lowe     if (*head == NULL) {
16807dc1947SRichard Lowe         *head = newone;
16907dc1947SRichard Lowe     } else {
17007dc1947SRichard Lowe         (*cur)->ci_next = newone;
17107dc1947SRichard Lowe     }
17207dc1947SRichard Lowe     *cur = newone;
17307dc1947SRichard Lowe }
17407dc1947SRichard Lowe 
175*4d9fdb46SRobert Mustacchi /*  The size of the length field plus the
176*4d9fdb46SRobert Mustacchi     value of length must be an integral
177*4d9fdb46SRobert Mustacchi     multiple of the address size.  Dwarf4 standard.
17807dc1947SRichard Lowe 
179*4d9fdb46SRobert Mustacchi     A constant that gives the number of bytes of the CIE
180*4d9fdb46SRobert Mustacchi     structure, not including the length field itself
181*4d9fdb46SRobert Mustacchi     (where length mod <size of an address> == 0)
18207dc1947SRichard Lowe     (see Section 7.2.2). Dwarf3 standard.
183*4d9fdb46SRobert Mustacchi 
184*4d9fdb46SRobert Mustacchi     A uword constant that gives the number of bytes of
18507dc1947SRichard Lowe     the CIE structure, not including the
18607dc1947SRichard Lowe     length field, itself (length mod <addressing unit size> == 0).
18707dc1947SRichard Lowe     Dwarf2 standard.*/
18807dc1947SRichard Lowe static void
validate_length(Dwarf_Debug dbg,Dwarf_Cie cieptr,Dwarf_Unsigned length,Dwarf_Unsigned length_size,Dwarf_Unsigned extension_size,Dwarf_Small * section_ptr,Dwarf_Small * ciefde_start,const char * cieorfde)18907dc1947SRichard Lowe validate_length(Dwarf_Debug dbg,
19007dc1947SRichard Lowe     Dwarf_Cie cieptr, Dwarf_Unsigned length,
19107dc1947SRichard Lowe     Dwarf_Unsigned length_size,
19207dc1947SRichard Lowe     Dwarf_Unsigned extension_size,
19307dc1947SRichard Lowe     Dwarf_Small * section_ptr,
19407dc1947SRichard Lowe     Dwarf_Small * ciefde_start,
19507dc1947SRichard Lowe     const char * cieorfde)
19607dc1947SRichard Lowe {
197*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned address_size = 0;
19807dc1947SRichard Lowe     Dwarf_Unsigned length_field_summed = length_size + extension_size;
19907dc1947SRichard Lowe     Dwarf_Unsigned total_len = length + length_field_summed;
200*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned mod = 0;
20107dc1947SRichard Lowe 
202*4d9fdb46SRobert Mustacchi     if (cieptr) {
203*4d9fdb46SRobert Mustacchi         address_size = cieptr->ci_address_size;
204*4d9fdb46SRobert Mustacchi     } else {
205*4d9fdb46SRobert Mustacchi         address_size = dbg->de_pointer_size;
206*4d9fdb46SRobert Mustacchi     }
207*4d9fdb46SRobert Mustacchi     mod = total_len % address_size;
20807dc1947SRichard Lowe     if (mod != 0) {
209*4d9fdb46SRobert Mustacchi         dwarfstring  harm;
21007dc1947SRichard Lowe         Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
211*4d9fdb46SRobert Mustacchi 
212*4d9fdb46SRobert Mustacchi         dwarfstring_constructor(&harm);
213*4d9fdb46SRobert Mustacchi         if (!cieorfde || (strlen(cieorfde) > 3)) {
214*4d9fdb46SRobert Mustacchi             /*  Coding error or memory corruption? */
215*4d9fdb46SRobert Mustacchi             cieorfde = "ERROR!";
216*4d9fdb46SRobert Mustacchi         }
217*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
21807dc1947SRichard Lowe             "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
219*4d9fdb46SRobert Mustacchi             " len=0x%" DW_PR_XZEROS DW_PR_DUx,
220*4d9fdb46SRobert Mustacchi             length);
221*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
222*4d9fdb46SRobert Mustacchi             ", len size=0x%"  DW_PR_XZEROS DW_PR_DUx,
223*4d9fdb46SRobert Mustacchi             length_size);
224*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
225*4d9fdb46SRobert Mustacchi             ", extn size=0x%" DW_PR_XZEROS DW_PR_DUx,
226*4d9fdb46SRobert Mustacchi             extension_size);
227*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
228*4d9fdb46SRobert Mustacchi             ", totl length=0x%" DW_PR_XZEROS DW_PR_DUx,
229*4d9fdb46SRobert Mustacchi             total_len);
230*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
231*4d9fdb46SRobert Mustacchi             ", addr size=0x%" DW_PR_XZEROS DW_PR_DUx,
232*4d9fdb46SRobert Mustacchi             address_size);
233*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
234*4d9fdb46SRobert Mustacchi             ", mod=0x%" DW_PR_XZEROS DW_PR_DUx " must be zero",
235*4d9fdb46SRobert Mustacchi             mod);
236*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_s(&harm,
237*4d9fdb46SRobert Mustacchi             " in %s",(char *)cieorfde);
238*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&harm,
239*4d9fdb46SRobert Mustacchi             ", offset 0x%" DW_PR_XZEROS DW_PR_DUx ".",
24007dc1947SRichard Lowe             sectionoffset);
241*4d9fdb46SRobert Mustacchi         dwarf_insert_harmless_error(dbg,
242*4d9fdb46SRobert Mustacchi             dwarfstring_string(&harm));
243*4d9fdb46SRobert Mustacchi         dwarfstring_destructor(&harm);
24407dc1947SRichard Lowe     }
24507dc1947SRichard Lowe     return;
24607dc1947SRichard Lowe }
24707dc1947SRichard Lowe 
24807dc1947SRichard Lowe 
249*4d9fdb46SRobert Mustacchi #if 0 /* FOR DEBUGGING */
25007dc1947SRichard Lowe /* For debugging only. */
25107dc1947SRichard Lowe static void
25207dc1947SRichard Lowe print_prefix(struct cie_fde_prefix_s *prefix, int line)
25307dc1947SRichard Lowe {
25407dc1947SRichard Lowe     printf("prefix-print, prefix at 0x%lx, line %d\n",
255*4d9fdb46SRobert Mustacchi         (unsigned long) prefix, line);
25607dc1947SRichard Lowe     printf("  start addr 0x%lx after prefix 0x%lx\n",
257*4d9fdb46SRobert Mustacchi         (unsigned long) prefix->cf_start_addr,
258*4d9fdb46SRobert Mustacchi         (unsigned long) prefix->cf_addr_after_prefix);
259*4d9fdb46SRobert Mustacchi     printf("  length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
260*4d9fdb46SRobert Mustacchi         (Dwarf_Unsigned) prefix->cf_length,
261*4d9fdb46SRobert Mustacchi         prefix->cf_local_length_size,
262*4d9fdb46SRobert Mustacchi         prefix->cf_local_extension_size);
26307dc1947SRichard Lowe     printf("  cie_id 0x%" DW_PR_DUx " cie_id  cie_id_addr 0x%lx\n",
264*4d9fdb46SRobert Mustacchi         (Dwarf_Unsigned) prefix->cf_cie_id,
265*4d9fdb46SRobert Mustacchi         (long) prefix->cf_cie_id_addr);
26607dc1947SRichard Lowe     printf
26707dc1947SRichard Lowe         ("  sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
268*4d9fdb46SRobert Mustacchi         (unsigned long) prefix->cf_section_ptr,
269*4d9fdb46SRobert Mustacchi         (Dwarf_Signed) prefix->cf_section_index,
270*4d9fdb46SRobert Mustacchi         (Dwarf_Unsigned) prefix->cf_section_length,
271*4d9fdb46SRobert Mustacchi         (unsigned long) prefix->cf_section_ptr +
272*4d9fdb46SRobert Mustacchi         (unsigned long)prefix->cf_section_length);
27307dc1947SRichard Lowe }
27407dc1947SRichard Lowe #endif
27507dc1947SRichard Lowe 
276*4d9fdb46SRobert Mustacchi /*  Make the 'cieptr' consistent across .debug_frame and .eh_frame.
277*4d9fdb46SRobert Mustacchi     Calculate a pointer into section bytes given a cie_id in
278*4d9fdb46SRobert Mustacchi     an FDE header.
279*4d9fdb46SRobert Mustacchi 
280*4d9fdb46SRobert Mustacchi     In .debug_frame, the CIE_pointer is an offset in .debug_frame.
281*4d9fdb46SRobert Mustacchi 
282*4d9fdb46SRobert Mustacchi     In .eh_frame, the CIE Pointer is, when
283*4d9fdb46SRobert Mustacchi     cie_id_value subtracted from the
284*4d9fdb46SRobert Mustacchi     cie_id_addr, the address in memory of
285*4d9fdb46SRobert Mustacchi     a CIE length field.
286*4d9fdb46SRobert Mustacchi     Since cie_id_addr is the address of an FDE CIE_Pointer
287*4d9fdb46SRobert Mustacchi     field, cie_id_value for .eh_frame
288*4d9fdb46SRobert Mustacchi     has to account for the length-prefix.
289*4d9fdb46SRobert Mustacchi     so that the returned cieptr really points to
290*4d9fdb46SRobert Mustacchi     a  CIE length field. Whew!
291*4d9fdb46SRobert Mustacchi     Available documentation on this is just a bit
292*4d9fdb46SRobert Mustacchi     ambiguous, but this calculation is correct.
293*4d9fdb46SRobert Mustacchi */
29407dc1947SRichard Lowe 
295*4d9fdb46SRobert Mustacchi static Dwarf_Small *
get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,int use_gnu_cie_calc,Dwarf_Small * section_ptr,Dwarf_Small * cie_id_addr)296*4d9fdb46SRobert Mustacchi get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
297*4d9fdb46SRobert Mustacchi     int use_gnu_cie_calc,
298*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr,
299*4d9fdb46SRobert Mustacchi     Dwarf_Small * cie_id_addr)
300*4d9fdb46SRobert Mustacchi {
301*4d9fdb46SRobert Mustacchi     Dwarf_Small *cieptr = 0;
30207dc1947SRichard Lowe 
303*4d9fdb46SRobert Mustacchi     if (use_gnu_cie_calc) {
304*4d9fdb46SRobert Mustacchi         /*  cie_id value is offset, in section, of the cie_id itself, to
305*4d9fdb46SRobert Mustacchi             use vm ptr of the value, less the value, to get to the cie
306*4d9fdb46SRobert Mustacchi             header.  */
307*4d9fdb46SRobert Mustacchi         cieptr = cie_id_addr - cie_id_value;
308*4d9fdb46SRobert Mustacchi     } else {
309*4d9fdb46SRobert Mustacchi         /*  Traditional dwarf section offset is in cie_id */
310*4d9fdb46SRobert Mustacchi         cieptr = section_ptr + cie_id_value;
311*4d9fdb46SRobert Mustacchi     }
312*4d9fdb46SRobert Mustacchi     return cieptr;
313*4d9fdb46SRobert Mustacchi }
314*4d9fdb46SRobert Mustacchi 
315*4d9fdb46SRobert Mustacchi 
316*4d9fdb46SRobert Mustacchi 
317*4d9fdb46SRobert Mustacchi /*  Internal function called from various places to create
318*4d9fdb46SRobert Mustacchi     lists of CIEs and FDEs.  Not directly called
319*4d9fdb46SRobert Mustacchi     by consumer code */
32007dc1947SRichard Lowe int
_dwarf_get_fde_list_internal(Dwarf_Debug dbg,Dwarf_Cie ** cie_data,Dwarf_Signed * cie_element_count,Dwarf_Fde ** fde_data,Dwarf_Signed * fde_element_count,Dwarf_Small * section_ptr,Dwarf_Unsigned section_index,Dwarf_Unsigned section_length,Dwarf_Unsigned cie_id_value,int use_gnu_cie_calc,Dwarf_Error * error)32107dc1947SRichard Lowe _dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
32207dc1947SRichard Lowe     Dwarf_Signed * cie_element_count,
32307dc1947SRichard Lowe     Dwarf_Fde ** fde_data,
32407dc1947SRichard Lowe     Dwarf_Signed * fde_element_count,
32507dc1947SRichard Lowe     Dwarf_Small * section_ptr,
32607dc1947SRichard Lowe     Dwarf_Unsigned section_index,
32707dc1947SRichard Lowe     Dwarf_Unsigned section_length,
32807dc1947SRichard Lowe     Dwarf_Unsigned cie_id_value,
32907dc1947SRichard Lowe     int use_gnu_cie_calc, Dwarf_Error * error)
33007dc1947SRichard Lowe {
33107dc1947SRichard Lowe     /* Scans the debug_frame section. */
33207dc1947SRichard Lowe     Dwarf_Small *frame_ptr = section_ptr;
333*4d9fdb46SRobert Mustacchi     Dwarf_Small *section_ptr_end = section_ptr + section_length;
33407dc1947SRichard Lowe 
33507dc1947SRichard Lowe 
33607dc1947SRichard Lowe 
337*4d9fdb46SRobert Mustacchi     /*  New_cie points to the Cie being read, and head_cie_ptr and
338*4d9fdb46SRobert Mustacchi         cur_cie_ptr are used for chaining them up in sequence.
339*4d9fdb46SRobert Mustacchi         In case cie's are reused aggressively we need tail_cie_ptr
340*4d9fdb46SRobert Mustacchi         to add to the chain.  If we re-use an early cie
341*4d9fdb46SRobert Mustacchi         later on, that does not mean we chain a new cie to the early one,
342*4d9fdb46SRobert Mustacchi         we always chain it to the tail.  */
34307dc1947SRichard Lowe     Dwarf_Cie head_cie_ptr = NULL;
34407dc1947SRichard Lowe     Dwarf_Cie cur_cie_ptr = NULL;
34507dc1947SRichard Lowe     Dwarf_Cie tail_cie_ptr = NULL;
346*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned cie_count = 0;
34707dc1947SRichard Lowe 
348*4d9fdb46SRobert Mustacchi     /*  Points to a list of contiguous pointers to Dwarf_Cie structures.
349*4d9fdb46SRobert Mustacchi     */
35007dc1947SRichard Lowe     Dwarf_Cie *cie_list_ptr = 0;
35107dc1947SRichard Lowe 
35207dc1947SRichard Lowe 
353*4d9fdb46SRobert Mustacchi     /*  New_fde points to the Fde being created, and head_fde_ptr and
354*4d9fdb46SRobert Mustacchi         cur_fde_ptr are used to chain them up. */
35507dc1947SRichard Lowe     Dwarf_Fde head_fde_ptr = NULL;
35607dc1947SRichard Lowe     Dwarf_Fde cur_fde_ptr = NULL;
357*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned fde_count = 0;
35807dc1947SRichard Lowe 
359*4d9fdb46SRobert Mustacchi     /*  Points to a list of contiguous pointers to Dwarf_Fde structures.
360*4d9fdb46SRobert Mustacchi     */
36107dc1947SRichard Lowe     Dwarf_Fde *fde_list_ptr = NULL;
36207dc1947SRichard Lowe 
363*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned i = 0;
36407dc1947SRichard Lowe     int res = DW_DLV_ERROR;
36507dc1947SRichard Lowe 
36607dc1947SRichard Lowe     if (frame_ptr == 0) {
36707dc1947SRichard Lowe         return DW_DLV_NO_ENTRY;
36807dc1947SRichard Lowe     }
36907dc1947SRichard Lowe 
370*4d9fdb46SRobert Mustacchi     /*  We create the fde and cie arrays. Processing each CIE as we come
371*4d9fdb46SRobert Mustacchi         to it or as an FDE refers to it.  We cannot process 'late' CIEs
372*4d9fdb46SRobert Mustacchi         late as GNU .eh_frame complexities mean we need the whole CIE
373*4d9fdb46SRobert Mustacchi         before we can process the FDE correctly. */
374*4d9fdb46SRobert Mustacchi     while (frame_ptr < section_ptr_end) {
37507dc1947SRichard Lowe 
37607dc1947SRichard Lowe         struct cie_fde_prefix_s prefix;
37707dc1947SRichard Lowe 
378*4d9fdb46SRobert Mustacchi         /*  First read in the 'common prefix' to figure out what we are
379*4d9fdb46SRobert Mustacchi             to do with this entry. */
38007dc1947SRichard Lowe         memset(&prefix, 0, sizeof(prefix));
38107dc1947SRichard Lowe         res = dwarf_read_cie_fde_prefix(dbg,
382*4d9fdb46SRobert Mustacchi             frame_ptr, section_ptr,
383*4d9fdb46SRobert Mustacchi             section_index,
384*4d9fdb46SRobert Mustacchi             section_length, &prefix, error);
38507dc1947SRichard Lowe         if (res == DW_DLV_ERROR) {
386*4d9fdb46SRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr,
387*4d9fdb46SRobert Mustacchi                 head_cie_ptr);
38807dc1947SRichard Lowe             return res;
38907dc1947SRichard Lowe         }
390*4d9fdb46SRobert Mustacchi         if (res == DW_DLV_NO_ENTRY) {
39107dc1947SRichard Lowe             break;
392*4d9fdb46SRobert Mustacchi         }
39307dc1947SRichard Lowe         frame_ptr = prefix.cf_addr_after_prefix;
394*4d9fdb46SRobert Mustacchi         if (frame_ptr >= section_ptr_end) {
39507dc1947SRichard Lowe             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
39607dc1947SRichard Lowe             _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
39707dc1947SRichard Lowe             return DW_DLV_ERROR;
39807dc1947SRichard Lowe         }
39907dc1947SRichard Lowe 
40007dc1947SRichard Lowe         if (prefix.cf_cie_id == cie_id_value) {
40107dc1947SRichard Lowe             /* This is a CIE.  */
40207dc1947SRichard Lowe             Dwarf_Cie cie_ptr_to_use = 0;
403*4d9fdb46SRobert Mustacchi             int resc = 0;
40407dc1947SRichard Lowe 
405*4d9fdb46SRobert Mustacchi             resc = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
406*4d9fdb46SRobert Mustacchi                 cur_cie_ptr,
407*4d9fdb46SRobert Mustacchi                 &cie_ptr_to_use,
408*4d9fdb46SRobert Mustacchi                 head_cie_ptr);
409*4d9fdb46SRobert Mustacchi             if (resc == DW_DLV_OK) {
41007dc1947SRichard Lowe                 cur_cie_ptr = cie_ptr_to_use;
41107dc1947SRichard Lowe                 /* Ok. Seen already. */
412*4d9fdb46SRobert Mustacchi             } else if (resc == DW_DLV_NO_ENTRY) {
41307dc1947SRichard Lowe                 /* CIE before its FDE in this case. */
414*4d9fdb46SRobert Mustacchi                 resc = dwarf_create_cie_from_after_start(dbg,
415*4d9fdb46SRobert Mustacchi                     &prefix,
416*4d9fdb46SRobert Mustacchi                     section_ptr,
417*4d9fdb46SRobert Mustacchi                     frame_ptr,
418*4d9fdb46SRobert Mustacchi                     section_ptr_end,
419*4d9fdb46SRobert Mustacchi                     cie_count,
420*4d9fdb46SRobert Mustacchi                     use_gnu_cie_calc,
421*4d9fdb46SRobert Mustacchi                     &cie_ptr_to_use,
422*4d9fdb46SRobert Mustacchi                     error);
423*4d9fdb46SRobert Mustacchi                 if (resc != DW_DLV_OK) {
42407dc1947SRichard Lowe                     dealloc_fde_cie_list_internal(head_fde_ptr,
425*4d9fdb46SRobert Mustacchi                         head_cie_ptr);
426*4d9fdb46SRobert Mustacchi                     return resc;
42707dc1947SRichard Lowe                 }
42807dc1947SRichard Lowe                 cie_count++;
42907dc1947SRichard Lowe                 chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
430*4d9fdb46SRobert Mustacchi                     &tail_cie_ptr);
43107dc1947SRichard Lowe                 cur_cie_ptr = tail_cie_ptr;
43207dc1947SRichard Lowe             } else {            /* res == DW_DLV_ERROR */
43307dc1947SRichard Lowe 
43407dc1947SRichard Lowe                 dealloc_fde_cie_list_internal(head_fde_ptr,
435*4d9fdb46SRobert Mustacchi                     head_cie_ptr);
436*4d9fdb46SRobert Mustacchi                 return resc;
43707dc1947SRichard Lowe             }
43807dc1947SRichard Lowe             frame_ptr = cie_ptr_to_use->ci_cie_start +
43907dc1947SRichard Lowe                 cie_ptr_to_use->ci_length +
44007dc1947SRichard Lowe                 cie_ptr_to_use->ci_length_size +
44107dc1947SRichard Lowe                 cie_ptr_to_use->ci_extension_size;
44207dc1947SRichard Lowe             continue;
44307dc1947SRichard Lowe         } else {
444*4d9fdb46SRobert Mustacchi             /*  This is an FDE, Frame Description Entry, see the Dwarf
445*4d9fdb46SRobert Mustacchi                 Spec, (section 6.4.1 in DWARF2, DWARF3, DWARF4, ...)
446*4d9fdb46SRobert Mustacchi                 Or see the .eh_frame specification,
447*4d9fdb46SRobert Mustacchi                 from the Linux Foundation (or other source).  */
448*4d9fdb46SRobert Mustacchi             int resf = DW_DLV_ERROR;
44907dc1947SRichard Lowe             Dwarf_Cie cie_ptr_to_use = 0;
45007dc1947SRichard Lowe             Dwarf_Fde fde_ptr_to_use = 0;
451*4d9fdb46SRobert Mustacchi             Dwarf_Small *cieptr_val = 0;
452*4d9fdb46SRobert Mustacchi 
453*4d9fdb46SRobert Mustacchi             cieptr_val = get_cieptr_given_offset(prefix.cf_cie_id,
454*4d9fdb46SRobert Mustacchi                 use_gnu_cie_calc,
455*4d9fdb46SRobert Mustacchi                 section_ptr,
456*4d9fdb46SRobert Mustacchi                 prefix.cf_cie_id_addr);
457*4d9fdb46SRobert Mustacchi             resf = dwarf_find_existing_cie_ptr(cieptr_val,
458*4d9fdb46SRobert Mustacchi                 cur_cie_ptr,
459*4d9fdb46SRobert Mustacchi                 &cie_ptr_to_use,
460*4d9fdb46SRobert Mustacchi                 head_cie_ptr);
461*4d9fdb46SRobert Mustacchi             if (resf == DW_DLV_OK) {
46207dc1947SRichard Lowe                 cur_cie_ptr = cie_ptr_to_use;
46307dc1947SRichard Lowe                 /* Ok. Seen CIE already. */
464*4d9fdb46SRobert Mustacchi             } else if (resf == DW_DLV_NO_ENTRY) {
465*4d9fdb46SRobert Mustacchi                 resf = dwarf_create_cie_from_start(dbg,
466*4d9fdb46SRobert Mustacchi                     cieptr_val,
467*4d9fdb46SRobert Mustacchi                     section_ptr,
468*4d9fdb46SRobert Mustacchi                     section_index,
469*4d9fdb46SRobert Mustacchi                     section_length,
470*4d9fdb46SRobert Mustacchi                     section_ptr_end,
471*4d9fdb46SRobert Mustacchi                     cie_id_value,
472*4d9fdb46SRobert Mustacchi                     cie_count,
473*4d9fdb46SRobert Mustacchi                     use_gnu_cie_calc,
474*4d9fdb46SRobert Mustacchi                     &cie_ptr_to_use,
475*4d9fdb46SRobert Mustacchi                     error);
476*4d9fdb46SRobert Mustacchi                 if (resf == DW_DLV_ERROR) {
47707dc1947SRichard Lowe                     dealloc_fde_cie_list_internal(head_fde_ptr,
478*4d9fdb46SRobert Mustacchi                         head_cie_ptr);
479*4d9fdb46SRobert Mustacchi                     return resf;
480*4d9fdb46SRobert Mustacchi                 } else if (resf == DW_DLV_NO_ENTRY) {
481*4d9fdb46SRobert Mustacchi                     return resf;
48207dc1947SRichard Lowe                 }
48307dc1947SRichard Lowe                 ++cie_count;
48407dc1947SRichard Lowe                 chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
485*4d9fdb46SRobert Mustacchi                     &tail_cie_ptr);
48607dc1947SRichard Lowe                 cur_cie_ptr = tail_cie_ptr;
48707dc1947SRichard Lowe 
48807dc1947SRichard Lowe             } else {
48907dc1947SRichard Lowe                 /* DW_DLV_ERROR */
490*4d9fdb46SRobert Mustacchi                 return resf;
49107dc1947SRichard Lowe             }
49207dc1947SRichard Lowe 
493*4d9fdb46SRobert Mustacchi             resf = dwarf_create_fde_from_after_start(dbg,
494*4d9fdb46SRobert Mustacchi                 &prefix,
495*4d9fdb46SRobert Mustacchi                 section_ptr,
496*4d9fdb46SRobert Mustacchi                 frame_ptr,
497*4d9fdb46SRobert Mustacchi                 section_ptr_end,
498*4d9fdb46SRobert Mustacchi                 use_gnu_cie_calc,
499*4d9fdb46SRobert Mustacchi                 cie_ptr_to_use,
500*4d9fdb46SRobert Mustacchi                 &fde_ptr_to_use,
501*4d9fdb46SRobert Mustacchi                 error);
502*4d9fdb46SRobert Mustacchi             if (resf == DW_DLV_ERROR) {
503*4d9fdb46SRobert Mustacchi                 dealloc_fde_cie_list_internal(head_fde_ptr,
504*4d9fdb46SRobert Mustacchi                     head_cie_ptr);
505*4d9fdb46SRobert Mustacchi                 return resf;
506*4d9fdb46SRobert Mustacchi             } else if (resf == DW_DLV_NO_ENTRY) {
507*4d9fdb46SRobert Mustacchi                 /* impossible. */
508*4d9fdb46SRobert Mustacchi                 return resf;
50907dc1947SRichard Lowe             }
51007dc1947SRichard Lowe             chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
51107dc1947SRichard Lowe             fde_count++;
51207dc1947SRichard Lowe             /* ASSERT: DW_DLV_OK. */
513*4d9fdb46SRobert Mustacchi             frame_ptr = cur_fde_ptr->fd_fde_start +
514*4d9fdb46SRobert Mustacchi                 cur_fde_ptr->fd_length +
515*4d9fdb46SRobert Mustacchi                 cur_fde_ptr->fd_length_size +
516*4d9fdb46SRobert Mustacchi                 cur_fde_ptr->fd_extension_size;
517*4d9fdb46SRobert Mustacchi             if (frame_ptr  <  fde_ptr_to_use->fd_fde_instr_start) {
518*4d9fdb46SRobert Mustacchi                 /*  Sanity check. With a really short fde instruction
519*4d9fdb46SRobert Mustacchi                     set and address_size we think is 8
520*4d9fdb46SRobert Mustacchi                     as it is ELF64 (but is
521*4d9fdb46SRobert Mustacchi                     really 4, as in DWARF{2,3} where we have
522*4d9fdb46SRobert Mustacchi                     no FDE address_size) we emit an error.
523*4d9fdb46SRobert Mustacchi                     This error means things will not go well. */
524*4d9fdb46SRobert Mustacchi                 dealloc_fde_cie_list_internal(head_fde_ptr,
525*4d9fdb46SRobert Mustacchi                     head_cie_ptr);
526*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg,error,
527*4d9fdb46SRobert Mustacchi                     DW_DLE_DEBUG_FRAME_POSSIBLE_ADDRESS_BOTCH);
528*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
529*4d9fdb46SRobert Mustacchi             }
53007dc1947SRichard Lowe             continue;
53107dc1947SRichard Lowe         }
53207dc1947SRichard Lowe     }
533*4d9fdb46SRobert Mustacchi     /*  Now build list of CIEs from the list. If there are no CIEs
534*4d9fdb46SRobert Mustacchi         there should be no FDEs. */
53507dc1947SRichard Lowe     if (cie_count > 0) {
53607dc1947SRichard Lowe         cie_list_ptr = (Dwarf_Cie *)
53707dc1947SRichard Lowe             _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
53807dc1947SRichard Lowe     } else {
539*4d9fdb46SRobert Mustacchi         if (fde_count > 0) {
54007dc1947SRichard Lowe             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
54107dc1947SRichard Lowe             _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
54207dc1947SRichard Lowe             return DW_DLV_ERROR;
54307dc1947SRichard Lowe         }
54407dc1947SRichard Lowe         dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
54507dc1947SRichard Lowe         return DW_DLV_NO_ENTRY;
54607dc1947SRichard Lowe     }
54707dc1947SRichard Lowe     if (cie_list_ptr == NULL) {
54807dc1947SRichard Lowe         dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
54907dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
55007dc1947SRichard Lowe         return DW_DLV_ERROR;
55107dc1947SRichard Lowe     }
552*4d9fdb46SRobert Mustacchi     if (!head_cie_ptr) {
553*4d9fdb46SRobert Mustacchi         /*  Should be impossible. */
554*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error,DW_DLE_DEBUGFRAME_ERROR);
555*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
556*4d9fdb46SRobert Mustacchi     }
55707dc1947SRichard Lowe     cur_cie_ptr = head_cie_ptr;
55807dc1947SRichard Lowe     for (i = 0; i < cie_count; i++) {
55907dc1947SRichard Lowe         *(cie_list_ptr + i) = cur_cie_ptr;
56007dc1947SRichard Lowe         cur_cie_ptr = cur_cie_ptr->ci_next;
56107dc1947SRichard Lowe     }
56207dc1947SRichard Lowe 
563*4d9fdb46SRobert Mustacchi     /*  Now build array of FDEs from the list.
564*4d9fdb46SRobert Mustacchi         With orphan CIEs (meaning no FDEs)
565*4d9fdb46SRobert Mustacchi         lets not return DW_DLV_NO_ENTRY */
56607dc1947SRichard Lowe     if (fde_count > 0) {
56707dc1947SRichard Lowe         fde_list_ptr = (Dwarf_Fde *)
56807dc1947SRichard Lowe             _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
56907dc1947SRichard Lowe     }
57007dc1947SRichard Lowe 
57107dc1947SRichard Lowe     /* It is ok if fde_list_ptr is NULL, we just have no fdes. */
57207dc1947SRichard Lowe     cur_fde_ptr = head_fde_ptr;
57307dc1947SRichard Lowe     for (i = 0; i < fde_count; i++) {
57407dc1947SRichard Lowe         *(fde_list_ptr + i) = cur_fde_ptr;
57507dc1947SRichard Lowe         cur_fde_ptr = cur_fde_ptr->fd_next;
57607dc1947SRichard Lowe     }
57707dc1947SRichard Lowe 
57807dc1947SRichard Lowe 
57907dc1947SRichard Lowe     /* Return arguments. */
58007dc1947SRichard Lowe     *cie_data = cie_list_ptr;
58107dc1947SRichard Lowe     *cie_element_count = cie_count;
58207dc1947SRichard Lowe 
58307dc1947SRichard Lowe     *fde_data = fde_list_ptr;
58407dc1947SRichard Lowe     *fde_element_count = fde_count;
585*4d9fdb46SRobert Mustacchi     if (use_gnu_cie_calc) {
586*4d9fdb46SRobert Mustacchi         dbg->de_fde_data_eh = fde_list_ptr;
587*4d9fdb46SRobert Mustacchi         dbg->de_fde_count_eh = fde_count;
588*4d9fdb46SRobert Mustacchi         dbg->de_cie_data_eh = cie_list_ptr;
589*4d9fdb46SRobert Mustacchi         dbg->de_cie_count_eh = cie_count;
59007dc1947SRichard Lowe     } else {
591*4d9fdb46SRobert Mustacchi         dbg->de_fde_data = fde_list_ptr;
592*4d9fdb46SRobert Mustacchi         dbg->de_fde_count = fde_count;
593*4d9fdb46SRobert Mustacchi         dbg->de_cie_data = cie_list_ptr;
594*4d9fdb46SRobert Mustacchi         dbg->de_cie_count = cie_count;
59507dc1947SRichard Lowe     }
59607dc1947SRichard Lowe 
597*4d9fdb46SRobert Mustacchi     /*  Sort the list by the address so that dwarf_get_fde_at_pc() can
598*4d9fdb46SRobert Mustacchi         binary search this list.  */
599*4d9fdb46SRobert Mustacchi     if (fde_count > 0) {
60007dc1947SRichard Lowe         qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
601*4d9fdb46SRobert Mustacchi             qsort_compare);
60207dc1947SRichard Lowe     }
60307dc1947SRichard Lowe 
60407dc1947SRichard Lowe     return (DW_DLV_OK);
60507dc1947SRichard Lowe }
60607dc1947SRichard Lowe 
607*4d9fdb46SRobert Mustacchi /*  Internal function, not called by consumer code.
608*4d9fdb46SRobert Mustacchi     'prefix' has accumulated the info up thru the cie-id
609*4d9fdb46SRobert Mustacchi     and now we consume the rest and build a Dwarf_Cie_s structure.
61007dc1947SRichard Lowe */
61107dc1947SRichard Lowe int
dwarf_create_cie_from_after_start(Dwarf_Debug dbg,struct cie_fde_prefix_s * prefix,Dwarf_Small * section_pointer,Dwarf_Small * frame_ptr,Dwarf_Small * section_ptr_end,Dwarf_Unsigned cie_count,int use_gnu_cie_calc,Dwarf_Cie * cie_ptr_out,Dwarf_Error * error)61207dc1947SRichard Lowe dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
61307dc1947SRichard Lowe     struct cie_fde_prefix_s *prefix,
61407dc1947SRichard Lowe     Dwarf_Small * section_pointer,
61507dc1947SRichard Lowe     Dwarf_Small * frame_ptr,
616*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
61707dc1947SRichard Lowe     Dwarf_Unsigned cie_count,
61807dc1947SRichard Lowe     int use_gnu_cie_calc,
61907dc1947SRichard Lowe     Dwarf_Cie * cie_ptr_out,
62007dc1947SRichard Lowe     Dwarf_Error * error)
62107dc1947SRichard Lowe {
62207dc1947SRichard Lowe     Dwarf_Cie new_cie = 0;
62307dc1947SRichard Lowe 
624*4d9fdb46SRobert Mustacchi     /*  egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
625*4d9fdb46SRobert Mustacchi         -1 (in .debug_frame). .eh_frame not quite identical to
626*4d9fdb46SRobert Mustacchi         .debug_frame */
627*4d9fdb46SRobert Mustacchi     /*  We here default the address size as it is not present
628*4d9fdb46SRobert Mustacchi         in DWARF2 or DWARF3 cie data, below we set it right if
629*4d9fdb46SRobert Mustacchi         it is present. */
63007dc1947SRichard Lowe     Dwarf_Half address_size = dbg->de_pointer_size;
63107dc1947SRichard Lowe     Dwarf_Small *augmentation = 0;
63207dc1947SRichard Lowe     Dwarf_Half segment_size = 0;
633*4d9fdb46SRobert Mustacchi     Dwarf_Signed data_alignment_factor = -1;
634*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned code_alignment_factor = 4;
63507dc1947SRichard Lowe     Dwarf_Unsigned return_address_register = 31;
63607dc1947SRichard Lowe     int local_length_size = 0;
637*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned leb128_length = 0;
63807dc1947SRichard Lowe     Dwarf_Unsigned cie_aug_data_len = 0;
63907dc1947SRichard Lowe     Dwarf_Small *cie_aug_data = 0;
64007dc1947SRichard Lowe     Dwarf_Addr gnu_personality_handler_addr = 0;
64107dc1947SRichard Lowe     unsigned char gnu_personality_handler_encoding = 0;
64207dc1947SRichard Lowe     unsigned char gnu_lsda_encoding = 0;
64307dc1947SRichard Lowe     unsigned char gnu_fde_begin_encoding = 0;
644*4d9fdb46SRobert Mustacchi     int res = 0;
645*4d9fdb46SRobert Mustacchi     Dwarf_Small version = 0;
64607dc1947SRichard Lowe 
64707dc1947SRichard Lowe 
64807dc1947SRichard Lowe     enum Dwarf_augmentation_type augt = aug_unknown;
64907dc1947SRichard Lowe 
650*4d9fdb46SRobert Mustacchi     /*  This is a CIE, Common Information Entry: See the dwarf spec,
651*4d9fdb46SRobert Mustacchi         section 6.4.1 */
652*4d9fdb46SRobert Mustacchi     if (frame_ptr >= section_ptr_end) {
653*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
654*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
655*4d9fdb46SRobert Mustacchi     }
656*4d9fdb46SRobert Mustacchi     version = *(Dwarf_Small *) frame_ptr;
65707dc1947SRichard Lowe 
658*4d9fdb46SRobert Mustacchi     if ((frame_ptr+2) >= section_ptr_end) {
659*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
660*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
661*4d9fdb46SRobert Mustacchi     }
66207dc1947SRichard Lowe 
66307dc1947SRichard Lowe     frame_ptr++;
66407dc1947SRichard Lowe     if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
665*4d9fdb46SRobert Mustacchi         version != DW_CIE_VERSION4 && version != DW_CIE_VERSION5) {
66607dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
66707dc1947SRichard Lowe         return (DW_DLV_ERROR);
66807dc1947SRichard Lowe     }
66907dc1947SRichard Lowe 
67007dc1947SRichard Lowe     augmentation = frame_ptr;
671*4d9fdb46SRobert Mustacchi 
672*4d9fdb46SRobert Mustacchi     res = _dwarf_check_string_valid(dbg,section_pointer,
673*4d9fdb46SRobert Mustacchi         frame_ptr,section_ptr_end,
674*4d9fdb46SRobert Mustacchi         DW_DLE_AUGMENTATION_STRING_OFF_END,error);
675*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
676*4d9fdb46SRobert Mustacchi         return res;
677*4d9fdb46SRobert Mustacchi     }
67807dc1947SRichard Lowe     frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
679*4d9fdb46SRobert Mustacchi     if (frame_ptr  >= section_ptr_end) {
680*4d9fdb46SRobert Mustacchi         _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
681*4d9fdb46SRobert Mustacchi             "DW_DLE_DEBUG_FRAME_LENGTH_BAD: following any "
682*4d9fdb46SRobert Mustacchi             "augmentation field we have run off the end of the section "
683*4d9fdb46SRobert Mustacchi             "with the CIE incomplete.  Corrupt Dwarf");
684*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
685*4d9fdb46SRobert Mustacchi     }
68607dc1947SRichard Lowe     augt = _dwarf_get_augmentation_type(dbg,
687*4d9fdb46SRobert Mustacchi         augmentation, use_gnu_cie_calc);
68807dc1947SRichard Lowe     if (augt == aug_eh) {
68907dc1947SRichard Lowe         /* REFERENCED *//* Not used in this instance */
690*4d9fdb46SRobert Mustacchi         UNUSEDARG Dwarf_Unsigned exception_table_addr;
69107dc1947SRichard Lowe 
692*4d9fdb46SRobert Mustacchi         if ((frame_ptr+local_length_size)  >= section_ptr_end) {
693*4d9fdb46SRobert Mustacchi             _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
694*4d9fdb46SRobert Mustacchi                 "DW_DLE_DEBUG_FRAME_LENGTH_BAD: following "
695*4d9fdb46SRobert Mustacchi                 "type field we have run off the end of the section "
696*4d9fdb46SRobert Mustacchi                 "with the CIE incomplete.  Corrupt Dwarf");
697*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
698*4d9fdb46SRobert Mustacchi         }
69907dc1947SRichard Lowe         /* this is per egcs-1.1.2 as on RH 6.0 */
700*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, exception_table_addr,
701*4d9fdb46SRobert Mustacchi             Dwarf_Unsigned, frame_ptr, local_length_size,
702*4d9fdb46SRobert Mustacchi             error,section_ptr_end);
70307dc1947SRichard Lowe         frame_ptr += local_length_size;
70407dc1947SRichard Lowe     }
70507dc1947SRichard Lowe     {
70607dc1947SRichard Lowe         Dwarf_Unsigned lreg = 0;
70707dc1947SRichard Lowe         unsigned long size = 0;
70807dc1947SRichard Lowe 
709*4d9fdb46SRobert Mustacchi         if (version == DW_CIE_VERSION4) {
710*4d9fdb46SRobert Mustacchi             if ((frame_ptr+2)  >= section_ptr_end) {
711*4d9fdb46SRobert Mustacchi                 _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
712*4d9fdb46SRobert Mustacchi                     "DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
713*4d9fdb46SRobert Mustacchi                     "We would run off the end of the section "
714*4d9fdb46SRobert Mustacchi                     "in a DWARF4 cie header.  Corrupt Dwarf");
715*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
716*4d9fdb46SRobert Mustacchi             }
71707dc1947SRichard Lowe             address_size = *((unsigned char *)frame_ptr);
718*4d9fdb46SRobert Mustacchi             if (address_size  <  1) {
719*4d9fdb46SRobert Mustacchi                 _dwarf_error_string(dbg, error, DW_DLE_ADDRESS_SIZE_ZERO,
720*4d9fdb46SRobert Mustacchi                     "DW_DLE_ADDRESS_SIZE_ZERO: bad addres size "
721*4d9fdb46SRobert Mustacchi                     "for a DWARF4 cie header");
722*4d9fdb46SRobert Mustacchi                 return (DW_DLV_ERROR);
723*4d9fdb46SRobert Mustacchi             }
724*4d9fdb46SRobert Mustacchi             if (address_size  > sizeof(Dwarf_Addr)) {
725*4d9fdb46SRobert Mustacchi                 _dwarf_create_address_size_dwarf_error(dbg,
726*4d9fdb46SRobert Mustacchi                     error,address_size,
727*4d9fdb46SRobert Mustacchi                     DW_DLE_ADDRESS_SIZE_ERROR,
728*4d9fdb46SRobert Mustacchi                     "DW_DLE_ADDRESS_SIZE_ERROR..:");
729*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
730*4d9fdb46SRobert Mustacchi             }
731*4d9fdb46SRobert Mustacchi             if ((frame_ptr+2)  >= section_ptr_end) {
732*4d9fdb46SRobert Mustacchi                 _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
733*4d9fdb46SRobert Mustacchi                     "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
734*4d9fdb46SRobert Mustacchi                     " of a CIE header. Corrupt DWARF4");
735*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
736*4d9fdb46SRobert Mustacchi             }
73707dc1947SRichard Lowe             ++frame_ptr;
73807dc1947SRichard Lowe             segment_size = *((unsigned char *)frame_ptr);
73907dc1947SRichard Lowe             ++frame_ptr;
740*4d9fdb46SRobert Mustacchi             if (segment_size  > sizeof(Dwarf_Addr)) {
741*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_SEGMENT_SIZE_BAD);
742*4d9fdb46SRobert Mustacchi                 return (DW_DLV_ERROR);
743*4d9fdb46SRobert Mustacchi             }
74407dc1947SRichard Lowe         }
74507dc1947SRichard Lowe 
746*4d9fdb46SRobert Mustacchi         /* Not a great test. But the DECODE* do checking so ok.  */
747*4d9fdb46SRobert Mustacchi         if ((frame_ptr+2)  >= section_ptr_end) {
748*4d9fdb46SRobert Mustacchi             _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
749*4d9fdb46SRobert Mustacchi                 "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
750*4d9fdb46SRobert Mustacchi                 " of a CIE header before the code alignment value "
751*4d9fdb46SRobert Mustacchi                 "read. Corrupt DWARF");
752*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
753*4d9fdb46SRobert Mustacchi         }
754*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_CK(frame_ptr, lreg,dbg,error,section_ptr_end);
755*4d9fdb46SRobert Mustacchi         code_alignment_factor = (Dwarf_Unsigned) lreg;
756*4d9fdb46SRobert Mustacchi         res = (Dwarf_Signed) _dwarf_decode_s_leb128_chk(frame_ptr,
757*4d9fdb46SRobert Mustacchi             &leb128_length,&data_alignment_factor,section_ptr_end);
758*4d9fdb46SRobert Mustacchi         if(res != DW_DLV_OK) {
759*4d9fdb46SRobert Mustacchi             return res;
760*4d9fdb46SRobert Mustacchi         }
76107dc1947SRichard Lowe         frame_ptr = frame_ptr + leb128_length;
762*4d9fdb46SRobert Mustacchi         /* Not a great test. FIXME */
763*4d9fdb46SRobert Mustacchi         if ((frame_ptr+1)  >= section_ptr_end) {
764*4d9fdb46SRobert Mustacchi             _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
765*4d9fdb46SRobert Mustacchi                 "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Running off the end "
766*4d9fdb46SRobert Mustacchi                 "of a CIE header before the return address register "
767*4d9fdb46SRobert Mustacchi                 "number read. Corrupt DWARF");
76807dc1947SRichard Lowe 
769*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
770*4d9fdb46SRobert Mustacchi         }
771*4d9fdb46SRobert Mustacchi         res = _dwarf_get_return_address_reg(frame_ptr, version,
772*4d9fdb46SRobert Mustacchi             dbg,section_ptr_end, &size,&return_address_register,error);
773*4d9fdb46SRobert Mustacchi         if(res != DW_DLV_OK) {
774*4d9fdb46SRobert Mustacchi             return res;
775*4d9fdb46SRobert Mustacchi         }
77607dc1947SRichard Lowe         if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
77707dc1947SRichard Lowe             _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
77807dc1947SRichard Lowe             return (DW_DLV_ERROR);
77907dc1947SRichard Lowe         }
78007dc1947SRichard Lowe         frame_ptr += size;
781*4d9fdb46SRobert Mustacchi         if ((frame_ptr)  > section_ptr_end) {
782*4d9fdb46SRobert Mustacchi             _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
783*4d9fdb46SRobert Mustacchi                 "DW_DLE_DEBUG_FRAME_LENGTH_BAD: Past the end "
784*4d9fdb46SRobert Mustacchi                 "of a CIE header before reading the augmentation string."
785*4d9fdb46SRobert Mustacchi                 " Corrupt DWARF");
786*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
787*4d9fdb46SRobert Mustacchi         }
78807dc1947SRichard Lowe     }
78907dc1947SRichard Lowe     switch (augt) {
79007dc1947SRichard Lowe     case aug_empty_string:
79107dc1947SRichard Lowe         break;
79207dc1947SRichard Lowe     case aug_irix_mti_v1:
79307dc1947SRichard Lowe         break;
79407dc1947SRichard Lowe     case aug_irix_exception_table:{
795*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned lreg = 0;
796*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned length_of_augmented_fields;
79707dc1947SRichard Lowe 
798*4d9fdb46SRobert Mustacchi         /* Decode the length of augmented fields. */
799*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_CK(frame_ptr, lreg,dbg,error,section_ptr_end);
800*4d9fdb46SRobert Mustacchi         length_of_augmented_fields = (Dwarf_Unsigned) lreg;
801*4d9fdb46SRobert Mustacchi         /* set the frame_ptr to point at the instruction start. */
802*4d9fdb46SRobert Mustacchi         frame_ptr += length_of_augmented_fields;
80307dc1947SRichard Lowe         }
80407dc1947SRichard Lowe         break;
80507dc1947SRichard Lowe 
80607dc1947SRichard Lowe     case aug_eh:{
807*4d9fdb46SRobert Mustacchi         int err = 0;
808*4d9fdb46SRobert Mustacchi         unsigned long increment = 0;
80907dc1947SRichard Lowe 
810*4d9fdb46SRobert Mustacchi         if (!use_gnu_cie_calc) {
811*4d9fdb46SRobert Mustacchi             /* This should be impossible. */
812*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
813*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
814*4d9fdb46SRobert Mustacchi         }
81507dc1947SRichard Lowe 
816*4d9fdb46SRobert Mustacchi         err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
817*4d9fdb46SRobert Mustacchi             augt,
818*4d9fdb46SRobert Mustacchi             section_ptr_end,
819*4d9fdb46SRobert Mustacchi             (char *) augmentation,error);
820*4d9fdb46SRobert Mustacchi         if (err == DW_DLV_ERROR) {
821*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
822*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
823*4d9fdb46SRobert Mustacchi         }
824*4d9fdb46SRobert Mustacchi         frame_ptr += increment;
82507dc1947SRichard Lowe         }
826*4d9fdb46SRobert Mustacchi         break;
82707dc1947SRichard Lowe     case aug_gcc_eh_z:{
828*4d9fdb46SRobert Mustacchi         /*  Here we have Augmentation Data Length (uleb128) followed
829*4d9fdb46SRobert Mustacchi             by Augmentation Data bytes (not a string). */
830*4d9fdb46SRobert Mustacchi         int resz = DW_DLV_ERROR;
831*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned adlen = 0;
832*4d9fdb46SRobert Mustacchi 
833*4d9fdb46SRobert Mustacchi         /* Not a great test. FIXME */
834*4d9fdb46SRobert Mustacchi         if ((frame_ptr+1)  > section_ptr_end) {
835*4d9fdb46SRobert Mustacchi             _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
836*4d9fdb46SRobert Mustacchi                 "DW_DLE_AUG_DATA_LENGTH_BAD: The "
837*4d9fdb46SRobert Mustacchi                 "gcc .eh_frame augmentation data "
838*4d9fdb46SRobert Mustacchi                 "cannot be read. Out of room in the section."
839*4d9fdb46SRobert Mustacchi                 " Corrupt DWARF.");
840*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
841*4d9fdb46SRobert Mustacchi         }
842*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
843*4d9fdb46SRobert Mustacchi             dbg,error,section_ptr_end);
844*4d9fdb46SRobert Mustacchi         cie_aug_data_len = adlen;
845*4d9fdb46SRobert Mustacchi         cie_aug_data = frame_ptr;
846*4d9fdb46SRobert Mustacchi         if (adlen) {
847*4d9fdb46SRobert Mustacchi             Dwarf_Small *cie_aug_data_end = cie_aug_data+adlen;
848*4d9fdb46SRobert Mustacchi             if (cie_aug_data_end < cie_aug_data ||
849*4d9fdb46SRobert Mustacchi                 cie_aug_data_end > section_ptr_end) {
850*4d9fdb46SRobert Mustacchi                 dwarfstring m;
851*4d9fdb46SRobert Mustacchi 
852*4d9fdb46SRobert Mustacchi                 dwarfstring_constructor(&m);
853*4d9fdb46SRobert Mustacchi                 dwarfstring_append_printf_u(&m,
854*4d9fdb46SRobert Mustacchi                     "DW_DLE_AUG_DATA_LENGTH_BAD: The "
855*4d9fdb46SRobert Mustacchi                     "gcc .eh_frame augmentation data "
856*4d9fdb46SRobert Mustacchi                     "length of %" DW_PR_DUu " is too long to"
857*4d9fdb46SRobert Mustacchi                     " fit in the section.",adlen);
858*4d9fdb46SRobert Mustacchi                 _dwarf_error_string(dbg, error,
859*4d9fdb46SRobert Mustacchi                     DW_DLE_AUG_DATA_LENGTH_BAD,
860*4d9fdb46SRobert Mustacchi                     dwarfstring_string(&m));
861*4d9fdb46SRobert Mustacchi                 dwarfstring_destructor(&m);
862*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
86307dc1947SRichard Lowe             }
86407dc1947SRichard Lowe         }
865*4d9fdb46SRobert Mustacchi         resz = gnu_aug_encodings(dbg,
866*4d9fdb46SRobert Mustacchi             (char *) augmentation,
867*4d9fdb46SRobert Mustacchi             cie_aug_data,
868*4d9fdb46SRobert Mustacchi             cie_aug_data_len,
869*4d9fdb46SRobert Mustacchi             address_size,
870*4d9fdb46SRobert Mustacchi             &gnu_personality_handler_encoding,
871*4d9fdb46SRobert Mustacchi             &gnu_lsda_encoding,
872*4d9fdb46SRobert Mustacchi             &gnu_fde_begin_encoding,
873*4d9fdb46SRobert Mustacchi             &gnu_personality_handler_addr,
874*4d9fdb46SRobert Mustacchi             error);
875*4d9fdb46SRobert Mustacchi         if (resz != DW_DLV_OK) {
876*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,
877*4d9fdb46SRobert Mustacchi                 DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
878*4d9fdb46SRobert Mustacchi             return resz;
879*4d9fdb46SRobert Mustacchi         }
880*4d9fdb46SRobert Mustacchi         frame_ptr += adlen;
881*4d9fdb46SRobert Mustacchi         }
882*4d9fdb46SRobert Mustacchi         break;
88307dc1947SRichard Lowe     case aug_armcc:
88407dc1947SRichard Lowe         break;
88507dc1947SRichard Lowe     default:{
886*4d9fdb46SRobert Mustacchi         /*  We do not understand the augmentation string. No
887*4d9fdb46SRobert Mustacchi             assumption can be made about any fields other than what
888*4d9fdb46SRobert Mustacchi             we have already read. */
889*4d9fdb46SRobert Mustacchi         frame_ptr = prefix->cf_start_addr +
890*4d9fdb46SRobert Mustacchi             prefix->cf_length + prefix->cf_local_length_size
891*4d9fdb46SRobert Mustacchi             + prefix->cf_local_extension_size;
892*4d9fdb46SRobert Mustacchi         /*  FIX -- What are the values of data_alignment_factor,
893*4d9fdb46SRobert Mustacchi             code_alignement_factor, return_address_register and
894*4d9fdb46SRobert Mustacchi             instruction start? They were clearly uninitalized in the
895*4d9fdb46SRobert Mustacchi             previous version and I am leaving them the same way. */
896*4d9fdb46SRobert Mustacchi         }
897*4d9fdb46SRobert Mustacchi         if ((frame_ptr)  > section_ptr_end) {
898*4d9fdb46SRobert Mustacchi             _dwarf_error_string(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD,
899*4d9fdb46SRobert Mustacchi                 "DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
900*4d9fdb46SRobert Mustacchi                 "Reading an unknown type of augmentation string "
901*4d9fdb46SRobert Mustacchi                 "run off the end of the section. Corrupt DWARF.");
902*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
90307dc1947SRichard Lowe         }
904*4d9fdb46SRobert Mustacchi         break;
90507dc1947SRichard Lowe     }                           /* End switch on augmentation type. */
90607dc1947SRichard Lowe 
90707dc1947SRichard Lowe     new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
90807dc1947SRichard Lowe     if (new_cie == NULL) {
90907dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
91007dc1947SRichard Lowe         return (DW_DLV_ERROR);
91107dc1947SRichard Lowe     }
91207dc1947SRichard Lowe 
91307dc1947SRichard Lowe     new_cie->ci_cie_version_number = version;
91407dc1947SRichard Lowe     new_cie->ci_initial_table = NULL;
915*4d9fdb46SRobert Mustacchi     new_cie->ci_length = (Dwarf_Unsigned) prefix->cf_length;
91607dc1947SRichard Lowe     new_cie->ci_length_size = prefix->cf_local_length_size;
91707dc1947SRichard Lowe     new_cie->ci_extension_size = prefix->cf_local_extension_size;
91807dc1947SRichard Lowe     new_cie->ci_augmentation = (char *) augmentation;
91907dc1947SRichard Lowe 
92007dc1947SRichard Lowe     new_cie->ci_data_alignment_factor =
92107dc1947SRichard Lowe         (Dwarf_Sbyte) data_alignment_factor;
92207dc1947SRichard Lowe     new_cie->ci_code_alignment_factor =
92307dc1947SRichard Lowe         (Dwarf_Small) code_alignment_factor;
92407dc1947SRichard Lowe     new_cie->ci_return_address_register = return_address_register;
92507dc1947SRichard Lowe     new_cie->ci_cie_start = prefix->cf_start_addr;
926*4d9fdb46SRobert Mustacchi 
927*4d9fdb46SRobert Mustacchi     if ( frame_ptr > section_ptr_end) {
928*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
929*4d9fdb46SRobert Mustacchi         return (DW_DLV_ERROR);
930*4d9fdb46SRobert Mustacchi     }
93107dc1947SRichard Lowe     new_cie->ci_cie_instr_start = frame_ptr;
93207dc1947SRichard Lowe     new_cie->ci_dbg = dbg;
93307dc1947SRichard Lowe     new_cie->ci_augmentation_type = augt;
93407dc1947SRichard Lowe     new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
93507dc1947SRichard Lowe     new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
93607dc1947SRichard Lowe     new_cie->ci_gnu_personality_handler_encoding =
93707dc1947SRichard Lowe         gnu_personality_handler_encoding;
93807dc1947SRichard Lowe     new_cie->ci_gnu_personality_handler_addr =
93907dc1947SRichard Lowe         gnu_personality_handler_addr;
94007dc1947SRichard Lowe     new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
94107dc1947SRichard Lowe     new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
94207dc1947SRichard Lowe 
94307dc1947SRichard Lowe     new_cie->ci_index = cie_count;
94407dc1947SRichard Lowe     new_cie->ci_section_ptr = prefix->cf_section_ptr;
945*4d9fdb46SRobert Mustacchi     new_cie->ci_section_end = section_ptr_end;
946*4d9fdb46SRobert Mustacchi     new_cie->ci_cie_end = new_cie->ci_cie_start + new_cie->ci_length +
947*4d9fdb46SRobert Mustacchi         new_cie->ci_length_size+ new_cie->ci_extension_size;
948*4d9fdb46SRobert Mustacchi     if ( new_cie->ci_cie_end > section_ptr_end) {
949*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
950*4d9fdb46SRobert Mustacchi         return (DW_DLV_ERROR);
951*4d9fdb46SRobert Mustacchi     }
952*4d9fdb46SRobert Mustacchi 
95307dc1947SRichard Lowe     /* The Following new in DWARF4 */
95407dc1947SRichard Lowe     new_cie->ci_address_size = address_size;
95507dc1947SRichard Lowe     new_cie->ci_segment_size = segment_size;
95607dc1947SRichard Lowe     validate_length(dbg,new_cie,new_cie->ci_length,
95707dc1947SRichard Lowe         new_cie->ci_length_size, new_cie->ci_extension_size,
95807dc1947SRichard Lowe         new_cie->ci_section_ptr,
95907dc1947SRichard Lowe         new_cie->ci_cie_start,"cie");
96007dc1947SRichard Lowe 
96107dc1947SRichard Lowe     *cie_ptr_out = new_cie;
96207dc1947SRichard Lowe     return DW_DLV_OK;
96307dc1947SRichard Lowe 
96407dc1947SRichard Lowe }
96507dc1947SRichard Lowe 
96607dc1947SRichard Lowe 
967*4d9fdb46SRobert Mustacchi /*  Internal function, not called by consumer code.
968*4d9fdb46SRobert Mustacchi     'prefix' has accumulated the info up thru the cie-id
969*4d9fdb46SRobert Mustacchi     and now we consume the rest and build a Dwarf_Fde_s structure.
970*4d9fdb46SRobert Mustacchi     Can be called with cie_ptr_in NULL from dwarf_frame.c  */
97107dc1947SRichard Lowe 
97207dc1947SRichard Lowe int
dwarf_create_fde_from_after_start(Dwarf_Debug dbg,struct cie_fde_prefix_s * prefix,Dwarf_Small * section_pointer,Dwarf_Small * frame_ptr,Dwarf_Small * section_ptr_end,int use_gnu_cie_calc,Dwarf_Cie cie_ptr_in,Dwarf_Fde * fde_ptr_out,Dwarf_Error * error)97307dc1947SRichard Lowe dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
97407dc1947SRichard Lowe     struct cie_fde_prefix_s *prefix,
97507dc1947SRichard Lowe     Dwarf_Small * section_pointer,
97607dc1947SRichard Lowe     Dwarf_Small * frame_ptr,
977*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
97807dc1947SRichard Lowe     int use_gnu_cie_calc,
97907dc1947SRichard Lowe     Dwarf_Cie cie_ptr_in,
98007dc1947SRichard Lowe     Dwarf_Fde * fde_ptr_out,
98107dc1947SRichard Lowe     Dwarf_Error * error)
98207dc1947SRichard Lowe {
98307dc1947SRichard Lowe     Dwarf_Fde new_fde = 0;
984*4d9fdb46SRobert Mustacchi     Dwarf_Cie cieptr = 0;
98507dc1947SRichard Lowe     Dwarf_Small *saved_frame_ptr = 0;
98607dc1947SRichard Lowe 
98707dc1947SRichard Lowe     Dwarf_Small *initloc = frame_ptr;
98807dc1947SRichard Lowe     Dwarf_Signed offset_into_exception_tables
98907dc1947SRichard Lowe         = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
99007dc1947SRichard Lowe     Dwarf_Small *fde_aug_data = 0;
99107dc1947SRichard Lowe     Dwarf_Unsigned fde_aug_data_len = 0;
99207dc1947SRichard Lowe     Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
99307dc1947SRichard Lowe     Dwarf_Addr initial_location = 0;    /* must be min de_pointer_size
994*4d9fdb46SRobert Mustacchi         bytes in size */
99507dc1947SRichard Lowe     Dwarf_Addr address_range = 0;       /* must be min de_pointer_size
996*4d9fdb46SRobert Mustacchi         bytes in size */
997*4d9fdb46SRobert Mustacchi     Dwarf_Half address_size = 0;
998*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned eh_table_value = 0;
999*4d9fdb46SRobert Mustacchi     Dwarf_Bool eh_table_value_set = FALSE;
1000*4d9fdb46SRobert Mustacchi     /* Temporary assumption.  */
1001*4d9fdb46SRobert Mustacchi     enum Dwarf_augmentation_type augt = aug_empty_string;
1002*4d9fdb46SRobert Mustacchi 
1003*4d9fdb46SRobert Mustacchi     if (cie_ptr_in) {
1004*4d9fdb46SRobert Mustacchi         cieptr = cie_ptr_in;
1005*4d9fdb46SRobert Mustacchi         address_size = cieptr->ci_address_size;
1006*4d9fdb46SRobert Mustacchi         augt = cieptr->ci_augmentation_type;
1007*4d9fdb46SRobert Mustacchi     }
100807dc1947SRichard Lowe 
100907dc1947SRichard Lowe     if (augt == aug_gcc_eh_z) {
1010*4d9fdb46SRobert Mustacchi         /*  If z augmentation this is eh_frame, and initial_location and
1011*4d9fdb46SRobert Mustacchi             address_range in the FDE are read according to the CIE
1012*4d9fdb46SRobert Mustacchi             augmentation string instructions.  */
101307dc1947SRichard Lowe 
101407dc1947SRichard Lowe         {
101507dc1947SRichard Lowe             Dwarf_Small *fp_updated = 0;
101607dc1947SRichard Lowe             int res = read_encoded_ptr(dbg,
101707dc1947SRichard Lowe                 section_pointer,
101807dc1947SRichard Lowe                 frame_ptr,
101907dc1947SRichard Lowe                 cieptr-> ci_gnu_fde_begin_encoding,
1020*4d9fdb46SRobert Mustacchi                 section_ptr_end,
102107dc1947SRichard Lowe                 address_size,
102207dc1947SRichard Lowe                 &initial_location,
1023*4d9fdb46SRobert Mustacchi                 &fp_updated,error);
102407dc1947SRichard Lowe             if (res != DW_DLV_OK) {
1025*4d9fdb46SRobert Mustacchi                 return res;
102607dc1947SRichard Lowe             }
102707dc1947SRichard Lowe             frame_ptr = fp_updated;
1028*4d9fdb46SRobert Mustacchi             /*  For the address-range it makes no sense to be
1029*4d9fdb46SRobert Mustacchi                 pc-relative, so we turn it off with a section_pointer of
1030*4d9fdb46SRobert Mustacchi                 NULL. Masking off DW_EH_PE_pcrel from the
1031*4d9fdb46SRobert Mustacchi                 ci_gnu_fde_begin_encoding in this call would also work
1032*4d9fdb46SRobert Mustacchi                 to turn off DW_EH_PE_pcrel. */
103307dc1947SRichard Lowe             res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
1034*4d9fdb46SRobert Mustacchi                 frame_ptr,
1035*4d9fdb46SRobert Mustacchi                 cieptr->ci_gnu_fde_begin_encoding,
1036*4d9fdb46SRobert Mustacchi                 section_ptr_end,
1037*4d9fdb46SRobert Mustacchi                 address_size,
1038*4d9fdb46SRobert Mustacchi                 &address_range, &fp_updated,error);
103907dc1947SRichard Lowe             if (res != DW_DLV_OK) {
1040*4d9fdb46SRobert Mustacchi                 return res;
104107dc1947SRichard Lowe             }
104207dc1947SRichard Lowe             frame_ptr = fp_updated;
104307dc1947SRichard Lowe         }
104407dc1947SRichard Lowe         {
104507dc1947SRichard Lowe             Dwarf_Unsigned adlen = 0;
104607dc1947SRichard Lowe 
1047*4d9fdb46SRobert Mustacchi             DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
1048*4d9fdb46SRobert Mustacchi                 dbg,error,section_ptr_end);
104907dc1947SRichard Lowe             fde_aug_data_len = adlen;
105007dc1947SRichard Lowe             fde_aug_data = frame_ptr;
105107dc1947SRichard Lowe             frame_ptr += adlen;
1052*4d9fdb46SRobert Mustacchi             if (adlen) {
1053*4d9fdb46SRobert Mustacchi                 if (frame_ptr < fde_aug_data ||
1054*4d9fdb46SRobert Mustacchi                     frame_ptr >= section_ptr_end ) {
1055*4d9fdb46SRobert Mustacchi                     dwarfstring m;
1056*4d9fdb46SRobert Mustacchi 
1057*4d9fdb46SRobert Mustacchi                     dwarfstring_constructor(&m);
1058*4d9fdb46SRobert Mustacchi                     dwarfstring_append_printf_u(&m,
1059*4d9fdb46SRobert Mustacchi                         "DW_DLE_AUG_DATA_LENGTH_BAD: The "
1060*4d9fdb46SRobert Mustacchi                         "gcc .eh_frame augmentation data "
1061*4d9fdb46SRobert Mustacchi                         "length of %" DW_PR_DUu " is too long to"
1062*4d9fdb46SRobert Mustacchi                         " fit in the section.",adlen);
1063*4d9fdb46SRobert Mustacchi                     _dwarf_error_string(dbg, error,
1064*4d9fdb46SRobert Mustacchi                         DW_DLE_AUG_DATA_LENGTH_BAD,
1065*4d9fdb46SRobert Mustacchi                         dwarfstring_string(&m));
1066*4d9fdb46SRobert Mustacchi                     dwarfstring_destructor(&m);
1067*4d9fdb46SRobert Mustacchi                     return DW_DLV_ERROR;
1068*4d9fdb46SRobert Mustacchi                 }
1069*4d9fdb46SRobert Mustacchi             }
107007dc1947SRichard Lowe         }
107107dc1947SRichard Lowe 
107207dc1947SRichard Lowe     } else {
1073*4d9fdb46SRobert Mustacchi         if ((frame_ptr + 2*address_size) > section_ptr_end) {
1074*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1075*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
1076*4d9fdb46SRobert Mustacchi         }
1077*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, initial_location, Dwarf_Addr,
1078*4d9fdb46SRobert Mustacchi             frame_ptr, address_size,
1079*4d9fdb46SRobert Mustacchi             error,section_ptr_end);
108007dc1947SRichard Lowe         frame_ptr += address_size;
1081*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, address_range, Dwarf_Addr,
1082*4d9fdb46SRobert Mustacchi             frame_ptr, address_size,
1083*4d9fdb46SRobert Mustacchi             error,section_ptr_end);
108407dc1947SRichard Lowe         frame_ptr += address_size;
108507dc1947SRichard Lowe     }
108607dc1947SRichard Lowe     switch (augt) {
108707dc1947SRichard Lowe     case aug_irix_mti_v1:
108807dc1947SRichard Lowe     case aug_empty_string:
108907dc1947SRichard Lowe         break;
109007dc1947SRichard Lowe     case aug_irix_exception_table:{
1091*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned lreg = 0;
1092*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned length_of_augmented_fields = 0;
1093*4d9fdb46SRobert Mustacchi 
1094*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_CK(frame_ptr, lreg,
1095*4d9fdb46SRobert Mustacchi             dbg,error,section_ptr_end);
1096*4d9fdb46SRobert Mustacchi         length_of_augmented_fields = (Dwarf_Unsigned) lreg;
1097*4d9fdb46SRobert Mustacchi 
1098*4d9fdb46SRobert Mustacchi         saved_frame_ptr = frame_ptr;
1099*4d9fdb46SRobert Mustacchi         /*  The first word is an offset into exception tables.
1100*4d9fdb46SRobert Mustacchi             Defined as a 32bit offset even for CC -64. */
1101*4d9fdb46SRobert Mustacchi         if ((frame_ptr + DWARF_32BIT_SIZE) > section_ptr_end) {
1102*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1103*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
1104*4d9fdb46SRobert Mustacchi         }
1105*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, offset_into_exception_tables,
1106*4d9fdb46SRobert Mustacchi             Dwarf_Addr, frame_ptr, DWARF_32BIT_SIZE,
1107*4d9fdb46SRobert Mustacchi             error,section_ptr_end);
1108*4d9fdb46SRobert Mustacchi         SIGN_EXTEND(offset_into_exception_tables,
1109*4d9fdb46SRobert Mustacchi             DWARF_32BIT_SIZE);
1110*4d9fdb46SRobert Mustacchi         frame_ptr = saved_frame_ptr + length_of_augmented_fields;
111107dc1947SRichard Lowe         }
111207dc1947SRichard Lowe         break;
111307dc1947SRichard Lowe     case aug_eh:{
111407dc1947SRichard Lowe 
1115*4d9fdb46SRobert Mustacchi         if (!use_gnu_cie_calc) {
1116*4d9fdb46SRobert Mustacchi             /* This should be impossible. */
1117*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1118*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
1119*4d9fdb46SRobert Mustacchi         }
112007dc1947SRichard Lowe 
1121*4d9fdb46SRobert Mustacchi         /* gnu eh fde case. we do not need to do anything */
1122*4d9fdb46SRobert Mustacchi         /*REFERENCED*/ /* Not used in this instance of the macro */
1123*4d9fdb46SRobert Mustacchi         if ((frame_ptr + address_size) > section_ptr_end) {
1124*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1125*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
1126*4d9fdb46SRobert Mustacchi         }
1127*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, eh_table_value,
1128*4d9fdb46SRobert Mustacchi             Dwarf_Unsigned, frame_ptr,
1129*4d9fdb46SRobert Mustacchi             address_size,
1130*4d9fdb46SRobert Mustacchi             error,section_ptr_end);
1131*4d9fdb46SRobert Mustacchi         eh_table_value_set = TRUE;
1132*4d9fdb46SRobert Mustacchi         frame_ptr += address_size;
113307dc1947SRichard Lowe         }
113407dc1947SRichard Lowe         break;
113507dc1947SRichard Lowe 
113607dc1947SRichard Lowe     case aug_gcc_eh_z:{
1137*4d9fdb46SRobert Mustacchi         /*  The Augmentation Data Length is here, followed by the
1138*4d9fdb46SRobert Mustacchi             Augmentation Data bytes themselves. */
113907dc1947SRichard Lowe         }
114007dc1947SRichard Lowe         break;
114107dc1947SRichard Lowe     case aug_armcc:
114207dc1947SRichard Lowe         break;
114307dc1947SRichard Lowe     case aug_past_last:
114407dc1947SRichard Lowe         break;
1145*4d9fdb46SRobert Mustacchi 
1146*4d9fdb46SRobert Mustacchi     case aug_metaware: /* No special fields. See dwarf_util.h */
1147*4d9fdb46SRobert Mustacchi         break;
1148*4d9fdb46SRobert Mustacchi 
114907dc1947SRichard Lowe     case aug_unknown:
115007dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
115107dc1947SRichard Lowe         return DW_DLV_ERROR;
115207dc1947SRichard Lowe     }                           /* End switch on augmentation type */
1153*4d9fdb46SRobert Mustacchi     if ( frame_ptr > section_ptr_end) {
1154*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
1155*4d9fdb46SRobert Mustacchi         return (DW_DLV_ERROR);
1156*4d9fdb46SRobert Mustacchi     }
1157*4d9fdb46SRobert Mustacchi 
115807dc1947SRichard Lowe     new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
115907dc1947SRichard Lowe     if (new_fde == NULL) {
116007dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
116107dc1947SRichard Lowe         return (DW_DLV_ERROR);
116207dc1947SRichard Lowe     }
116307dc1947SRichard Lowe 
116407dc1947SRichard Lowe     new_fde->fd_length = prefix->cf_length;
116507dc1947SRichard Lowe     new_fde->fd_length_size = prefix->cf_local_length_size;
116607dc1947SRichard Lowe     new_fde->fd_extension_size = prefix->cf_local_extension_size;
116707dc1947SRichard Lowe     new_fde->fd_is_eh = use_gnu_cie_calc;
116807dc1947SRichard Lowe     new_fde->fd_cie_offset = cie_base_offset;
1169*4d9fdb46SRobert Mustacchi     if (cieptr) {
1170*4d9fdb46SRobert Mustacchi         new_fde->fd_cie_index = cieptr->ci_index;
1171*4d9fdb46SRobert Mustacchi     }
117207dc1947SRichard Lowe     new_fde->fd_cie = cieptr;
117307dc1947SRichard Lowe     new_fde->fd_initial_location = initial_location;
117407dc1947SRichard Lowe     new_fde->fd_initial_loc_pos = initloc;
117507dc1947SRichard Lowe     new_fde->fd_address_range = address_range;
117607dc1947SRichard Lowe     new_fde->fd_fde_start = prefix->cf_start_addr;
1177*4d9fdb46SRobert Mustacchi 
117807dc1947SRichard Lowe     new_fde->fd_fde_instr_start = frame_ptr;
1179*4d9fdb46SRobert Mustacchi     new_fde->fd_fde_end = prefix->cf_start_addr +
1180*4d9fdb46SRobert Mustacchi         prefix->cf_length +  prefix->cf_local_length_size  +
1181*4d9fdb46SRobert Mustacchi         prefix->cf_local_extension_size;
1182*4d9fdb46SRobert Mustacchi     if ( new_fde->fd_fde_end > section_ptr_end) {
1183*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DF_FRAME_DECODING_ERROR);
1184*4d9fdb46SRobert Mustacchi         return (DW_DLV_ERROR);
1185*4d9fdb46SRobert Mustacchi     }
1186*4d9fdb46SRobert Mustacchi 
118707dc1947SRichard Lowe     new_fde->fd_dbg = dbg;
118807dc1947SRichard Lowe     new_fde->fd_offset_into_exception_tables =
118907dc1947SRichard Lowe         offset_into_exception_tables;
1190*4d9fdb46SRobert Mustacchi     new_fde->fd_eh_table_value = eh_table_value;
1191*4d9fdb46SRobert Mustacchi     new_fde->fd_eh_table_value_set = eh_table_value_set;
119207dc1947SRichard Lowe 
119307dc1947SRichard Lowe     new_fde->fd_section_ptr = prefix->cf_section_ptr;
119407dc1947SRichard Lowe     new_fde->fd_section_index = prefix->cf_section_index;
119507dc1947SRichard Lowe     new_fde->fd_section_length = prefix->cf_section_length;
1196*4d9fdb46SRobert Mustacchi     new_fde->fd_section_end = section_ptr_end;
119707dc1947SRichard Lowe 
1198*4d9fdb46SRobert Mustacchi     if (augt == aug_gcc_eh_z) {
1199*4d9fdb46SRobert Mustacchi         new_fde->fd_gnu_eh_aug_present = TRUE;
1200*4d9fdb46SRobert Mustacchi     }
120107dc1947SRichard Lowe     new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
120207dc1947SRichard Lowe     new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
120307dc1947SRichard Lowe     validate_length(dbg,cieptr,new_fde->fd_length,
120407dc1947SRichard Lowe         new_fde->fd_length_size, new_fde->fd_extension_size,
120507dc1947SRichard Lowe         new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
120607dc1947SRichard Lowe     *fde_ptr_out = new_fde;
120707dc1947SRichard Lowe     return DW_DLV_OK;
120807dc1947SRichard Lowe }
120907dc1947SRichard Lowe 
1210*4d9fdb46SRobert Mustacchi /*  Read in the common cie/fde prefix, including reading
1211*4d9fdb46SRobert Mustacchi     the cie-value which shows which this is: cie or fde.  */
121207dc1947SRichard Lowe int
dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,Dwarf_Small * frame_ptr_in,Dwarf_Small * section_ptr_in,Dwarf_Unsigned section_index_in,Dwarf_Unsigned section_length_in,struct cie_fde_prefix_s * data_out,Dwarf_Error * error)121307dc1947SRichard Lowe dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
1214*4d9fdb46SRobert Mustacchi     Dwarf_Small * frame_ptr_in,
1215*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_in,
1216*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned section_index_in,
1217*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned section_length_in,
1218*4d9fdb46SRobert Mustacchi     struct cie_fde_prefix_s *data_out,
1219*4d9fdb46SRobert Mustacchi     Dwarf_Error * error)
122007dc1947SRichard Lowe {
122107dc1947SRichard Lowe     Dwarf_Unsigned length = 0;
122207dc1947SRichard Lowe     int local_length_size = 0;
122307dc1947SRichard Lowe     int local_extension_size = 0;
122407dc1947SRichard Lowe     Dwarf_Small *frame_ptr = frame_ptr_in;
122507dc1947SRichard Lowe     Dwarf_Small *cie_ptr_addr = 0;
122607dc1947SRichard Lowe     Dwarf_Unsigned cie_id = 0;
1227*4d9fdb46SRobert Mustacchi     Dwarf_Small *section_end = section_ptr_in + section_length_in;
1228*4d9fdb46SRobert Mustacchi 
1229*4d9fdb46SRobert Mustacchi     if(section_end < (frame_ptr +4)) {
1230*4d9fdb46SRobert Mustacchi         dwarfstring m;
1231*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned u = (Dwarf_Unsigned)(uintptr_t)(frame_ptr+4) -
1232*4d9fdb46SRobert Mustacchi             (Dwarf_Unsigned)(uintptr_t)section_end;
1233*4d9fdb46SRobert Mustacchi 
1234*4d9fdb46SRobert Mustacchi         dwarfstring_constructor(&m);
1235*4d9fdb46SRobert Mustacchi         dwarfstring_append_printf_u(&m,
1236*4d9fdb46SRobert Mustacchi             "DW_DLE_DEBUG_FRAME_LENGTH_BAD: "
1237*4d9fdb46SRobert Mustacchi             "Reading the cie/fde prefix would "
1238*4d9fdb46SRobert Mustacchi             "put us %u bytes past the end of the "
1239*4d9fdb46SRobert Mustacchi             "frame section.  Corrupt Dwarf.",u);
1240*4d9fdb46SRobert Mustacchi         _dwarf_error_string(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD,
1241*4d9fdb46SRobert Mustacchi             dwarfstring_string(&m));
1242*4d9fdb46SRobert Mustacchi         dwarfstring_destructor(&m);
1243*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
1244*4d9fdb46SRobert Mustacchi     }
124507dc1947SRichard Lowe     /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
1246*4d9fdb46SRobert Mustacchi     READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned,
1247*4d9fdb46SRobert Mustacchi         frame_ptr, local_length_size,
1248*4d9fdb46SRobert Mustacchi         local_extension_size,error,
1249*4d9fdb46SRobert Mustacchi         section_length_in,section_end);
125007dc1947SRichard Lowe 
125107dc1947SRichard Lowe     if (length == 0) {
1252*4d9fdb46SRobert Mustacchi         /*  nul bytes at end of section, seen at end of egcs eh_frame
1253*4d9fdb46SRobert Mustacchi             sections (in a.out). Take this as meaning no more CIE/FDE
1254*4d9fdb46SRobert Mustacchi             data. We should be very close to end of section. */
125507dc1947SRichard Lowe         return DW_DLV_NO_ENTRY;
125607dc1947SRichard Lowe     }
1257*4d9fdb46SRobert Mustacchi     if((frame_ptr + local_length_size) >= section_end) {
1258*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1259*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
1260*4d9fdb46SRobert Mustacchi     }
126107dc1947SRichard Lowe 
126207dc1947SRichard Lowe     cie_ptr_addr = frame_ptr;
1263*4d9fdb46SRobert Mustacchi     READ_UNALIGNED_CK(dbg, cie_id, Dwarf_Unsigned,
1264*4d9fdb46SRobert Mustacchi         frame_ptr, local_length_size,error,section_end);
126507dc1947SRichard Lowe     SIGN_EXTEND(cie_id, local_length_size);
126607dc1947SRichard Lowe     frame_ptr += local_length_size;
126707dc1947SRichard Lowe 
126807dc1947SRichard Lowe     data_out->cf_start_addr = frame_ptr_in;
126907dc1947SRichard Lowe     data_out->cf_addr_after_prefix = frame_ptr;
127007dc1947SRichard Lowe 
127107dc1947SRichard Lowe     data_out->cf_length = length;
1272*4d9fdb46SRobert Mustacchi     if (length > section_length_in) {
1273*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1274*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
1275*4d9fdb46SRobert Mustacchi     }
1276*4d9fdb46SRobert Mustacchi     if (cie_ptr_addr+length > section_end) {
1277*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg,error,DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1278*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
1279*4d9fdb46SRobert Mustacchi     }
128007dc1947SRichard Lowe     data_out->cf_local_length_size = local_length_size;
128107dc1947SRichard Lowe     data_out->cf_local_extension_size = local_extension_size;
1282*4d9fdb46SRobert Mustacchi 
1283*4d9fdb46SRobert Mustacchi     /*  We do not know if it is a CIE or FDE id yet.
1284*4d9fdb46SRobert Mustacchi         How we check and what it means
1285*4d9fdb46SRobert Mustacchi         depends whether it is .debug_frame
1286*4d9fdb46SRobert Mustacchi         or .eh_frame. */
128707dc1947SRichard Lowe     data_out->cf_cie_id = cie_id;
1288*4d9fdb46SRobert Mustacchi 
1289*4d9fdb46SRobert Mustacchi     /*  The address of the CIE_id  or FDE_id value in memory.  */
129007dc1947SRichard Lowe     data_out->cf_cie_id_addr = cie_ptr_addr;
1291*4d9fdb46SRobert Mustacchi 
129207dc1947SRichard Lowe     data_out->cf_section_ptr = section_ptr_in;
129307dc1947SRichard Lowe     data_out->cf_section_index = section_index_in;
129407dc1947SRichard Lowe     data_out->cf_section_length = section_length_in;
129507dc1947SRichard Lowe     return DW_DLV_OK;
129607dc1947SRichard Lowe }
129707dc1947SRichard Lowe 
1298*4d9fdb46SRobert Mustacchi /*  On various errors previously-allocated CIEs and FDEs
1299*4d9fdb46SRobert Mustacchi     must be cleaned up.
1300*4d9fdb46SRobert Mustacchi     This helps avoid leaks in case of errors.
130107dc1947SRichard Lowe */
130207dc1947SRichard Lowe static void
dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,Dwarf_Cie head_cie_ptr)130307dc1947SRichard Lowe dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
130407dc1947SRichard Lowe     Dwarf_Cie head_cie_ptr)
130507dc1947SRichard Lowe {
130607dc1947SRichard Lowe     Dwarf_Fde curfde = 0;
130707dc1947SRichard Lowe     Dwarf_Cie curcie = 0;
130807dc1947SRichard Lowe     Dwarf_Fde nextfde = 0;
130907dc1947SRichard Lowe     Dwarf_Cie nextcie = 0;
131007dc1947SRichard Lowe 
131107dc1947SRichard Lowe     for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
131207dc1947SRichard Lowe         nextfde = curfde->fd_next;
131307dc1947SRichard Lowe         dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
131407dc1947SRichard Lowe     }
131507dc1947SRichard Lowe     for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
131607dc1947SRichard Lowe         Dwarf_Frame frame = curcie->ci_initial_table;
131707dc1947SRichard Lowe 
131807dc1947SRichard Lowe         nextcie = curcie->ci_next;
131907dc1947SRichard Lowe         if (frame)
132007dc1947SRichard Lowe             dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
132107dc1947SRichard Lowe         dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
132207dc1947SRichard Lowe     }
132307dc1947SRichard Lowe }
132407dc1947SRichard Lowe 
1325*4d9fdb46SRobert Mustacchi /*  Find the cie whose id value is given: the id
1326*4d9fdb46SRobert Mustacchi     value is, per DWARF2/3, an offset in the section.
1327*4d9fdb46SRobert Mustacchi     For .debug_frame, zero is a legal offset. For
1328*4d9fdb46SRobert Mustacchi     GNU .eh_frame it is not a legal offset.
1329*4d9fdb46SRobert Mustacchi     'cie_ptr' is a pointer into our section, not an offset. */
133007dc1947SRichard Lowe static int
dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,Dwarf_Cie cur_cie_ptr,Dwarf_Cie * cie_ptr_to_use_out,Dwarf_Cie head_cie_ptr)133107dc1947SRichard Lowe dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
1332*4d9fdb46SRobert Mustacchi     Dwarf_Cie cur_cie_ptr,
1333*4d9fdb46SRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
1334*4d9fdb46SRobert Mustacchi     Dwarf_Cie head_cie_ptr)
133507dc1947SRichard Lowe {
133607dc1947SRichard Lowe     Dwarf_Cie next = 0;
133707dc1947SRichard Lowe 
133807dc1947SRichard Lowe     if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
133907dc1947SRichard Lowe         /* Usually, we use the same cie again and again. */
134007dc1947SRichard Lowe         *cie_ptr_to_use_out = cur_cie_ptr;
134107dc1947SRichard Lowe         return DW_DLV_OK;
134207dc1947SRichard Lowe     }
134307dc1947SRichard Lowe     for (next = head_cie_ptr; next; next = next->ci_next) {
134407dc1947SRichard Lowe         if (cie_ptr == next->ci_cie_start) {
134507dc1947SRichard Lowe             *cie_ptr_to_use_out = next;
134607dc1947SRichard Lowe             return DW_DLV_OK;
134707dc1947SRichard Lowe         }
134807dc1947SRichard Lowe     }
134907dc1947SRichard Lowe     return DW_DLV_NO_ENTRY;
135007dc1947SRichard Lowe }
135107dc1947SRichard Lowe 
135207dc1947SRichard Lowe 
1353*4d9fdb46SRobert Mustacchi /*  We have a valid cie_ptr_val that has not been
1354*4d9fdb46SRobert Mustacchi     turned into an internal Cie yet. Do so now.
1355*4d9fdb46SRobert Mustacchi     Returns DW_DLV_OK or DW_DLV_ERROR, never
1356*4d9fdb46SRobert Mustacchi     DW_DLV_NO_ENTRY.
135707dc1947SRichard Lowe 
1358*4d9fdb46SRobert Mustacchi     'section_ptr'    - Points to first byte of section data.
1359*4d9fdb46SRobert Mustacchi     'section_length' - Length of the section, in bytes.
1360*4d9fdb46SRobert Mustacchi     'section_ptr_end'  - Points 1-past last byte of section data.  */
136107dc1947SRichard Lowe static int
dwarf_create_cie_from_start(Dwarf_Debug dbg,Dwarf_Small * cie_ptr_val,Dwarf_Small * section_ptr,Dwarf_Unsigned section_index,Dwarf_Unsigned section_length,Dwarf_Small * section_ptr_end,Dwarf_Unsigned cie_id_value,Dwarf_Unsigned cie_count,int use_gnu_cie_calc,Dwarf_Cie * cie_ptr_to_use_out,Dwarf_Error * error)136207dc1947SRichard Lowe dwarf_create_cie_from_start(Dwarf_Debug dbg,
136307dc1947SRichard Lowe     Dwarf_Small * cie_ptr_val,
136407dc1947SRichard Lowe     Dwarf_Small * section_ptr,
136507dc1947SRichard Lowe     Dwarf_Unsigned section_index,
136607dc1947SRichard Lowe     Dwarf_Unsigned section_length,
1367*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
136807dc1947SRichard Lowe     Dwarf_Unsigned cie_id_value,
136907dc1947SRichard Lowe     Dwarf_Unsigned cie_count,
137007dc1947SRichard Lowe     int use_gnu_cie_calc,
137107dc1947SRichard Lowe     Dwarf_Cie * cie_ptr_to_use_out,
137207dc1947SRichard Lowe     Dwarf_Error * error)
137307dc1947SRichard Lowe {
137407dc1947SRichard Lowe     struct cie_fde_prefix_s prefix;
137507dc1947SRichard Lowe     int res = DW_DLV_ERROR;
137607dc1947SRichard Lowe     Dwarf_Small *frame_ptr = cie_ptr_val;
137707dc1947SRichard Lowe 
1378*4d9fdb46SRobert Mustacchi     if (frame_ptr < section_ptr || frame_ptr >= section_ptr_end) {
137907dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
138007dc1947SRichard Lowe         return DW_DLV_ERROR;
138107dc1947SRichard Lowe     }
1382*4d9fdb46SRobert Mustacchi     /*  First read in the 'common prefix' to figure out what * we are to
1383*4d9fdb46SRobert Mustacchi         do with this entry. If it is not a cie * we are in big trouble. */
138407dc1947SRichard Lowe     memset(&prefix, 0, sizeof(prefix));
138507dc1947SRichard Lowe     res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
138607dc1947SRichard Lowe         section_index, section_length,
138707dc1947SRichard Lowe         &prefix, error);
138807dc1947SRichard Lowe     if (res == DW_DLV_ERROR) {
138907dc1947SRichard Lowe         return res;
139007dc1947SRichard Lowe     }
139107dc1947SRichard Lowe     if (res == DW_DLV_NO_ENTRY) {
139207dc1947SRichard Lowe         /* error. */
139307dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
139407dc1947SRichard Lowe         return DW_DLV_ERROR;
139507dc1947SRichard Lowe 
139607dc1947SRichard Lowe     }
139707dc1947SRichard Lowe 
139807dc1947SRichard Lowe     if (prefix.cf_cie_id != cie_id_value) {
139907dc1947SRichard Lowe         _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
140007dc1947SRichard Lowe         return DW_DLV_ERROR;
140107dc1947SRichard Lowe     }
140207dc1947SRichard Lowe     frame_ptr = prefix.cf_addr_after_prefix;
140307dc1947SRichard Lowe     res = dwarf_create_cie_from_after_start(dbg,
140407dc1947SRichard Lowe         &prefix,
140507dc1947SRichard Lowe         section_ptr,
140607dc1947SRichard Lowe         frame_ptr,
1407*4d9fdb46SRobert Mustacchi         section_ptr_end,
140807dc1947SRichard Lowe         cie_count,
140907dc1947SRichard Lowe         use_gnu_cie_calc,
141007dc1947SRichard Lowe         cie_ptr_to_use_out, error);
141107dc1947SRichard Lowe     return res;
141207dc1947SRichard Lowe 
141307dc1947SRichard Lowe }
141407dc1947SRichard Lowe 
141507dc1947SRichard Lowe 
141607dc1947SRichard Lowe /* This is for gnu eh frames, the 'z' case.
141707dc1947SRichard Lowe    We find the letter involved
141807dc1947SRichard Lowe    Return the augmentation character and, if applicable,
141907dc1947SRichard Lowe    the personality routine address.
142007dc1947SRichard Lowe 
1421*4d9fdb46SRobert Mustacchi    personality_routine_out -
1422*4d9fdb46SRobert Mustacchi         if 'P' is augchar, is personality handler addr.
142307dc1947SRichard Lowe         Otherwise is not set.
142407dc1947SRichard Lowe    aug_data  - if 'P' points  to data space of the
142507dc1947SRichard Lowe    aug_data_len - length of areas aug_data points to.
142607dc1947SRichard Lowe 
1427*4d9fdb46SRobert Mustacchi */
142807dc1947SRichard Lowe 
1429*4d9fdb46SRobert Mustacchi /*  It is not clear if this is entirely correct. */
143007dc1947SRichard Lowe static int
gnu_aug_encodings(Dwarf_Debug dbg,char * augmentation,Dwarf_Small * aug_data,Dwarf_Unsigned aug_data_len,Dwarf_Half address_size,unsigned char * pers_hand_enc_out,unsigned char * lsda_enc_out,unsigned char * fde_begin_enc_out,Dwarf_Addr * gnu_pers_addr_out,Dwarf_Error * error)143107dc1947SRichard Lowe gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
143207dc1947SRichard Lowe     Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
143307dc1947SRichard Lowe     Dwarf_Half address_size,
143407dc1947SRichard Lowe     unsigned char *pers_hand_enc_out,
143507dc1947SRichard Lowe     unsigned char *lsda_enc_out,
143607dc1947SRichard Lowe     unsigned char *fde_begin_enc_out,
1437*4d9fdb46SRobert Mustacchi     Dwarf_Addr * gnu_pers_addr_out,
1438*4d9fdb46SRobert Mustacchi     Dwarf_Error * error)
143907dc1947SRichard Lowe {
144007dc1947SRichard Lowe     char *nc = 0;
144107dc1947SRichard Lowe     Dwarf_Small *cur_aug_p = aug_data;
144207dc1947SRichard Lowe     Dwarf_Small *end_aug_p = aug_data + aug_data_len;
144307dc1947SRichard Lowe 
144407dc1947SRichard Lowe     for (nc = augmentation; *nc; ++nc) {
144507dc1947SRichard Lowe         char c = *nc;
144607dc1947SRichard Lowe 
144707dc1947SRichard Lowe         switch (c) {
144807dc1947SRichard Lowe         case 'z':
144907dc1947SRichard Lowe             /* Means that the augmentation data is present. */
145007dc1947SRichard Lowe             continue;
145107dc1947SRichard Lowe 
145207dc1947SRichard Lowe         case 'S':
1453*4d9fdb46SRobert Mustacchi             /*  Indicates this is a signal stack frame.
1454*4d9fdb46SRobert Mustacchi                 Debuggers have to do
1455*4d9fdb46SRobert Mustacchi                 special handling.  We don't need to do more than
1456*4d9fdb46SRobert Mustacchi                 print this flag at the right time, though
1457*4d9fdb46SRobert Mustacchi                 (see dwarfdump where it prints the augmentation
1458*4d9fdb46SRobert Mustacchi                 string).
1459*4d9fdb46SRobert Mustacchi                 A signal stack frame (in some OS's) can only be
1460*4d9fdb46SRobert Mustacchi                 unwound (backtraced) by knowing it is a signal
1461*4d9fdb46SRobert Mustacchi                 stack frame (perhaps by noticing the name of the
1462*4d9fdb46SRobert Mustacchi                 function for the stack frame if the name can be
1463*4d9fdb46SRobert Mustacchi                 found somehow) and figuring
1464*4d9fdb46SRobert Mustacchi                 out (or knowing) how the kernel and libc
1465*4d9fdb46SRobert Mustacchi                 pushed a structure
1466*4d9fdb46SRobert Mustacchi                 onto the stack and loading registers from that structure.
1467*4d9fdb46SRobert Mustacchi                 Totally different from normal stack unwinding.
1468*4d9fdb46SRobert Mustacchi                 This flag gives an unwinder a big leg up by
1469*4d9fdb46SRobert Mustacchi                 decoupling the 'hint: this is a stack frame'
1470*4d9fdb46SRobert Mustacchi                 from knowledge like
1471*4d9fdb46SRobert Mustacchi                 the function name (the name might be
1472*4d9fdb46SRobert Mustacchi                 unavailable at unwind time).
147307dc1947SRichard Lowe             */
147407dc1947SRichard Lowe             break;
1475*4d9fdb46SRobert Mustacchi 
147607dc1947SRichard Lowe         case 'L':
147707dc1947SRichard Lowe             if (cur_aug_p > end_aug_p) {
1478*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
147907dc1947SRichard Lowe                 return DW_DLV_ERROR;
148007dc1947SRichard Lowe             }
148107dc1947SRichard Lowe             *lsda_enc_out = *(unsigned char *) cur_aug_p;
148207dc1947SRichard Lowe             ++cur_aug_p;
148307dc1947SRichard Lowe             break;
148407dc1947SRichard Lowe         case 'R':
1485*4d9fdb46SRobert Mustacchi             /*  Followed by a one byte argument giving the
1486*4d9fdb46SRobert Mustacchi                 pointer encoding for the address pointers in the fde. */
148707dc1947SRichard Lowe             if (cur_aug_p >= end_aug_p) {
1488*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
148907dc1947SRichard Lowe                 return DW_DLV_ERROR;
149007dc1947SRichard Lowe             }
149107dc1947SRichard Lowe             *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
149207dc1947SRichard Lowe             ++cur_aug_p;
149307dc1947SRichard Lowe             break;
149407dc1947SRichard Lowe         case 'P':{
1495*4d9fdb46SRobert Mustacchi             int res = DW_DLV_ERROR;
1496*4d9fdb46SRobert Mustacchi             Dwarf_Small *updated_aug_p = 0;
1497*4d9fdb46SRobert Mustacchi             unsigned char encoding = 0;
149807dc1947SRichard Lowe 
1499*4d9fdb46SRobert Mustacchi             if (cur_aug_p >= end_aug_p) {
1500*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1501*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
1502*4d9fdb46SRobert Mustacchi             }
1503*4d9fdb46SRobert Mustacchi             encoding = *(unsigned char *) cur_aug_p;
1504*4d9fdb46SRobert Mustacchi             *pers_hand_enc_out = encoding;
1505*4d9fdb46SRobert Mustacchi             ++cur_aug_p;
1506*4d9fdb46SRobert Mustacchi             if (cur_aug_p > end_aug_p) {
1507*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1508*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
1509*4d9fdb46SRobert Mustacchi             }
1510*4d9fdb46SRobert Mustacchi             /*  DW_EH_PE_pcrel makes no sense here, so we turn it
1511*4d9fdb46SRobert Mustacchi                 off via a section pointer of NULL. */
1512*4d9fdb46SRobert Mustacchi             res = read_encoded_ptr(dbg,
1513*4d9fdb46SRobert Mustacchi                 (Dwarf_Small *) NULL,
1514*4d9fdb46SRobert Mustacchi                 cur_aug_p,
1515*4d9fdb46SRobert Mustacchi                 encoding,
1516*4d9fdb46SRobert Mustacchi                 end_aug_p,
1517*4d9fdb46SRobert Mustacchi                 address_size,
1518*4d9fdb46SRobert Mustacchi                 gnu_pers_addr_out,
1519*4d9fdb46SRobert Mustacchi                 &updated_aug_p,
1520*4d9fdb46SRobert Mustacchi                 error);
1521*4d9fdb46SRobert Mustacchi             if (res != DW_DLV_OK) {
1522*4d9fdb46SRobert Mustacchi                 return res;
1523*4d9fdb46SRobert Mustacchi             }
1524*4d9fdb46SRobert Mustacchi             cur_aug_p = updated_aug_p;
1525*4d9fdb46SRobert Mustacchi             if (cur_aug_p > end_aug_p) {
1526*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1527*4d9fdb46SRobert Mustacchi                 return DW_DLV_ERROR;
1528*4d9fdb46SRobert Mustacchi             }
152907dc1947SRichard Lowe             }
153007dc1947SRichard Lowe             break;
153107dc1947SRichard Lowe         default:
1532*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
153307dc1947SRichard Lowe             return DW_DLV_ERROR;
153407dc1947SRichard Lowe 
153507dc1947SRichard Lowe         }
153607dc1947SRichard Lowe     }
153707dc1947SRichard Lowe     return DW_DLV_OK;
153807dc1947SRichard Lowe }
153907dc1947SRichard Lowe 
1540*4d9fdb46SRobert Mustacchi /*  Given augmentation character (the encoding) giving the
1541*4d9fdb46SRobert Mustacchi     address format, read the address from input_field
1542*4d9fdb46SRobert Mustacchi     and return an incremented value 1 past the input bytes of the
1543*4d9fdb46SRobert Mustacchi     address.
1544*4d9fdb46SRobert Mustacchi     Push the address read back thru the *addr pointer.
1545*4d9fdb46SRobert Mustacchi     See LSB (Linux Standard Base)  exception handling documents.  */
154607dc1947SRichard Lowe static int
read_encoded_ptr(Dwarf_Debug dbg,Dwarf_Small * section_pointer,Dwarf_Small * input_field,int gnu_encoding,Dwarf_Small * section_end,Dwarf_Half address_size,Dwarf_Unsigned * addr,Dwarf_Small ** input_field_updated,Dwarf_Error * error)154707dc1947SRichard Lowe read_encoded_ptr(Dwarf_Debug dbg,
154807dc1947SRichard Lowe     Dwarf_Small * section_pointer,
154907dc1947SRichard Lowe     Dwarf_Small * input_field,
155007dc1947SRichard Lowe     int gnu_encoding,
1551*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_end,
155207dc1947SRichard Lowe     Dwarf_Half address_size,
155307dc1947SRichard Lowe     Dwarf_Unsigned * addr,
1554*4d9fdb46SRobert Mustacchi     Dwarf_Small ** input_field_updated,
1555*4d9fdb46SRobert Mustacchi     Dwarf_Error *error)
155607dc1947SRichard Lowe {
155707dc1947SRichard Lowe     int value_type = gnu_encoding & 0xf;
155807dc1947SRichard Lowe     Dwarf_Small *input_field_original = input_field;
155907dc1947SRichard Lowe 
156007dc1947SRichard Lowe     if (gnu_encoding == 0xff) {
156107dc1947SRichard Lowe         /* There is no data here. */
156207dc1947SRichard Lowe 
156307dc1947SRichard Lowe         *addr = 0;
156407dc1947SRichard Lowe         *input_field_updated = input_field;
156507dc1947SRichard Lowe         /* Should we return DW_DLV_NO_ENTRY? */
156607dc1947SRichard Lowe         return DW_DLV_OK;
156707dc1947SRichard Lowe     }
156807dc1947SRichard Lowe     switch (value_type) {
156907dc1947SRichard Lowe     case DW_EH_PE_absptr:{
1570*4d9fdb46SRobert Mustacchi         /* value_type is zero. Treat as pointer size of the object.
1571*4d9fdb46SRobert Mustacchi         */
1572*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
1573*4d9fdb46SRobert Mustacchi 
1574*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1575*4d9fdb46SRobert Mustacchi             input_field, address_size,error,section_end);
1576*4d9fdb46SRobert Mustacchi         *addr = ret_value;
1577*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + address_size;
157807dc1947SRichard Lowe         }
157907dc1947SRichard Lowe         break;
158007dc1947SRichard Lowe     case DW_EH_PE_uleb128:{
1581*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned val = 0;
158207dc1947SRichard Lowe 
1583*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_CK(input_field,val,dbg,error,section_end);
1584*4d9fdb46SRobert Mustacchi         *addr = val;
1585*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field;
158607dc1947SRichard Lowe         }
158707dc1947SRichard Lowe         break;
158807dc1947SRichard Lowe     case DW_EH_PE_udata2:{
1589*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
159007dc1947SRichard Lowe 
1591*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1592*4d9fdb46SRobert Mustacchi             input_field, 2,error,section_end);
1593*4d9fdb46SRobert Mustacchi         *addr = ret_value;
1594*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + 2;
159507dc1947SRichard Lowe         }
159607dc1947SRichard Lowe         break;
159707dc1947SRichard Lowe 
159807dc1947SRichard Lowe     case DW_EH_PE_udata4:{
1599*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
160007dc1947SRichard Lowe 
1601*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1602*4d9fdb46SRobert Mustacchi             input_field, DWARF_32BIT_SIZE,error,section_end);
1603*4d9fdb46SRobert Mustacchi         *addr = ret_value;
1604*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + DWARF_32BIT_SIZE;
160507dc1947SRichard Lowe         }
160607dc1947SRichard Lowe         break;
160707dc1947SRichard Lowe 
160807dc1947SRichard Lowe     case DW_EH_PE_udata8:{
1609*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
161007dc1947SRichard Lowe 
1611*4d9fdb46SRobert Mustacchi         /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
1612*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1613*4d9fdb46SRobert Mustacchi             input_field, DWARF_64BIT_SIZE,error,section_end);
1614*4d9fdb46SRobert Mustacchi         *addr = ret_value;
1615*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field +  DWARF_64BIT_SIZE;
161607dc1947SRichard Lowe         }
161707dc1947SRichard Lowe         break;
161807dc1947SRichard Lowe 
161907dc1947SRichard Lowe     case DW_EH_PE_sleb128:{
1620*4d9fdb46SRobert Mustacchi         Dwarf_Signed val = 0;
162107dc1947SRichard Lowe 
1622*4d9fdb46SRobert Mustacchi         DECODE_LEB128_SWORD_CK(input_field,val,dbg,error,section_end);
1623*4d9fdb46SRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1624*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field;
162507dc1947SRichard Lowe         }
162607dc1947SRichard Lowe         break;
162707dc1947SRichard Lowe     case DW_EH_PE_sdata2:{
1628*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned val = 0;
162907dc1947SRichard Lowe 
1630*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, val, Dwarf_Unsigned, input_field, 2,
1631*4d9fdb46SRobert Mustacchi             error,section_end);
1632*4d9fdb46SRobert Mustacchi         SIGN_EXTEND(val, 2);
1633*4d9fdb46SRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1634*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + 2;
163507dc1947SRichard Lowe         }
163607dc1947SRichard Lowe         break;
163707dc1947SRichard Lowe 
163807dc1947SRichard Lowe     case DW_EH_PE_sdata4:{
1639*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned val = 0;
1640*4d9fdb46SRobert Mustacchi 
1641*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, val,
1642*4d9fdb46SRobert Mustacchi             Dwarf_Unsigned, input_field,
1643*4d9fdb46SRobert Mustacchi             DWARF_32BIT_SIZE,error,section_end);
1644*4d9fdb46SRobert Mustacchi         SIGN_EXTEND(val, DWARF_32BIT_SIZE);
1645*4d9fdb46SRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1646*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + DWARF_32BIT_SIZE;
164707dc1947SRichard Lowe         }
164807dc1947SRichard Lowe         break;
164907dc1947SRichard Lowe     case DW_EH_PE_sdata8:{
1650*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned val = 0;
1651*4d9fdb46SRobert Mustacchi 
1652*4d9fdb46SRobert Mustacchi         /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
1653*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, val,
1654*4d9fdb46SRobert Mustacchi             Dwarf_Unsigned, input_field,
1655*4d9fdb46SRobert Mustacchi             DWARF_64BIT_SIZE,error,section_end);
1656*4d9fdb46SRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1657*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + DWARF_64BIT_SIZE;
165807dc1947SRichard Lowe         }
165907dc1947SRichard Lowe         break;
166007dc1947SRichard Lowe     default:
1661*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
166207dc1947SRichard Lowe         return DW_DLV_ERROR;
166307dc1947SRichard Lowe 
166407dc1947SRichard Lowe     };
1665*4d9fdb46SRobert Mustacchi     /*  The ELF ABI for gnu does not document the meaning of
1666*4d9fdb46SRobert Mustacchi         DW_EH_PE_pcrel, which is awkward.  It apparently means the value
1667*4d9fdb46SRobert Mustacchi         we got above is pc-relative (meaning section-relative), so we
1668*4d9fdb46SRobert Mustacchi         adjust the value. Section_pointer may be null if it is known
1669*4d9fdb46SRobert Mustacchi         DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an
1670*4d9fdb46SRobert Mustacchi         address-range value. */
167107dc1947SRichard Lowe     if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
1672*4d9fdb46SRobert Mustacchi         /*  Address (*addr) above is pc relative with respect to a
1673*4d9fdb46SRobert Mustacchi             section. Add to the offset the base address (from elf) of
1674*4d9fdb46SRobert Mustacchi             section and the distance of the field we are reading from
1675*4d9fdb46SRobert Mustacchi             the section-beginning to get the actual address. */
1676*4d9fdb46SRobert Mustacchi         /*  ASSERT: input_field_original >= section_pointer */
167707dc1947SRichard Lowe         Dwarf_Unsigned distance =
167807dc1947SRichard Lowe             input_field_original - section_pointer;
167907dc1947SRichard Lowe         *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
168007dc1947SRichard Lowe     }
168107dc1947SRichard Lowe     return DW_DLV_OK;
168207dc1947SRichard Lowe }
168307dc1947SRichard Lowe 
1684*4d9fdb46SRobert Mustacchi /*  All augmentation string checking done here now.
168507dc1947SRichard Lowe 
1686*4d9fdb46SRobert Mustacchi     For .eh_frame, gcc from 3.3 uses the z style, earlier used
1687*4d9fdb46SRobert Mustacchi     only "eh" as augmentation.  We don't yet handle
1688*4d9fdb46SRobert Mustacchi     decoding .eh_frame with the z style extensions like L P.
1689*4d9fdb46SRobert Mustacchi     gnu_aug_encodings() does handle L P.
169007dc1947SRichard Lowe 
1691*4d9fdb46SRobert Mustacchi     These are nasty heuristics, but then that's life
1692*4d9fdb46SRobert Mustacchi     as augmentations are implementation specific.  */
169307dc1947SRichard Lowe /* ARGSUSED */
169407dc1947SRichard Lowe enum Dwarf_augmentation_type
_dwarf_get_augmentation_type(UNUSEDARG Dwarf_Debug dbg,Dwarf_Small * augmentation_string,int is_gcc_eh_frame)1695*4d9fdb46SRobert Mustacchi _dwarf_get_augmentation_type(UNUSEDARG Dwarf_Debug dbg,
169607dc1947SRichard Lowe     Dwarf_Small * augmentation_string,
169707dc1947SRichard Lowe     int is_gcc_eh_frame)
169807dc1947SRichard Lowe {
169907dc1947SRichard Lowe     enum Dwarf_augmentation_type t = aug_unknown;
170007dc1947SRichard Lowe     char *ag_string = (char *) augmentation_string;
170107dc1947SRichard Lowe 
170207dc1947SRichard Lowe     if (ag_string[0] == 0) {
1703*4d9fdb46SRobert Mustacchi         /*  Empty string. We'll just guess that we know what this means:
1704*4d9fdb46SRobert Mustacchi             standard dwarf2/3 with no implementation-defined fields.  */
170507dc1947SRichard Lowe         t = aug_empty_string;
170607dc1947SRichard Lowe     } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
1707*4d9fdb46SRobert Mustacchi         /*  The string is "mti v1". Used internally at SGI, probably
1708*4d9fdb46SRobert Mustacchi             never shipped. Replaced by "z". Treat like 'nothing
1709*4d9fdb46SRobert Mustacchi             special'.  */
171007dc1947SRichard Lowe         t = aug_irix_mti_v1;
171107dc1947SRichard Lowe     } else if (ag_string[0] == 'z') {
1712*4d9fdb46SRobert Mustacchi         /*  If it's IRIX cc, z means aug_irix_exception_table. z1 z2
1713*4d9fdb46SRobert Mustacchi             were designed as for IRIX CC, but never implemented */
1714*4d9fdb46SRobert Mustacchi         /*  If it's gcc, z may be any of several things. "z" or z
1715*4d9fdb46SRobert Mustacchi             followed optionally followed by one or more of L R P, each
1716*4d9fdb46SRobert Mustacchi             of which means a value may be present. Should be in eh_frame
1717*4d9fdb46SRobert Mustacchi             only, I think. */
171807dc1947SRichard Lowe         if (is_gcc_eh_frame) {
171907dc1947SRichard Lowe             t = aug_gcc_eh_z;
172007dc1947SRichard Lowe         } else if (ag_string[1] == 0) {
1721*4d9fdb46SRobert Mustacchi             /*  This is the normal IRIX C++ case, where there is an
1722*4d9fdb46SRobert Mustacchi                 offset into a table in each fde. The table being for
1723*4d9fdb46SRobert Mustacchi                 IRIX CC exception handling.  */
1724*4d9fdb46SRobert Mustacchi             /*  DW_CIE_AUGMENTER_STRING_V0 "z" */
172507dc1947SRichard Lowe             t = aug_irix_exception_table;
172607dc1947SRichard Lowe         }                       /* Else unknown. */
172707dc1947SRichard Lowe     } else if (strncmp(ag_string, "eh", 2) == 0) {
1728*4d9fdb46SRobert Mustacchi         /*  gcc .eh_frame augmentation for egcs and gcc 2.x, at least
1729*4d9fdb46SRobert Mustacchi             for x86. */
173007dc1947SRichard Lowe         t = aug_eh;
173107dc1947SRichard Lowe     } else if (strcmp(ag_string, "armcc+") == 0) {
1732*4d9fdb46SRobert Mustacchi         /*  Arm  uses this string to mean a bug in
1733*4d9fdb46SRobert Mustacchi             in Arm compilers was fixed, changing to the standard
1734*4d9fdb46SRobert Mustacchi             calculation of the CFA.  See
1735*4d9fdb46SRobert Mustacchi             http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
1736*4d9fdb46SRobert Mustacchi             for details. */
173707dc1947SRichard Lowe         t = aug_armcc;
1738*4d9fdb46SRobert Mustacchi     } else if (strcmp(ag_string, "HC") == 0) {
1739*4d9fdb46SRobert Mustacchi         t = aug_metaware;
174007dc1947SRichard Lowe     } else {
174107dc1947SRichard Lowe     }
174207dc1947SRichard Lowe     return t;
174307dc1947SRichard Lowe }
174407dc1947SRichard Lowe 
1745*4d9fdb46SRobert Mustacchi /*  Using augmentation, and version
1746*4d9fdb46SRobert Mustacchi     read in the augmentation data for GNU eh.
1747*4d9fdb46SRobert Mustacchi 
1748*4d9fdb46SRobert Mustacchi     Return DW_DLV_OK if we succeeded,
1749*4d9fdb46SRobert Mustacchi     DW_DLV_ERR if we fail.
175007dc1947SRichard Lowe 
1751*4d9fdb46SRobert Mustacchi     On success, update  'size_of_augmentation_data' with
1752*4d9fdb46SRobert Mustacchi     the length of the fields that are part of augmentation (so the
1753*4d9fdb46SRobert Mustacchi     caller can increment frame_ptr appropriately).
175407dc1947SRichard Lowe 
1755*4d9fdb46SRobert Mustacchi     'frame_ptr' points within section.
1756*4d9fdb46SRobert Mustacchi     'section_end' points to end of section area of interest.
175707dc1947SRichard Lowe 
175807dc1947SRichard Lowe */
175907dc1947SRichard Lowe /* ARGSUSED */
176007dc1947SRichard Lowe static int
get_gcc_eh_augmentation(Dwarf_Debug dbg,Dwarf_Small * frame_ptr,unsigned long * size_of_augmentation_data,enum Dwarf_augmentation_type augtype,Dwarf_Small * section_ptr_end,char * augmentation,Dwarf_Error * error)176107dc1947SRichard Lowe get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
176207dc1947SRichard Lowe     unsigned long *size_of_augmentation_data,
176307dc1947SRichard Lowe     enum Dwarf_augmentation_type augtype,
1764*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
1765*4d9fdb46SRobert Mustacchi     char *augmentation,
1766*4d9fdb46SRobert Mustacchi     Dwarf_Error *error)
176707dc1947SRichard Lowe {
176807dc1947SRichard Lowe     char *suffix = 0;
176907dc1947SRichard Lowe     unsigned long augdata_size = 0;
177007dc1947SRichard Lowe 
177107dc1947SRichard Lowe     if (augtype == aug_gcc_eh_z) {
177207dc1947SRichard Lowe         /* Has leading 'z'. */
1773*4d9fdb46SRobert Mustacchi         UNUSEDARG Dwarf_Unsigned val = 0;
1774*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned leb128_length = 0;
177507dc1947SRichard Lowe 
177607dc1947SRichard Lowe         /* Dwarf_Unsigned eh_value = */
1777*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_LEN_CK(frame_ptr,val,leb128_length,
1778*4d9fdb46SRobert Mustacchi             dbg,error,section_ptr_end);
177907dc1947SRichard Lowe         augdata_size += leb128_length;
178007dc1947SRichard Lowe         suffix = augmentation + 1;
178107dc1947SRichard Lowe     } else {
1782*4d9fdb46SRobert Mustacchi         /*  Prefix is 'eh'.  As in gcc 3.2. No suffix present
1783*4d9fdb46SRobert Mustacchi             apparently. */
178407dc1947SRichard Lowe         suffix = augmentation + 2;
178507dc1947SRichard Lowe     }
1786*4d9fdb46SRobert Mustacchi     /*  FIXME: This could run  too far. */
1787*4d9fdb46SRobert Mustacchi     /* for (; *suffix; ++suffix) if we think we can do something  */
1788*4d9fdb46SRobert Mustacchi     if (*suffix) {
1789*4d9fdb46SRobert Mustacchi         /*  We have no idea what this is as yet.
1790*4d9fdb46SRobert Mustacchi             Some extensions beyond
1791*4d9fdb46SRobert Mustacchi             dwarf exist which we do not yet handle. */
1792*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
179307dc1947SRichard Lowe         return DW_DLV_ERROR;
179407dc1947SRichard Lowe 
179507dc1947SRichard Lowe     }
179607dc1947SRichard Lowe 
179707dc1947SRichard Lowe     *size_of_augmentation_data = augdata_size;
179807dc1947SRichard Lowe     return DW_DLV_OK;
179907dc1947SRichard Lowe }
180007dc1947SRichard Lowe 
180107dc1947SRichard Lowe 
180207dc1947SRichard Lowe /* To properly release all spaced used.
180307dc1947SRichard Lowe    Earlier approaches (before July 15, 2005)
180407dc1947SRichard Lowe    letting client do the dealloc directly left
180507dc1947SRichard Lowe    some data allocated.
180607dc1947SRichard Lowe    This is directly called by consumer code.
180707dc1947SRichard Lowe */
180807dc1947SRichard Lowe void
dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,Dwarf_Cie * cie_data,Dwarf_Signed cie_element_count,Dwarf_Fde * fde_data,Dwarf_Signed fde_element_count)180907dc1947SRichard Lowe dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
181007dc1947SRichard Lowe     Dwarf_Cie * cie_data,
181107dc1947SRichard Lowe     Dwarf_Signed cie_element_count,
181207dc1947SRichard Lowe     Dwarf_Fde * fde_data,
181307dc1947SRichard Lowe     Dwarf_Signed fde_element_count)
181407dc1947SRichard Lowe {
181507dc1947SRichard Lowe     Dwarf_Signed i = 0;
181607dc1947SRichard Lowe 
181707dc1947SRichard Lowe     for (i = 0; i < cie_element_count; ++i) {
181807dc1947SRichard Lowe         Dwarf_Frame frame = cie_data[i]->ci_initial_table;
181907dc1947SRichard Lowe 
1820*4d9fdb46SRobert Mustacchi         if (frame) {
182107dc1947SRichard Lowe             dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
1822*4d9fdb46SRobert Mustacchi         }
182307dc1947SRichard Lowe         dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
182407dc1947SRichard Lowe     }
182507dc1947SRichard Lowe     for (i = 0; i < fde_element_count; ++i) {
182607dc1947SRichard Lowe         dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
182707dc1947SRichard Lowe     }
1828*4d9fdb46SRobert Mustacchi     if (cie_data) {
182907dc1947SRichard Lowe         dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
1830*4d9fdb46SRobert Mustacchi     }
1831*4d9fdb46SRobert Mustacchi     if (fde_data) {
183207dc1947SRichard Lowe         dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
1833*4d9fdb46SRobert Mustacchi     }
183407dc1947SRichard Lowe }
1835