xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_frame2.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
1bc1f688bSRobert Mustacchi /*
2bc1f688bSRobert Mustacchi   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.
5bc1f688bSRobert 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.
10bc1f688bSRobert 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.
15bc1f688bSRobert 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.
23bc1f688bSRobert 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.
28bc1f688bSRobert Mustacchi 
29bc1f688bSRobert Mustacchi */
30bc1f688bSRobert Mustacchi 
31*4d9fdb46SRobert Mustacchi /*  This  implements _dwarf_get_fde_list_internal()
32*4d9fdb46SRobert Mustacchi     and related helper functions for reading cie/fde data.  */
33bc1f688bSRobert Mustacchi 
34bc1f688bSRobert Mustacchi #include "config.h"
35bc1f688bSRobert Mustacchi #include <stdio.h>
36*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDLIB_H
37bc1f688bSRobert 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"
43bc1f688bSRobert 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"
46bc1f688bSRobert Mustacchi 
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.
52*4d9fdb46SRobert Mustacchi 
53*4d9fdb46SRobert Mustacchi     .eh_frame_hdr contains data for C++ unwinding. Namely
54*4d9fdb46SRobert Mustacchi     tables for fast access into .eh_frame.
55*4d9fdb46SRobert Mustacchi */
56*4d9fdb46SRobert Mustacchi 
57*4d9fdb46SRobert Mustacchi 
58*4d9fdb46SRobert Mustacchi 
59*4d9fdb46SRobert Mustacchi #define TRUE 1
60*4d9fdb46SRobert Mustacchi #define FALSE 0
61*4d9fdb46SRobert Mustacchi 
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 }
75*4d9fdb46SRobert Mustacchi 
76*4d9fdb46SRobert Mustacchi #endif
77bc1f688bSRobert Mustacchi 
78bc1f688bSRobert Mustacchi static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
79bc1f688bSRobert Mustacchi     Dwarf_Cie cur_cie_ptr,
80bc1f688bSRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
81bc1f688bSRobert Mustacchi     Dwarf_Cie head_cie_ptr);
82bc1f688bSRobert Mustacchi static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
83bc1f688bSRobert Mustacchi     Dwarf_Cie head_cie_ptr);
84bc1f688bSRobert Mustacchi static int dwarf_create_cie_from_start(Dwarf_Debug dbg,
85bc1f688bSRobert Mustacchi     Dwarf_Small * cie_ptr_val,
86bc1f688bSRobert Mustacchi     Dwarf_Small * section_ptr,
87bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_index,
88bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_length,
89*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
90bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_id_value,
91bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_count,
92bc1f688bSRobert Mustacchi     int use_gnu_cie_calc,
93bc1f688bSRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
94bc1f688bSRobert Mustacchi     Dwarf_Error * error);
95bc1f688bSRobert Mustacchi 
96bc1f688bSRobert Mustacchi static int get_gcc_eh_augmentation(Dwarf_Debug dbg,
97bc1f688bSRobert Mustacchi     Dwarf_Small * frame_ptr,
98bc1f688bSRobert Mustacchi     unsigned long
99bc1f688bSRobert Mustacchi     *size_of_augmentation_data,
100bc1f688bSRobert 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);
104bc1f688bSRobert Mustacchi 
105bc1f688bSRobert Mustacchi static int
106bc1f688bSRobert Mustacchi gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
107bc1f688bSRobert Mustacchi     Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
108bc1f688bSRobert Mustacchi     Dwarf_Half address_size,
109bc1f688bSRobert Mustacchi     unsigned char *pers_hand_enc_out,
110bc1f688bSRobert Mustacchi     unsigned char *lsda_enc_out,
111bc1f688bSRobert Mustacchi     unsigned char *fde_begin_enc_out,
112*4d9fdb46SRobert Mustacchi     Dwarf_Addr * gnu_pers_addr_out,
113*4d9fdb46SRobert Mustacchi     Dwarf_Error *error);
114bc1f688bSRobert Mustacchi 
115bc1f688bSRobert Mustacchi 
116bc1f688bSRobert Mustacchi static int read_encoded_ptr(Dwarf_Debug dbg,
117bc1f688bSRobert Mustacchi     Dwarf_Small * section_pointer,
118bc1f688bSRobert Mustacchi     Dwarf_Small * input_field,
119bc1f688bSRobert Mustacchi     int gnu_encoding,
120*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
121bc1f688bSRobert Mustacchi     Dwarf_Half address_size,
122bc1f688bSRobert Mustacchi     Dwarf_Unsigned * addr,
123*4d9fdb46SRobert Mustacchi     Dwarf_Small ** input_field_out,
124*4d9fdb46SRobert Mustacchi     Dwarf_Error *error);
125bc1f688bSRobert Mustacchi 
126bc1f688bSRobert Mustacchi 
127bc1f688bSRobert Mustacchi 
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;
139bc1f688bSRobert Mustacchi 
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 }
147bc1f688bSRobert Mustacchi 
148bc1f688bSRobert Mustacchi /*  Adds 'newone' to the end of the list starting at 'head'
149bc1f688bSRobert Mustacchi     and makes the new one 'cur'rent. */
150bc1f688bSRobert Mustacchi static void
chain_up_fde(Dwarf_Fde newone,Dwarf_Fde * head,Dwarf_Fde * cur)151bc1f688bSRobert Mustacchi chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
152bc1f688bSRobert Mustacchi {
153bc1f688bSRobert Mustacchi     if (*head == NULL)
154bc1f688bSRobert Mustacchi         *head = newone;
155bc1f688bSRobert Mustacchi     else {
156bc1f688bSRobert Mustacchi         (*cur)->fd_next = newone;
157bc1f688bSRobert Mustacchi     }
158bc1f688bSRobert Mustacchi     *cur = newone;
159bc1f688bSRobert Mustacchi 
160bc1f688bSRobert Mustacchi }
161bc1f688bSRobert Mustacchi 
162bc1f688bSRobert Mustacchi /*  Adds 'newone' to the end of the list starting at 'head'
163bc1f688bSRobert Mustacchi     and makes the new one 'cur'rent. */
164bc1f688bSRobert Mustacchi static void
chain_up_cie(Dwarf_Cie newone,Dwarf_Cie * head,Dwarf_Cie * cur)165bc1f688bSRobert Mustacchi chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
166bc1f688bSRobert Mustacchi {
167bc1f688bSRobert Mustacchi     if (*head == NULL) {
168bc1f688bSRobert Mustacchi         *head = newone;
169bc1f688bSRobert Mustacchi     } else {
170bc1f688bSRobert Mustacchi         (*cur)->ci_next = newone;
171bc1f688bSRobert Mustacchi     }
172bc1f688bSRobert Mustacchi     *cur = newone;
173bc1f688bSRobert Mustacchi }
174bc1f688bSRobert Mustacchi 
175bc1f688bSRobert Mustacchi /*  The size of the length field plus the
176bc1f688bSRobert Mustacchi     value of length must be an integral
177bc1f688bSRobert Mustacchi     multiple of the address size.  Dwarf4 standard.
178bc1f688bSRobert Mustacchi 
179bc1f688bSRobert Mustacchi     A constant that gives the number of bytes of the CIE
180bc1f688bSRobert Mustacchi     structure, not including the length field itself
181bc1f688bSRobert Mustacchi     (where length mod <size of an address> == 0)
182bc1f688bSRobert Mustacchi     (see Section 7.2.2). Dwarf3 standard.
183bc1f688bSRobert Mustacchi 
184bc1f688bSRobert Mustacchi     A uword constant that gives the number of bytes of
185bc1f688bSRobert Mustacchi     the CIE structure, not including the
186bc1f688bSRobert Mustacchi     length field, itself (length mod <addressing unit size> == 0).
187bc1f688bSRobert Mustacchi     Dwarf2 standard.*/
188bc1f688bSRobert Mustacchi 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)189bc1f688bSRobert Mustacchi validate_length(Dwarf_Debug dbg,
190bc1f688bSRobert Mustacchi     Dwarf_Cie cieptr, Dwarf_Unsigned length,
191bc1f688bSRobert Mustacchi     Dwarf_Unsigned length_size,
192bc1f688bSRobert Mustacchi     Dwarf_Unsigned extension_size,
193bc1f688bSRobert Mustacchi     Dwarf_Small * section_ptr,
194bc1f688bSRobert Mustacchi     Dwarf_Small * ciefde_start,
195bc1f688bSRobert Mustacchi     const char * cieorfde)
196bc1f688bSRobert Mustacchi {
197*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned address_size = 0;
198bc1f688bSRobert Mustacchi     Dwarf_Unsigned length_field_summed = length_size + extension_size;
199bc1f688bSRobert Mustacchi     Dwarf_Unsigned total_len = length + length_field_summed;
200*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned mod = 0;
201bc1f688bSRobert Mustacchi 
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;
208bc1f688bSRobert Mustacchi     if (mod != 0) {
209*4d9fdb46SRobert Mustacchi         dwarfstring  harm;
210bc1f688bSRobert Mustacchi         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,
218bc1f688bSRobert Mustacchi             "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 ".",
240bc1f688bSRobert Mustacchi             sectionoffset);
241*4d9fdb46SRobert Mustacchi         dwarf_insert_harmless_error(dbg,
242*4d9fdb46SRobert Mustacchi             dwarfstring_string(&harm));
243*4d9fdb46SRobert Mustacchi         dwarfstring_destructor(&harm);
244bc1f688bSRobert Mustacchi     }
245bc1f688bSRobert Mustacchi     return;
246bc1f688bSRobert Mustacchi }
247bc1f688bSRobert Mustacchi 
248bc1f688bSRobert Mustacchi 
249*4d9fdb46SRobert Mustacchi #if 0 /* FOR DEBUGGING */
250bc1f688bSRobert Mustacchi /* For debugging only. */
251bc1f688bSRobert Mustacchi static void
252bc1f688bSRobert Mustacchi print_prefix(struct cie_fde_prefix_s *prefix, int line)
253bc1f688bSRobert Mustacchi {
254bc1f688bSRobert Mustacchi     printf("prefix-print, prefix at 0x%lx, line %d\n",
255*4d9fdb46SRobert Mustacchi         (unsigned long) prefix, line);
256bc1f688bSRobert Mustacchi     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);
259bc1f688bSRobert Mustacchi     printf("  length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
260bc1f688bSRobert Mustacchi         (Dwarf_Unsigned) prefix->cf_length,
261bc1f688bSRobert Mustacchi         prefix->cf_local_length_size,
262bc1f688bSRobert Mustacchi         prefix->cf_local_extension_size);
263bc1f688bSRobert Mustacchi     printf("  cie_id 0x%" DW_PR_DUx " cie_id  cie_id_addr 0x%lx\n",
264bc1f688bSRobert Mustacchi         (Dwarf_Unsigned) prefix->cf_cie_id,
265bc1f688bSRobert Mustacchi         (long) prefix->cf_cie_id_addr);
266bc1f688bSRobert Mustacchi     printf
267bc1f688bSRobert Mustacchi         ("  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,
269bc1f688bSRobert Mustacchi         (Dwarf_Signed) prefix->cf_section_index,
270bc1f688bSRobert 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);
273bc1f688bSRobert Mustacchi }
274bc1f688bSRobert Mustacchi #endif
275bc1f688bSRobert Mustacchi 
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 */
294*4d9fdb46SRobert Mustacchi 
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;
302*4d9fdb46SRobert Mustacchi 
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 
315bc1f688bSRobert Mustacchi 
316bc1f688bSRobert Mustacchi 
317bc1f688bSRobert Mustacchi /*  Internal function called from various places to create
318bc1f688bSRobert Mustacchi     lists of CIEs and FDEs.  Not directly called
319bc1f688bSRobert Mustacchi     by consumer code */
320bc1f688bSRobert Mustacchi 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)321bc1f688bSRobert Mustacchi _dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
322bc1f688bSRobert Mustacchi     Dwarf_Signed * cie_element_count,
323bc1f688bSRobert Mustacchi     Dwarf_Fde ** fde_data,
324bc1f688bSRobert Mustacchi     Dwarf_Signed * fde_element_count,
325bc1f688bSRobert Mustacchi     Dwarf_Small * section_ptr,
326bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_index,
327bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_length,
328bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_id_value,
329bc1f688bSRobert Mustacchi     int use_gnu_cie_calc, Dwarf_Error * error)
330bc1f688bSRobert Mustacchi {
331bc1f688bSRobert Mustacchi     /* Scans the debug_frame section. */
332bc1f688bSRobert Mustacchi     Dwarf_Small *frame_ptr = section_ptr;
333*4d9fdb46SRobert Mustacchi     Dwarf_Small *section_ptr_end = section_ptr + section_length;
334bc1f688bSRobert Mustacchi 
335bc1f688bSRobert Mustacchi 
336bc1f688bSRobert Mustacchi 
337*4d9fdb46SRobert Mustacchi     /*  New_cie points to the Cie being read, and head_cie_ptr and
338bc1f688bSRobert Mustacchi         cur_cie_ptr are used for chaining them up in sequence.
339bc1f688bSRobert Mustacchi         In case cie's are reused aggressively we need tail_cie_ptr
340bc1f688bSRobert Mustacchi         to add to the chain.  If we re-use an early cie
341bc1f688bSRobert Mustacchi         later on, that does not mean we chain a new cie to the early one,
342bc1f688bSRobert Mustacchi         we always chain it to the tail.  */
343bc1f688bSRobert Mustacchi     Dwarf_Cie head_cie_ptr = NULL;
344bc1f688bSRobert Mustacchi     Dwarf_Cie cur_cie_ptr = NULL;
345bc1f688bSRobert Mustacchi     Dwarf_Cie tail_cie_ptr = NULL;
346*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned cie_count = 0;
347bc1f688bSRobert Mustacchi 
348*4d9fdb46SRobert Mustacchi     /*  Points to a list of contiguous pointers to Dwarf_Cie structures.
349bc1f688bSRobert Mustacchi     */
350bc1f688bSRobert Mustacchi     Dwarf_Cie *cie_list_ptr = 0;
351bc1f688bSRobert Mustacchi 
352bc1f688bSRobert Mustacchi 
353*4d9fdb46SRobert Mustacchi     /*  New_fde points to the Fde being created, and head_fde_ptr and
354bc1f688bSRobert Mustacchi         cur_fde_ptr are used to chain them up. */
355bc1f688bSRobert Mustacchi     Dwarf_Fde head_fde_ptr = NULL;
356bc1f688bSRobert Mustacchi     Dwarf_Fde cur_fde_ptr = NULL;
357*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned fde_count = 0;
358bc1f688bSRobert Mustacchi 
359*4d9fdb46SRobert Mustacchi     /*  Points to a list of contiguous pointers to Dwarf_Fde structures.
360bc1f688bSRobert Mustacchi     */
361bc1f688bSRobert Mustacchi     Dwarf_Fde *fde_list_ptr = NULL;
362bc1f688bSRobert Mustacchi 
363*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned i = 0;
364bc1f688bSRobert Mustacchi     int res = DW_DLV_ERROR;
365bc1f688bSRobert Mustacchi 
366bc1f688bSRobert Mustacchi     if (frame_ptr == 0) {
367bc1f688bSRobert Mustacchi         return DW_DLV_NO_ENTRY;
368bc1f688bSRobert Mustacchi     }
369bc1f688bSRobert Mustacchi 
370bc1f688bSRobert Mustacchi     /*  We create the fde and cie arrays. Processing each CIE as we come
371bc1f688bSRobert Mustacchi         to it or as an FDE refers to it.  We cannot process 'late' CIEs
372bc1f688bSRobert Mustacchi         late as GNU .eh_frame complexities mean we need the whole CIE
373bc1f688bSRobert Mustacchi         before we can process the FDE correctly. */
374*4d9fdb46SRobert Mustacchi     while (frame_ptr < section_ptr_end) {
375bc1f688bSRobert Mustacchi 
376bc1f688bSRobert Mustacchi         struct cie_fde_prefix_s prefix;
377bc1f688bSRobert Mustacchi 
378bc1f688bSRobert Mustacchi         /*  First read in the 'common prefix' to figure out what we are
379bc1f688bSRobert Mustacchi             to do with this entry. */
380bc1f688bSRobert Mustacchi         memset(&prefix, 0, sizeof(prefix));
381bc1f688bSRobert Mustacchi         res = dwarf_read_cie_fde_prefix(dbg,
382bc1f688bSRobert Mustacchi             frame_ptr, section_ptr,
383bc1f688bSRobert Mustacchi             section_index,
384bc1f688bSRobert Mustacchi             section_length, &prefix, error);
385bc1f688bSRobert Mustacchi         if (res == DW_DLV_ERROR) {
386*4d9fdb46SRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr,
387*4d9fdb46SRobert Mustacchi                 head_cie_ptr);
388bc1f688bSRobert Mustacchi             return res;
389bc1f688bSRobert Mustacchi         }
390*4d9fdb46SRobert Mustacchi         if (res == DW_DLV_NO_ENTRY) {
391bc1f688bSRobert Mustacchi             break;
392*4d9fdb46SRobert Mustacchi         }
393bc1f688bSRobert Mustacchi         frame_ptr = prefix.cf_addr_after_prefix;
394*4d9fdb46SRobert Mustacchi         if (frame_ptr >= section_ptr_end) {
395bc1f688bSRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
396bc1f688bSRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
397bc1f688bSRobert Mustacchi             return DW_DLV_ERROR;
398bc1f688bSRobert Mustacchi         }
399bc1f688bSRobert Mustacchi 
400bc1f688bSRobert Mustacchi         if (prefix.cf_cie_id == cie_id_value) {
401bc1f688bSRobert Mustacchi             /* This is a CIE.  */
402bc1f688bSRobert Mustacchi             Dwarf_Cie cie_ptr_to_use = 0;
403*4d9fdb46SRobert Mustacchi             int resc = 0;
404bc1f688bSRobert Mustacchi 
405*4d9fdb46SRobert Mustacchi             resc = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
406bc1f688bSRobert Mustacchi                 cur_cie_ptr,
407bc1f688bSRobert Mustacchi                 &cie_ptr_to_use,
408bc1f688bSRobert Mustacchi                 head_cie_ptr);
409*4d9fdb46SRobert Mustacchi             if (resc == DW_DLV_OK) {
410bc1f688bSRobert Mustacchi                 cur_cie_ptr = cie_ptr_to_use;
411bc1f688bSRobert Mustacchi                 /* Ok. Seen already. */
412*4d9fdb46SRobert Mustacchi             } else if (resc == DW_DLV_NO_ENTRY) {
413bc1f688bSRobert Mustacchi                 /* CIE before its FDE in this case. */
414*4d9fdb46SRobert Mustacchi                 resc = dwarf_create_cie_from_after_start(dbg,
415bc1f688bSRobert Mustacchi                     &prefix,
416bc1f688bSRobert Mustacchi                     section_ptr,
417bc1f688bSRobert Mustacchi                     frame_ptr,
418*4d9fdb46SRobert Mustacchi                     section_ptr_end,
419bc1f688bSRobert Mustacchi                     cie_count,
420bc1f688bSRobert Mustacchi                     use_gnu_cie_calc,
421bc1f688bSRobert Mustacchi                     &cie_ptr_to_use,
422bc1f688bSRobert Mustacchi                     error);
423*4d9fdb46SRobert Mustacchi                 if (resc != DW_DLV_OK) {
424bc1f688bSRobert Mustacchi                     dealloc_fde_cie_list_internal(head_fde_ptr,
425bc1f688bSRobert Mustacchi                         head_cie_ptr);
426*4d9fdb46SRobert Mustacchi                     return resc;
427bc1f688bSRobert Mustacchi                 }
428bc1f688bSRobert Mustacchi                 cie_count++;
429bc1f688bSRobert Mustacchi                 chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
430bc1f688bSRobert Mustacchi                     &tail_cie_ptr);
431bc1f688bSRobert Mustacchi                 cur_cie_ptr = tail_cie_ptr;
432bc1f688bSRobert Mustacchi             } else {            /* res == DW_DLV_ERROR */
433bc1f688bSRobert Mustacchi 
434bc1f688bSRobert Mustacchi                 dealloc_fde_cie_list_internal(head_fde_ptr,
435bc1f688bSRobert Mustacchi                     head_cie_ptr);
436*4d9fdb46SRobert Mustacchi                 return resc;
437bc1f688bSRobert Mustacchi             }
438bc1f688bSRobert Mustacchi             frame_ptr = cie_ptr_to_use->ci_cie_start +
439bc1f688bSRobert Mustacchi                 cie_ptr_to_use->ci_length +
440bc1f688bSRobert Mustacchi                 cie_ptr_to_use->ci_length_size +
441bc1f688bSRobert Mustacchi                 cie_ptr_to_use->ci_extension_size;
442bc1f688bSRobert Mustacchi             continue;
443bc1f688bSRobert Mustacchi         } 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;
449bc1f688bSRobert Mustacchi             Dwarf_Cie cie_ptr_to_use = 0;
450bc1f688bSRobert Mustacchi             Dwarf_Fde fde_ptr_to_use = 0;
451*4d9fdb46SRobert Mustacchi             Dwarf_Small *cieptr_val = 0;
452bc1f688bSRobert Mustacchi 
453*4d9fdb46SRobert Mustacchi             cieptr_val = get_cieptr_given_offset(prefix.cf_cie_id,
454bc1f688bSRobert Mustacchi                 use_gnu_cie_calc,
455bc1f688bSRobert Mustacchi                 section_ptr,
456bc1f688bSRobert Mustacchi                 prefix.cf_cie_id_addr);
457*4d9fdb46SRobert Mustacchi             resf = dwarf_find_existing_cie_ptr(cieptr_val,
458bc1f688bSRobert Mustacchi                 cur_cie_ptr,
459bc1f688bSRobert Mustacchi                 &cie_ptr_to_use,
460bc1f688bSRobert Mustacchi                 head_cie_ptr);
461*4d9fdb46SRobert Mustacchi             if (resf == DW_DLV_OK) {
462bc1f688bSRobert Mustacchi                 cur_cie_ptr = cie_ptr_to_use;
463bc1f688bSRobert Mustacchi                 /* Ok. Seen CIE already. */
464*4d9fdb46SRobert Mustacchi             } else if (resf == DW_DLV_NO_ENTRY) {
465*4d9fdb46SRobert Mustacchi                 resf = dwarf_create_cie_from_start(dbg,
466bc1f688bSRobert Mustacchi                     cieptr_val,
467bc1f688bSRobert Mustacchi                     section_ptr,
468bc1f688bSRobert Mustacchi                     section_index,
469bc1f688bSRobert Mustacchi                     section_length,
470*4d9fdb46SRobert Mustacchi                     section_ptr_end,
471bc1f688bSRobert Mustacchi                     cie_id_value,
472bc1f688bSRobert Mustacchi                     cie_count,
473bc1f688bSRobert Mustacchi                     use_gnu_cie_calc,
474bc1f688bSRobert Mustacchi                     &cie_ptr_to_use,
475bc1f688bSRobert Mustacchi                     error);
476*4d9fdb46SRobert Mustacchi                 if (resf == DW_DLV_ERROR) {
477bc1f688bSRobert Mustacchi                     dealloc_fde_cie_list_internal(head_fde_ptr,
478bc1f688bSRobert Mustacchi                         head_cie_ptr);
479*4d9fdb46SRobert Mustacchi                     return resf;
480*4d9fdb46SRobert Mustacchi                 } else if (resf == DW_DLV_NO_ENTRY) {
481*4d9fdb46SRobert Mustacchi                     return resf;
482bc1f688bSRobert Mustacchi                 }
483bc1f688bSRobert Mustacchi                 ++cie_count;
484bc1f688bSRobert Mustacchi                 chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
485bc1f688bSRobert Mustacchi                     &tail_cie_ptr);
486bc1f688bSRobert Mustacchi                 cur_cie_ptr = tail_cie_ptr;
487bc1f688bSRobert Mustacchi 
488bc1f688bSRobert Mustacchi             } else {
489bc1f688bSRobert Mustacchi                 /* DW_DLV_ERROR */
490*4d9fdb46SRobert Mustacchi                 return resf;
491bc1f688bSRobert Mustacchi             }
492bc1f688bSRobert Mustacchi 
493*4d9fdb46SRobert Mustacchi             resf = dwarf_create_fde_from_after_start(dbg,
494bc1f688bSRobert Mustacchi                 &prefix,
495bc1f688bSRobert Mustacchi                 section_ptr,
496bc1f688bSRobert Mustacchi                 frame_ptr,
497*4d9fdb46SRobert Mustacchi                 section_ptr_end,
498bc1f688bSRobert Mustacchi                 use_gnu_cie_calc,
499bc1f688bSRobert Mustacchi                 cie_ptr_to_use,
500bc1f688bSRobert Mustacchi                 &fde_ptr_to_use,
501bc1f688bSRobert 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;
509bc1f688bSRobert Mustacchi             }
510bc1f688bSRobert Mustacchi             chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
511bc1f688bSRobert Mustacchi             fde_count++;
512bc1f688bSRobert Mustacchi             /* 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             }
530bc1f688bSRobert Mustacchi             continue;
531bc1f688bSRobert Mustacchi         }
532bc1f688bSRobert Mustacchi     }
533bc1f688bSRobert Mustacchi     /*  Now build list of CIEs from the list. If there are no CIEs
534bc1f688bSRobert Mustacchi         there should be no FDEs. */
535bc1f688bSRobert Mustacchi     if (cie_count > 0) {
536bc1f688bSRobert Mustacchi         cie_list_ptr = (Dwarf_Cie *)
537bc1f688bSRobert Mustacchi             _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
538bc1f688bSRobert Mustacchi     } else {
539bc1f688bSRobert Mustacchi         if (fde_count > 0) {
540bc1f688bSRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
541bc1f688bSRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
542bc1f688bSRobert Mustacchi             return DW_DLV_ERROR;
543bc1f688bSRobert Mustacchi         }
544bc1f688bSRobert Mustacchi         dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
545bc1f688bSRobert Mustacchi         return DW_DLV_NO_ENTRY;
546bc1f688bSRobert Mustacchi     }
547bc1f688bSRobert Mustacchi     if (cie_list_ptr == NULL) {
548bc1f688bSRobert Mustacchi         dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
549bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
550bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
551bc1f688bSRobert Mustacchi     }
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     }
557bc1f688bSRobert Mustacchi     cur_cie_ptr = head_cie_ptr;
558bc1f688bSRobert Mustacchi     for (i = 0; i < cie_count; i++) {
559bc1f688bSRobert Mustacchi         *(cie_list_ptr + i) = cur_cie_ptr;
560bc1f688bSRobert Mustacchi         cur_cie_ptr = cur_cie_ptr->ci_next;
561bc1f688bSRobert Mustacchi     }
562bc1f688bSRobert Mustacchi 
563bc1f688bSRobert 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 */
566bc1f688bSRobert Mustacchi     if (fde_count > 0) {
567bc1f688bSRobert Mustacchi         fde_list_ptr = (Dwarf_Fde *)
568bc1f688bSRobert Mustacchi             _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
569bc1f688bSRobert Mustacchi     }
570bc1f688bSRobert Mustacchi 
571bc1f688bSRobert Mustacchi     /* It is ok if fde_list_ptr is NULL, we just have no fdes. */
572bc1f688bSRobert Mustacchi     cur_fde_ptr = head_fde_ptr;
573bc1f688bSRobert Mustacchi     for (i = 0; i < fde_count; i++) {
574bc1f688bSRobert Mustacchi         *(fde_list_ptr + i) = cur_fde_ptr;
575bc1f688bSRobert Mustacchi         cur_fde_ptr = cur_fde_ptr->fd_next;
576bc1f688bSRobert Mustacchi     }
577bc1f688bSRobert Mustacchi 
578bc1f688bSRobert Mustacchi 
579bc1f688bSRobert Mustacchi     /* Return arguments. */
580bc1f688bSRobert Mustacchi     *cie_data = cie_list_ptr;
581bc1f688bSRobert Mustacchi     *cie_element_count = cie_count;
582bc1f688bSRobert Mustacchi 
583bc1f688bSRobert Mustacchi     *fde_data = fde_list_ptr;
584bc1f688bSRobert Mustacchi     *fde_element_count = fde_count;
585bc1f688bSRobert Mustacchi     if (use_gnu_cie_calc) {
586bc1f688bSRobert Mustacchi         dbg->de_fde_data_eh = fde_list_ptr;
587bc1f688bSRobert Mustacchi         dbg->de_fde_count_eh = fde_count;
588bc1f688bSRobert Mustacchi         dbg->de_cie_data_eh = cie_list_ptr;
589bc1f688bSRobert Mustacchi         dbg->de_cie_count_eh = cie_count;
590bc1f688bSRobert Mustacchi     } else {
591bc1f688bSRobert Mustacchi         dbg->de_fde_data = fde_list_ptr;
592bc1f688bSRobert Mustacchi         dbg->de_fde_count = fde_count;
593bc1f688bSRobert Mustacchi         dbg->de_cie_data = cie_list_ptr;
594bc1f688bSRobert Mustacchi         dbg->de_cie_count = cie_count;
595bc1f688bSRobert Mustacchi     }
596bc1f688bSRobert Mustacchi 
597bc1f688bSRobert Mustacchi     /*  Sort the list by the address so that dwarf_get_fde_at_pc() can
598bc1f688bSRobert Mustacchi         binary search this list.  */
599bc1f688bSRobert Mustacchi     if (fde_count > 0) {
600bc1f688bSRobert Mustacchi         qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
601bc1f688bSRobert Mustacchi             qsort_compare);
602bc1f688bSRobert Mustacchi     }
603bc1f688bSRobert Mustacchi 
604bc1f688bSRobert Mustacchi     return (DW_DLV_OK);
605bc1f688bSRobert Mustacchi }
606bc1f688bSRobert Mustacchi 
607bc1f688bSRobert Mustacchi /*  Internal function, not called by consumer code.
608bc1f688bSRobert Mustacchi     'prefix' has accumulated the info up thru the cie-id
609bc1f688bSRobert Mustacchi     and now we consume the rest and build a Dwarf_Cie_s structure.
610bc1f688bSRobert Mustacchi */
611bc1f688bSRobert Mustacchi 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)612bc1f688bSRobert Mustacchi dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
613bc1f688bSRobert Mustacchi     struct cie_fde_prefix_s *prefix,
614bc1f688bSRobert Mustacchi     Dwarf_Small * section_pointer,
615bc1f688bSRobert Mustacchi     Dwarf_Small * frame_ptr,
616*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
617bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_count,
618bc1f688bSRobert Mustacchi     int use_gnu_cie_calc,
619bc1f688bSRobert Mustacchi     Dwarf_Cie * cie_ptr_out,
620bc1f688bSRobert Mustacchi     Dwarf_Error * error)
621bc1f688bSRobert Mustacchi {
622bc1f688bSRobert Mustacchi     Dwarf_Cie new_cie = 0;
623bc1f688bSRobert Mustacchi 
624bc1f688bSRobert Mustacchi     /*  egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
625bc1f688bSRobert Mustacchi         -1 (in .debug_frame). .eh_frame not quite identical to
626bc1f688bSRobert Mustacchi         .debug_frame */
627bc1f688bSRobert Mustacchi     /*  We here default the address size as it is not present
628bc1f688bSRobert Mustacchi         in DWARF2 or DWARF3 cie data, below we set it right if
629bc1f688bSRobert Mustacchi         it is present. */
630bc1f688bSRobert Mustacchi     Dwarf_Half address_size = dbg->de_pointer_size;
631bc1f688bSRobert Mustacchi     Dwarf_Small *augmentation = 0;
632bc1f688bSRobert Mustacchi     Dwarf_Half segment_size = 0;
633*4d9fdb46SRobert Mustacchi     Dwarf_Signed data_alignment_factor = -1;
634*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned code_alignment_factor = 4;
635bc1f688bSRobert Mustacchi     Dwarf_Unsigned return_address_register = 31;
636bc1f688bSRobert Mustacchi     int local_length_size = 0;
637*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned leb128_length = 0;
638bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_aug_data_len = 0;
639bc1f688bSRobert Mustacchi     Dwarf_Small *cie_aug_data = 0;
640bc1f688bSRobert Mustacchi     Dwarf_Addr gnu_personality_handler_addr = 0;
641bc1f688bSRobert Mustacchi     unsigned char gnu_personality_handler_encoding = 0;
642bc1f688bSRobert Mustacchi     unsigned char gnu_lsda_encoding = 0;
643bc1f688bSRobert Mustacchi     unsigned char gnu_fde_begin_encoding = 0;
644*4d9fdb46SRobert Mustacchi     int res = 0;
645*4d9fdb46SRobert Mustacchi     Dwarf_Small version = 0;
646bc1f688bSRobert Mustacchi 
647bc1f688bSRobert Mustacchi 
648bc1f688bSRobert Mustacchi     enum Dwarf_augmentation_type augt = aug_unknown;
649bc1f688bSRobert Mustacchi 
650*4d9fdb46SRobert Mustacchi     /*  This is a CIE, Common Information Entry: See the dwarf spec,
651bc1f688bSRobert 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;
657*4d9fdb46SRobert Mustacchi 
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     }
662bc1f688bSRobert Mustacchi 
663bc1f688bSRobert Mustacchi     frame_ptr++;
664bc1f688bSRobert Mustacchi     if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
665*4d9fdb46SRobert Mustacchi         version != DW_CIE_VERSION4 && version != DW_CIE_VERSION5) {
666bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
667bc1f688bSRobert Mustacchi         return (DW_DLV_ERROR);
668bc1f688bSRobert Mustacchi     }
669bc1f688bSRobert Mustacchi 
670bc1f688bSRobert Mustacchi     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     }
678bc1f688bSRobert Mustacchi     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     }
686bc1f688bSRobert Mustacchi     augt = _dwarf_get_augmentation_type(dbg,
687bc1f688bSRobert Mustacchi         augmentation, use_gnu_cie_calc);
688bc1f688bSRobert Mustacchi     if (augt == aug_eh) {
689bc1f688bSRobert Mustacchi         /* REFERENCED *//* Not used in this instance */
690*4d9fdb46SRobert Mustacchi         UNUSEDARG Dwarf_Unsigned exception_table_addr;
691bc1f688bSRobert Mustacchi 
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         }
699bc1f688bSRobert Mustacchi         /* 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);
703bc1f688bSRobert Mustacchi         frame_ptr += local_length_size;
704bc1f688bSRobert Mustacchi     }
705bc1f688bSRobert Mustacchi     {
706bc1f688bSRobert Mustacchi         Dwarf_Unsigned lreg = 0;
707bc1f688bSRobert Mustacchi         unsigned long size = 0;
708bc1f688bSRobert Mustacchi 
709bc1f688bSRobert 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             }
717bc1f688bSRobert Mustacchi             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             }
737bc1f688bSRobert Mustacchi             ++frame_ptr;
738bc1f688bSRobert Mustacchi             segment_size = *((unsigned char *)frame_ptr);
739bc1f688bSRobert Mustacchi             ++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             }
744bc1f688bSRobert Mustacchi         }
745bc1f688bSRobert Mustacchi 
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         }
761bc1f688bSRobert Mustacchi         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");
768bc1f688bSRobert Mustacchi 
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         }
776bc1f688bSRobert Mustacchi         if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
777bc1f688bSRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
778bc1f688bSRobert Mustacchi             return (DW_DLV_ERROR);
779bc1f688bSRobert Mustacchi         }
780bc1f688bSRobert Mustacchi         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         }
788bc1f688bSRobert Mustacchi     }
789bc1f688bSRobert Mustacchi     switch (augt) {
790bc1f688bSRobert Mustacchi     case aug_empty_string:
791bc1f688bSRobert Mustacchi         break;
792bc1f688bSRobert Mustacchi     case aug_irix_mti_v1:
793bc1f688bSRobert Mustacchi         break;
794bc1f688bSRobert Mustacchi     case aug_irix_exception_table:{
795bc1f688bSRobert Mustacchi         Dwarf_Unsigned lreg = 0;
796*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned length_of_augmented_fields;
797bc1f688bSRobert Mustacchi 
798bc1f688bSRobert 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;
801bc1f688bSRobert Mustacchi         /* set the frame_ptr to point at the instruction start. */
802bc1f688bSRobert Mustacchi         frame_ptr += length_of_augmented_fields;
803bc1f688bSRobert Mustacchi         }
804bc1f688bSRobert Mustacchi         break;
805bc1f688bSRobert Mustacchi 
806bc1f688bSRobert Mustacchi     case aug_eh:{
807bc1f688bSRobert Mustacchi         int err = 0;
808bc1f688bSRobert Mustacchi         unsigned long increment = 0;
809bc1f688bSRobert Mustacchi 
810bc1f688bSRobert Mustacchi         if (!use_gnu_cie_calc) {
811bc1f688bSRobert Mustacchi             /* This should be impossible. */
812*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
813bc1f688bSRobert Mustacchi             return DW_DLV_ERROR;
814bc1f688bSRobert Mustacchi         }
815bc1f688bSRobert Mustacchi 
816bc1f688bSRobert Mustacchi         err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
817bc1f688bSRobert Mustacchi             augt,
818*4d9fdb46SRobert Mustacchi             section_ptr_end,
819*4d9fdb46SRobert Mustacchi             (char *) augmentation,error);
820bc1f688bSRobert Mustacchi         if (err == DW_DLV_ERROR) {
821*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
822bc1f688bSRobert Mustacchi             return DW_DLV_ERROR;
823bc1f688bSRobert Mustacchi         }
824bc1f688bSRobert Mustacchi         frame_ptr += increment;
825bc1f688bSRobert Mustacchi         }
826*4d9fdb46SRobert Mustacchi         break;
827bc1f688bSRobert Mustacchi     case aug_gcc_eh_z:{
828bc1f688bSRobert 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;
831bc1f688bSRobert Mustacchi         Dwarf_Unsigned adlen = 0;
832bc1f688bSRobert 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);
844bc1f688bSRobert Mustacchi         cie_aug_data_len = adlen;
845bc1f688bSRobert 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;
863*4d9fdb46SRobert Mustacchi             }
864*4d9fdb46SRobert Mustacchi         }
865*4d9fdb46SRobert Mustacchi         resz = gnu_aug_encodings(dbg,
866bc1f688bSRobert Mustacchi             (char *) augmentation,
867bc1f688bSRobert Mustacchi             cie_aug_data,
868bc1f688bSRobert Mustacchi             cie_aug_data_len,
869bc1f688bSRobert Mustacchi             address_size,
870bc1f688bSRobert Mustacchi             &gnu_personality_handler_encoding,
871bc1f688bSRobert Mustacchi             &gnu_lsda_encoding,
872bc1f688bSRobert Mustacchi             &gnu_fde_begin_encoding,
873*4d9fdb46SRobert Mustacchi             &gnu_personality_handler_addr,
874*4d9fdb46SRobert Mustacchi             error);
875*4d9fdb46SRobert Mustacchi         if (resz != DW_DLV_OK) {
876bc1f688bSRobert Mustacchi             _dwarf_error(dbg, error,
877bc1f688bSRobert Mustacchi                 DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
878*4d9fdb46SRobert Mustacchi             return resz;
879bc1f688bSRobert Mustacchi         }
880bc1f688bSRobert Mustacchi         frame_ptr += adlen;
881bc1f688bSRobert Mustacchi         }
882*4d9fdb46SRobert Mustacchi         break;
883bc1f688bSRobert Mustacchi     case aug_armcc:
884bc1f688bSRobert Mustacchi         break;
885bc1f688bSRobert Mustacchi     default:{
886bc1f688bSRobert Mustacchi         /*  We do not understand the augmentation string. No
887bc1f688bSRobert Mustacchi             assumption can be made about any fields other than what
888bc1f688bSRobert Mustacchi             we have already read. */
889bc1f688bSRobert Mustacchi         frame_ptr = prefix->cf_start_addr +
890bc1f688bSRobert Mustacchi             prefix->cf_length + prefix->cf_local_length_size
891bc1f688bSRobert Mustacchi             + prefix->cf_local_extension_size;
892bc1f688bSRobert Mustacchi         /*  FIX -- What are the values of data_alignment_factor,
893bc1f688bSRobert Mustacchi             code_alignement_factor, return_address_register and
894bc1f688bSRobert Mustacchi             instruction start? They were clearly uninitalized in the
895bc1f688bSRobert Mustacchi             previous version and I am leaving them the same way. */
896bc1f688bSRobert 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;
903*4d9fdb46SRobert Mustacchi         }
904*4d9fdb46SRobert Mustacchi         break;
905bc1f688bSRobert Mustacchi     }                           /* End switch on augmentation type. */
906bc1f688bSRobert Mustacchi 
907bc1f688bSRobert Mustacchi     new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
908bc1f688bSRobert Mustacchi     if (new_cie == NULL) {
909bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
910bc1f688bSRobert Mustacchi         return (DW_DLV_ERROR);
911bc1f688bSRobert Mustacchi     }
912bc1f688bSRobert Mustacchi 
913bc1f688bSRobert Mustacchi     new_cie->ci_cie_version_number = version;
914bc1f688bSRobert Mustacchi     new_cie->ci_initial_table = NULL;
915*4d9fdb46SRobert Mustacchi     new_cie->ci_length = (Dwarf_Unsigned) prefix->cf_length;
916bc1f688bSRobert Mustacchi     new_cie->ci_length_size = prefix->cf_local_length_size;
917bc1f688bSRobert Mustacchi     new_cie->ci_extension_size = prefix->cf_local_extension_size;
918bc1f688bSRobert Mustacchi     new_cie->ci_augmentation = (char *) augmentation;
919bc1f688bSRobert Mustacchi 
920bc1f688bSRobert Mustacchi     new_cie->ci_data_alignment_factor =
921bc1f688bSRobert Mustacchi         (Dwarf_Sbyte) data_alignment_factor;
922bc1f688bSRobert Mustacchi     new_cie->ci_code_alignment_factor =
923bc1f688bSRobert Mustacchi         (Dwarf_Small) code_alignment_factor;
924bc1f688bSRobert Mustacchi     new_cie->ci_return_address_register = return_address_register;
925bc1f688bSRobert Mustacchi     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     }
931bc1f688bSRobert Mustacchi     new_cie->ci_cie_instr_start = frame_ptr;
932bc1f688bSRobert Mustacchi     new_cie->ci_dbg = dbg;
933bc1f688bSRobert Mustacchi     new_cie->ci_augmentation_type = augt;
934bc1f688bSRobert Mustacchi     new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
935bc1f688bSRobert Mustacchi     new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
936bc1f688bSRobert Mustacchi     new_cie->ci_gnu_personality_handler_encoding =
937bc1f688bSRobert Mustacchi         gnu_personality_handler_encoding;
938bc1f688bSRobert Mustacchi     new_cie->ci_gnu_personality_handler_addr =
939bc1f688bSRobert Mustacchi         gnu_personality_handler_addr;
940bc1f688bSRobert Mustacchi     new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
941bc1f688bSRobert Mustacchi     new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
942bc1f688bSRobert Mustacchi 
943bc1f688bSRobert Mustacchi     new_cie->ci_index = cie_count;
944bc1f688bSRobert Mustacchi     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 
953bc1f688bSRobert Mustacchi     /* The Following new in DWARF4 */
954bc1f688bSRobert Mustacchi     new_cie->ci_address_size = address_size;
955bc1f688bSRobert Mustacchi     new_cie->ci_segment_size = segment_size;
956bc1f688bSRobert Mustacchi     validate_length(dbg,new_cie,new_cie->ci_length,
957bc1f688bSRobert Mustacchi         new_cie->ci_length_size, new_cie->ci_extension_size,
958bc1f688bSRobert Mustacchi         new_cie->ci_section_ptr,
959bc1f688bSRobert Mustacchi         new_cie->ci_cie_start,"cie");
960bc1f688bSRobert Mustacchi 
961bc1f688bSRobert Mustacchi     *cie_ptr_out = new_cie;
962bc1f688bSRobert Mustacchi     return DW_DLV_OK;
963bc1f688bSRobert Mustacchi 
964bc1f688bSRobert Mustacchi }
965bc1f688bSRobert Mustacchi 
966bc1f688bSRobert Mustacchi 
967bc1f688bSRobert Mustacchi /*  Internal function, not called by consumer code.
968bc1f688bSRobert Mustacchi     'prefix' has accumulated the info up thru the cie-id
969bc1f688bSRobert 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  */
971bc1f688bSRobert Mustacchi 
972bc1f688bSRobert Mustacchi 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)973bc1f688bSRobert Mustacchi dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
974bc1f688bSRobert Mustacchi     struct cie_fde_prefix_s *prefix,
975bc1f688bSRobert Mustacchi     Dwarf_Small * section_pointer,
976bc1f688bSRobert Mustacchi     Dwarf_Small * frame_ptr,
977*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
978bc1f688bSRobert Mustacchi     int use_gnu_cie_calc,
979bc1f688bSRobert Mustacchi     Dwarf_Cie cie_ptr_in,
980bc1f688bSRobert Mustacchi     Dwarf_Fde * fde_ptr_out,
981bc1f688bSRobert Mustacchi     Dwarf_Error * error)
982bc1f688bSRobert Mustacchi {
983bc1f688bSRobert Mustacchi     Dwarf_Fde new_fde = 0;
984*4d9fdb46SRobert Mustacchi     Dwarf_Cie cieptr = 0;
985bc1f688bSRobert Mustacchi     Dwarf_Small *saved_frame_ptr = 0;
986bc1f688bSRobert Mustacchi 
987bc1f688bSRobert Mustacchi     Dwarf_Small *initloc = frame_ptr;
988bc1f688bSRobert Mustacchi     Dwarf_Signed offset_into_exception_tables
989bc1f688bSRobert Mustacchi         = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
990bc1f688bSRobert Mustacchi     Dwarf_Small *fde_aug_data = 0;
991bc1f688bSRobert Mustacchi     Dwarf_Unsigned fde_aug_data_len = 0;
992bc1f688bSRobert Mustacchi     Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
993bc1f688bSRobert Mustacchi     Dwarf_Addr initial_location = 0;    /* must be min de_pointer_size
994bc1f688bSRobert Mustacchi         bytes in size */
995bc1f688bSRobert Mustacchi     Dwarf_Addr address_range = 0;       /* must be min de_pointer_size
996bc1f688bSRobert 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;
1002bc1f688bSRobert 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     }
1008bc1f688bSRobert Mustacchi 
1009bc1f688bSRobert Mustacchi     if (augt == aug_gcc_eh_z) {
1010bc1f688bSRobert Mustacchi         /*  If z augmentation this is eh_frame, and initial_location and
1011bc1f688bSRobert Mustacchi             address_range in the FDE are read according to the CIE
1012bc1f688bSRobert Mustacchi             augmentation string instructions.  */
1013bc1f688bSRobert Mustacchi 
1014bc1f688bSRobert Mustacchi         {
1015bc1f688bSRobert Mustacchi             Dwarf_Small *fp_updated = 0;
1016bc1f688bSRobert Mustacchi             int res = read_encoded_ptr(dbg,
1017bc1f688bSRobert Mustacchi                 section_pointer,
1018bc1f688bSRobert Mustacchi                 frame_ptr,
1019bc1f688bSRobert Mustacchi                 cieptr-> ci_gnu_fde_begin_encoding,
1020*4d9fdb46SRobert Mustacchi                 section_ptr_end,
1021bc1f688bSRobert Mustacchi                 address_size,
1022bc1f688bSRobert Mustacchi                 &initial_location,
1023*4d9fdb46SRobert Mustacchi                 &fp_updated,error);
1024bc1f688bSRobert Mustacchi             if (res != DW_DLV_OK) {
1025*4d9fdb46SRobert Mustacchi                 return res;
1026bc1f688bSRobert Mustacchi             }
1027bc1f688bSRobert Mustacchi             frame_ptr = fp_updated;
1028bc1f688bSRobert Mustacchi             /*  For the address-range it makes no sense to be
1029bc1f688bSRobert Mustacchi                 pc-relative, so we turn it off with a section_pointer of
1030bc1f688bSRobert Mustacchi                 NULL. Masking off DW_EH_PE_pcrel from the
1031bc1f688bSRobert Mustacchi                 ci_gnu_fde_begin_encoding in this call would also work
1032bc1f688bSRobert Mustacchi                 to turn off DW_EH_PE_pcrel. */
1033bc1f688bSRobert Mustacchi             res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
1034bc1f688bSRobert Mustacchi                 frame_ptr,
1035bc1f688bSRobert Mustacchi                 cieptr->ci_gnu_fde_begin_encoding,
1036*4d9fdb46SRobert Mustacchi                 section_ptr_end,
1037bc1f688bSRobert Mustacchi                 address_size,
1038*4d9fdb46SRobert Mustacchi                 &address_range, &fp_updated,error);
1039bc1f688bSRobert Mustacchi             if (res != DW_DLV_OK) {
1040*4d9fdb46SRobert Mustacchi                 return res;
1041bc1f688bSRobert Mustacchi             }
1042bc1f688bSRobert Mustacchi             frame_ptr = fp_updated;
1043bc1f688bSRobert Mustacchi         }
1044bc1f688bSRobert Mustacchi         {
1045bc1f688bSRobert Mustacchi             Dwarf_Unsigned adlen = 0;
1046bc1f688bSRobert Mustacchi 
1047*4d9fdb46SRobert Mustacchi             DECODE_LEB128_UWORD_CK(frame_ptr, adlen,
1048*4d9fdb46SRobert Mustacchi                 dbg,error,section_ptr_end);
1049bc1f688bSRobert Mustacchi             fde_aug_data_len = adlen;
1050bc1f688bSRobert Mustacchi             fde_aug_data = frame_ptr;
1051bc1f688bSRobert Mustacchi             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             }
1070bc1f688bSRobert Mustacchi         }
1071bc1f688bSRobert Mustacchi 
1072bc1f688bSRobert Mustacchi     } 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);
1080bc1f688bSRobert Mustacchi         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);
1084bc1f688bSRobert Mustacchi         frame_ptr += address_size;
1085bc1f688bSRobert Mustacchi     }
1086bc1f688bSRobert Mustacchi     switch (augt) {
1087bc1f688bSRobert Mustacchi     case aug_irix_mti_v1:
1088bc1f688bSRobert Mustacchi     case aug_empty_string:
1089bc1f688bSRobert Mustacchi         break;
1090bc1f688bSRobert Mustacchi     case aug_irix_exception_table:{
1091bc1f688bSRobert Mustacchi         Dwarf_Unsigned lreg = 0;
1092*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned length_of_augmented_fields = 0;
1093bc1f688bSRobert 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;
1097bc1f688bSRobert Mustacchi 
1098bc1f688bSRobert Mustacchi         saved_frame_ptr = frame_ptr;
1099bc1f688bSRobert Mustacchi         /*  The first word is an offset into exception tables.
1100bc1f688bSRobert 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);
1108bc1f688bSRobert Mustacchi         SIGN_EXTEND(offset_into_exception_tables,
1109*4d9fdb46SRobert Mustacchi             DWARF_32BIT_SIZE);
1110bc1f688bSRobert Mustacchi         frame_ptr = saved_frame_ptr + length_of_augmented_fields;
1111bc1f688bSRobert Mustacchi         }
1112bc1f688bSRobert Mustacchi         break;
1113bc1f688bSRobert Mustacchi     case aug_eh:{
1114bc1f688bSRobert Mustacchi 
1115bc1f688bSRobert Mustacchi         if (!use_gnu_cie_calc) {
1116bc1f688bSRobert Mustacchi             /* This should be impossible. */
1117*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error,DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1118bc1f688bSRobert Mustacchi             return DW_DLV_ERROR;
1119bc1f688bSRobert Mustacchi         }
1120bc1f688bSRobert Mustacchi 
1121bc1f688bSRobert 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,
1128bc1f688bSRobert 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;
1132bc1f688bSRobert Mustacchi         frame_ptr += address_size;
1133bc1f688bSRobert Mustacchi         }
1134bc1f688bSRobert Mustacchi         break;
1135bc1f688bSRobert Mustacchi 
1136bc1f688bSRobert Mustacchi     case aug_gcc_eh_z:{
1137bc1f688bSRobert Mustacchi         /*  The Augmentation Data Length is here, followed by the
1138bc1f688bSRobert Mustacchi             Augmentation Data bytes themselves. */
1139bc1f688bSRobert Mustacchi         }
1140bc1f688bSRobert Mustacchi         break;
1141bc1f688bSRobert Mustacchi     case aug_armcc:
1142bc1f688bSRobert Mustacchi         break;
1143bc1f688bSRobert Mustacchi     case aug_past_last:
1144bc1f688bSRobert Mustacchi         break;
1145*4d9fdb46SRobert Mustacchi 
1146*4d9fdb46SRobert Mustacchi     case aug_metaware: /* No special fields. See dwarf_util.h */
1147*4d9fdb46SRobert Mustacchi         break;
1148*4d9fdb46SRobert Mustacchi 
1149bc1f688bSRobert Mustacchi     case aug_unknown:
1150bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1151bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
1152bc1f688bSRobert Mustacchi     }                           /* 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 
1158bc1f688bSRobert Mustacchi     new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
1159bc1f688bSRobert Mustacchi     if (new_fde == NULL) {
1160bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
1161bc1f688bSRobert Mustacchi         return (DW_DLV_ERROR);
1162bc1f688bSRobert Mustacchi     }
1163bc1f688bSRobert Mustacchi 
1164bc1f688bSRobert Mustacchi     new_fde->fd_length = prefix->cf_length;
1165bc1f688bSRobert Mustacchi     new_fde->fd_length_size = prefix->cf_local_length_size;
1166bc1f688bSRobert Mustacchi     new_fde->fd_extension_size = prefix->cf_local_extension_size;
1167bc1f688bSRobert Mustacchi     new_fde->fd_is_eh = use_gnu_cie_calc;
1168bc1f688bSRobert Mustacchi     new_fde->fd_cie_offset = cie_base_offset;
1169*4d9fdb46SRobert Mustacchi     if (cieptr) {
1170bc1f688bSRobert Mustacchi         new_fde->fd_cie_index = cieptr->ci_index;
1171*4d9fdb46SRobert Mustacchi     }
1172bc1f688bSRobert Mustacchi     new_fde->fd_cie = cieptr;
1173bc1f688bSRobert Mustacchi     new_fde->fd_initial_location = initial_location;
1174bc1f688bSRobert Mustacchi     new_fde->fd_initial_loc_pos = initloc;
1175bc1f688bSRobert Mustacchi     new_fde->fd_address_range = address_range;
1176bc1f688bSRobert Mustacchi     new_fde->fd_fde_start = prefix->cf_start_addr;
1177*4d9fdb46SRobert Mustacchi 
1178bc1f688bSRobert Mustacchi     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 
1187bc1f688bSRobert Mustacchi     new_fde->fd_dbg = dbg;
1188bc1f688bSRobert Mustacchi     new_fde->fd_offset_into_exception_tables =
1189bc1f688bSRobert Mustacchi         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;
1192bc1f688bSRobert Mustacchi 
1193bc1f688bSRobert Mustacchi     new_fde->fd_section_ptr = prefix->cf_section_ptr;
1194bc1f688bSRobert Mustacchi     new_fde->fd_section_index = prefix->cf_section_index;
1195bc1f688bSRobert Mustacchi     new_fde->fd_section_length = prefix->cf_section_length;
1196*4d9fdb46SRobert Mustacchi     new_fde->fd_section_end = section_ptr_end;
1197bc1f688bSRobert Mustacchi 
1198*4d9fdb46SRobert Mustacchi     if (augt == aug_gcc_eh_z) {
1199*4d9fdb46SRobert Mustacchi         new_fde->fd_gnu_eh_aug_present = TRUE;
1200*4d9fdb46SRobert Mustacchi     }
1201bc1f688bSRobert Mustacchi     new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
1202bc1f688bSRobert Mustacchi     new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
1203bc1f688bSRobert Mustacchi     validate_length(dbg,cieptr,new_fde->fd_length,
1204bc1f688bSRobert Mustacchi         new_fde->fd_length_size, new_fde->fd_extension_size,
1205bc1f688bSRobert Mustacchi         new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
1206bc1f688bSRobert Mustacchi     *fde_ptr_out = new_fde;
1207bc1f688bSRobert Mustacchi     return DW_DLV_OK;
1208bc1f688bSRobert Mustacchi }
1209bc1f688bSRobert Mustacchi 
1210bc1f688bSRobert Mustacchi /*  Read in the common cie/fde prefix, including reading
1211*4d9fdb46SRobert Mustacchi     the cie-value which shows which this is: cie or fde.  */
1212bc1f688bSRobert Mustacchi 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)1213bc1f688bSRobert Mustacchi dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
1214bc1f688bSRobert Mustacchi     Dwarf_Small * frame_ptr_in,
1215bc1f688bSRobert Mustacchi     Dwarf_Small * section_ptr_in,
1216bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_index_in,
1217bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_length_in,
1218bc1f688bSRobert Mustacchi     struct cie_fde_prefix_s *data_out,
1219bc1f688bSRobert Mustacchi     Dwarf_Error * error)
1220bc1f688bSRobert Mustacchi {
1221bc1f688bSRobert Mustacchi     Dwarf_Unsigned length = 0;
1222bc1f688bSRobert Mustacchi     int local_length_size = 0;
1223bc1f688bSRobert Mustacchi     int local_extension_size = 0;
1224bc1f688bSRobert Mustacchi     Dwarf_Small *frame_ptr = frame_ptr_in;
1225bc1f688bSRobert Mustacchi     Dwarf_Small *cie_ptr_addr = 0;
1226bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_id = 0;
1227*4d9fdb46SRobert Mustacchi     Dwarf_Small *section_end = section_ptr_in + section_length_in;
1228bc1f688bSRobert 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     }
1245bc1f688bSRobert Mustacchi     /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
1246*4d9fdb46SRobert Mustacchi     READ_AREA_LENGTH_CK(dbg, length, Dwarf_Unsigned,
1247bc1f688bSRobert Mustacchi         frame_ptr, local_length_size,
1248*4d9fdb46SRobert Mustacchi         local_extension_size,error,
1249*4d9fdb46SRobert Mustacchi         section_length_in,section_end);
1250bc1f688bSRobert Mustacchi 
1251bc1f688bSRobert Mustacchi     if (length == 0) {
1252bc1f688bSRobert Mustacchi         /*  nul bytes at end of section, seen at end of egcs eh_frame
1253bc1f688bSRobert Mustacchi             sections (in a.out). Take this as meaning no more CIE/FDE
1254bc1f688bSRobert Mustacchi             data. We should be very close to end of section. */
1255bc1f688bSRobert Mustacchi         return DW_DLV_NO_ENTRY;
1256bc1f688bSRobert Mustacchi     }
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     }
1261bc1f688bSRobert Mustacchi 
1262bc1f688bSRobert Mustacchi     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);
1265bc1f688bSRobert Mustacchi     SIGN_EXTEND(cie_id, local_length_size);
1266bc1f688bSRobert Mustacchi     frame_ptr += local_length_size;
1267bc1f688bSRobert Mustacchi 
1268bc1f688bSRobert Mustacchi     data_out->cf_start_addr = frame_ptr_in;
1269bc1f688bSRobert Mustacchi     data_out->cf_addr_after_prefix = frame_ptr;
1270bc1f688bSRobert Mustacchi 
1271bc1f688bSRobert Mustacchi     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     }
1280bc1f688bSRobert Mustacchi     data_out->cf_local_length_size = local_length_size;
1281bc1f688bSRobert Mustacchi     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. */
1287bc1f688bSRobert Mustacchi     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.  */
1290bc1f688bSRobert Mustacchi     data_out->cf_cie_id_addr = cie_ptr_addr;
1291*4d9fdb46SRobert Mustacchi 
1292bc1f688bSRobert Mustacchi     data_out->cf_section_ptr = section_ptr_in;
1293bc1f688bSRobert Mustacchi     data_out->cf_section_index = section_index_in;
1294bc1f688bSRobert Mustacchi     data_out->cf_section_length = section_length_in;
1295bc1f688bSRobert Mustacchi     return DW_DLV_OK;
1296bc1f688bSRobert Mustacchi }
1297bc1f688bSRobert Mustacchi 
1298bc1f688bSRobert Mustacchi /*  On various errors previously-allocated CIEs and FDEs
1299bc1f688bSRobert Mustacchi     must be cleaned up.
1300bc1f688bSRobert Mustacchi     This helps avoid leaks in case of errors.
1301bc1f688bSRobert Mustacchi */
1302bc1f688bSRobert Mustacchi static void
dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,Dwarf_Cie head_cie_ptr)1303bc1f688bSRobert Mustacchi dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
1304bc1f688bSRobert Mustacchi     Dwarf_Cie head_cie_ptr)
1305bc1f688bSRobert Mustacchi {
1306bc1f688bSRobert Mustacchi     Dwarf_Fde curfde = 0;
1307bc1f688bSRobert Mustacchi     Dwarf_Cie curcie = 0;
1308bc1f688bSRobert Mustacchi     Dwarf_Fde nextfde = 0;
1309bc1f688bSRobert Mustacchi     Dwarf_Cie nextcie = 0;
1310bc1f688bSRobert Mustacchi 
1311bc1f688bSRobert Mustacchi     for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
1312bc1f688bSRobert Mustacchi         nextfde = curfde->fd_next;
1313bc1f688bSRobert Mustacchi         dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
1314bc1f688bSRobert Mustacchi     }
1315bc1f688bSRobert Mustacchi     for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
1316bc1f688bSRobert Mustacchi         Dwarf_Frame frame = curcie->ci_initial_table;
1317bc1f688bSRobert Mustacchi 
1318bc1f688bSRobert Mustacchi         nextcie = curcie->ci_next;
1319bc1f688bSRobert Mustacchi         if (frame)
1320bc1f688bSRobert Mustacchi             dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
1321bc1f688bSRobert Mustacchi         dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
1322bc1f688bSRobert Mustacchi     }
1323bc1f688bSRobert Mustacchi }
1324bc1f688bSRobert Mustacchi 
1325bc1f688bSRobert 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. */
1330bc1f688bSRobert Mustacchi 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)1331bc1f688bSRobert Mustacchi dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
1332bc1f688bSRobert Mustacchi     Dwarf_Cie cur_cie_ptr,
1333bc1f688bSRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
1334bc1f688bSRobert Mustacchi     Dwarf_Cie head_cie_ptr)
1335bc1f688bSRobert Mustacchi {
1336bc1f688bSRobert Mustacchi     Dwarf_Cie next = 0;
1337bc1f688bSRobert Mustacchi 
1338bc1f688bSRobert Mustacchi     if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
1339bc1f688bSRobert Mustacchi         /* Usually, we use the same cie again and again. */
1340bc1f688bSRobert Mustacchi         *cie_ptr_to_use_out = cur_cie_ptr;
1341bc1f688bSRobert Mustacchi         return DW_DLV_OK;
1342bc1f688bSRobert Mustacchi     }
1343bc1f688bSRobert Mustacchi     for (next = head_cie_ptr; next; next = next->ci_next) {
1344bc1f688bSRobert Mustacchi         if (cie_ptr == next->ci_cie_start) {
1345bc1f688bSRobert Mustacchi             *cie_ptr_to_use_out = next;
1346bc1f688bSRobert Mustacchi             return DW_DLV_OK;
1347bc1f688bSRobert Mustacchi         }
1348bc1f688bSRobert Mustacchi     }
1349bc1f688bSRobert Mustacchi     return DW_DLV_NO_ENTRY;
1350bc1f688bSRobert Mustacchi }
1351bc1f688bSRobert Mustacchi 
1352bc1f688bSRobert Mustacchi 
1353bc1f688bSRobert 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.
1357bc1f688bSRobert Mustacchi 
1358bc1f688bSRobert Mustacchi     'section_ptr'    - Points to first byte of section data.
1359bc1f688bSRobert Mustacchi     'section_length' - Length of the section, in bytes.
1360*4d9fdb46SRobert Mustacchi     'section_ptr_end'  - Points 1-past last byte of section data.  */
1361bc1f688bSRobert Mustacchi 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)1362bc1f688bSRobert Mustacchi dwarf_create_cie_from_start(Dwarf_Debug dbg,
1363bc1f688bSRobert Mustacchi     Dwarf_Small * cie_ptr_val,
1364bc1f688bSRobert Mustacchi     Dwarf_Small * section_ptr,
1365bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_index,
1366bc1f688bSRobert Mustacchi     Dwarf_Unsigned section_length,
1367*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
1368bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_id_value,
1369bc1f688bSRobert Mustacchi     Dwarf_Unsigned cie_count,
1370bc1f688bSRobert Mustacchi     int use_gnu_cie_calc,
1371bc1f688bSRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
1372bc1f688bSRobert Mustacchi     Dwarf_Error * error)
1373bc1f688bSRobert Mustacchi {
1374bc1f688bSRobert Mustacchi     struct cie_fde_prefix_s prefix;
1375bc1f688bSRobert Mustacchi     int res = DW_DLV_ERROR;
1376bc1f688bSRobert Mustacchi     Dwarf_Small *frame_ptr = cie_ptr_val;
1377bc1f688bSRobert Mustacchi 
1378*4d9fdb46SRobert Mustacchi     if (frame_ptr < section_ptr || frame_ptr >= section_ptr_end) {
1379bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1380bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
1381bc1f688bSRobert Mustacchi     }
1382bc1f688bSRobert Mustacchi     /*  First read in the 'common prefix' to figure out what * we are to
1383bc1f688bSRobert Mustacchi         do with this entry. If it is not a cie * we are in big trouble. */
1384bc1f688bSRobert Mustacchi     memset(&prefix, 0, sizeof(prefix));
1385bc1f688bSRobert Mustacchi     res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
1386bc1f688bSRobert Mustacchi         section_index, section_length,
1387bc1f688bSRobert Mustacchi         &prefix, error);
1388bc1f688bSRobert Mustacchi     if (res == DW_DLV_ERROR) {
1389bc1f688bSRobert Mustacchi         return res;
1390bc1f688bSRobert Mustacchi     }
1391bc1f688bSRobert Mustacchi     if (res == DW_DLV_NO_ENTRY) {
1392bc1f688bSRobert Mustacchi         /* error. */
1393bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
1394bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
1395bc1f688bSRobert Mustacchi 
1396bc1f688bSRobert Mustacchi     }
1397bc1f688bSRobert Mustacchi 
1398bc1f688bSRobert Mustacchi     if (prefix.cf_cie_id != cie_id_value) {
1399bc1f688bSRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
1400bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
1401bc1f688bSRobert Mustacchi     }
1402bc1f688bSRobert Mustacchi     frame_ptr = prefix.cf_addr_after_prefix;
1403bc1f688bSRobert Mustacchi     res = dwarf_create_cie_from_after_start(dbg,
1404bc1f688bSRobert Mustacchi         &prefix,
1405bc1f688bSRobert Mustacchi         section_ptr,
1406bc1f688bSRobert Mustacchi         frame_ptr,
1407*4d9fdb46SRobert Mustacchi         section_ptr_end,
1408bc1f688bSRobert Mustacchi         cie_count,
1409bc1f688bSRobert Mustacchi         use_gnu_cie_calc,
1410bc1f688bSRobert Mustacchi         cie_ptr_to_use_out, error);
1411bc1f688bSRobert Mustacchi     return res;
1412bc1f688bSRobert Mustacchi 
1413bc1f688bSRobert Mustacchi }
1414bc1f688bSRobert Mustacchi 
1415bc1f688bSRobert Mustacchi 
1416bc1f688bSRobert Mustacchi /* This is for gnu eh frames, the 'z' case.
1417bc1f688bSRobert Mustacchi    We find the letter involved
1418bc1f688bSRobert Mustacchi    Return the augmentation character and, if applicable,
1419bc1f688bSRobert Mustacchi    the personality routine address.
1420bc1f688bSRobert Mustacchi 
1421bc1f688bSRobert Mustacchi    personality_routine_out -
1422bc1f688bSRobert Mustacchi         if 'P' is augchar, is personality handler addr.
1423bc1f688bSRobert Mustacchi         Otherwise is not set.
1424bc1f688bSRobert Mustacchi    aug_data  - if 'P' points  to data space of the
1425bc1f688bSRobert Mustacchi    aug_data_len - length of areas aug_data points to.
1426bc1f688bSRobert Mustacchi 
1427bc1f688bSRobert Mustacchi */
1428bc1f688bSRobert Mustacchi 
1429*4d9fdb46SRobert Mustacchi /*  It is not clear if this is entirely correct. */
1430bc1f688bSRobert Mustacchi 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)1431bc1f688bSRobert Mustacchi gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
1432bc1f688bSRobert Mustacchi     Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
1433bc1f688bSRobert Mustacchi     Dwarf_Half address_size,
1434bc1f688bSRobert Mustacchi     unsigned char *pers_hand_enc_out,
1435bc1f688bSRobert Mustacchi     unsigned char *lsda_enc_out,
1436bc1f688bSRobert Mustacchi     unsigned char *fde_begin_enc_out,
1437*4d9fdb46SRobert Mustacchi     Dwarf_Addr * gnu_pers_addr_out,
1438*4d9fdb46SRobert Mustacchi     Dwarf_Error * error)
1439bc1f688bSRobert Mustacchi {
1440bc1f688bSRobert Mustacchi     char *nc = 0;
1441bc1f688bSRobert Mustacchi     Dwarf_Small *cur_aug_p = aug_data;
1442bc1f688bSRobert Mustacchi     Dwarf_Small *end_aug_p = aug_data + aug_data_len;
1443bc1f688bSRobert Mustacchi 
1444bc1f688bSRobert Mustacchi     for (nc = augmentation; *nc; ++nc) {
1445bc1f688bSRobert Mustacchi         char c = *nc;
1446bc1f688bSRobert Mustacchi 
1447bc1f688bSRobert Mustacchi         switch (c) {
1448bc1f688bSRobert Mustacchi         case 'z':
1449bc1f688bSRobert Mustacchi             /* Means that the augmentation data is present. */
1450bc1f688bSRobert Mustacchi             continue;
1451bc1f688bSRobert Mustacchi 
1452bc1f688bSRobert Mustacchi         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
1458bc1f688bSRobert Mustacchi                 string).
1459bc1f688bSRobert 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
1466bc1f688bSRobert Mustacchi                 onto the stack and loading registers from that structure.
1467bc1f688bSRobert 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).
1473bc1f688bSRobert Mustacchi             */
1474bc1f688bSRobert Mustacchi             break;
1475bc1f688bSRobert Mustacchi 
1476bc1f688bSRobert Mustacchi         case 'L':
1477bc1f688bSRobert Mustacchi             if (cur_aug_p > end_aug_p) {
1478*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1479bc1f688bSRobert Mustacchi                 return DW_DLV_ERROR;
1480bc1f688bSRobert Mustacchi             }
1481bc1f688bSRobert Mustacchi             *lsda_enc_out = *(unsigned char *) cur_aug_p;
1482bc1f688bSRobert Mustacchi             ++cur_aug_p;
1483bc1f688bSRobert Mustacchi             break;
1484bc1f688bSRobert Mustacchi         case 'R':
1485bc1f688bSRobert Mustacchi             /*  Followed by a one byte argument giving the
1486bc1f688bSRobert Mustacchi                 pointer encoding for the address pointers in the fde. */
1487bc1f688bSRobert Mustacchi             if (cur_aug_p >= end_aug_p) {
1488*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1489bc1f688bSRobert Mustacchi                 return DW_DLV_ERROR;
1490bc1f688bSRobert Mustacchi             }
1491bc1f688bSRobert Mustacchi             *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
1492bc1f688bSRobert Mustacchi             ++cur_aug_p;
1493bc1f688bSRobert Mustacchi             break;
1494bc1f688bSRobert Mustacchi         case 'P':{
1495bc1f688bSRobert Mustacchi             int res = DW_DLV_ERROR;
1496bc1f688bSRobert Mustacchi             Dwarf_Small *updated_aug_p = 0;
1497bc1f688bSRobert Mustacchi             unsigned char encoding = 0;
1498bc1f688bSRobert Mustacchi 
1499bc1f688bSRobert Mustacchi             if (cur_aug_p >= end_aug_p) {
1500*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1501bc1f688bSRobert Mustacchi                 return DW_DLV_ERROR;
1502bc1f688bSRobert Mustacchi             }
1503bc1f688bSRobert Mustacchi             encoding = *(unsigned char *) cur_aug_p;
1504bc1f688bSRobert Mustacchi             *pers_hand_enc_out = encoding;
1505bc1f688bSRobert Mustacchi             ++cur_aug_p;
1506bc1f688bSRobert Mustacchi             if (cur_aug_p > end_aug_p) {
1507*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1508bc1f688bSRobert Mustacchi                 return DW_DLV_ERROR;
1509bc1f688bSRobert Mustacchi             }
1510bc1f688bSRobert Mustacchi             /*  DW_EH_PE_pcrel makes no sense here, so we turn it
1511bc1f688bSRobert Mustacchi                 off via a section pointer of NULL. */
1512bc1f688bSRobert Mustacchi             res = read_encoded_ptr(dbg,
1513bc1f688bSRobert Mustacchi                 (Dwarf_Small *) NULL,
1514bc1f688bSRobert Mustacchi                 cur_aug_p,
1515bc1f688bSRobert Mustacchi                 encoding,
1516*4d9fdb46SRobert Mustacchi                 end_aug_p,
1517bc1f688bSRobert Mustacchi                 address_size,
1518bc1f688bSRobert Mustacchi                 gnu_pers_addr_out,
1519*4d9fdb46SRobert Mustacchi                 &updated_aug_p,
1520*4d9fdb46SRobert Mustacchi                 error);
1521bc1f688bSRobert Mustacchi             if (res != DW_DLV_OK) {
1522bc1f688bSRobert Mustacchi                 return res;
1523bc1f688bSRobert Mustacchi             }
1524bc1f688bSRobert Mustacchi             cur_aug_p = updated_aug_p;
1525bc1f688bSRobert Mustacchi             if (cur_aug_p > end_aug_p) {
1526*4d9fdb46SRobert Mustacchi                 _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1527bc1f688bSRobert Mustacchi                 return DW_DLV_ERROR;
1528bc1f688bSRobert Mustacchi             }
1529bc1f688bSRobert Mustacchi             }
1530bc1f688bSRobert Mustacchi             break;
1531bc1f688bSRobert Mustacchi         default:
1532*4d9fdb46SRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1533bc1f688bSRobert Mustacchi             return DW_DLV_ERROR;
1534bc1f688bSRobert Mustacchi 
1535bc1f688bSRobert Mustacchi         }
1536bc1f688bSRobert Mustacchi     }
1537bc1f688bSRobert Mustacchi     return DW_DLV_OK;
1538bc1f688bSRobert Mustacchi }
1539bc1f688bSRobert Mustacchi 
1540bc1f688bSRobert Mustacchi /*  Given augmentation character (the encoding) giving the
1541bc1f688bSRobert Mustacchi     address format, read the address from input_field
1542bc1f688bSRobert Mustacchi     and return an incremented value 1 past the input bytes of the
1543bc1f688bSRobert Mustacchi     address.
1544bc1f688bSRobert Mustacchi     Push the address read back thru the *addr pointer.
1545*4d9fdb46SRobert Mustacchi     See LSB (Linux Standard Base)  exception handling documents.  */
1546bc1f688bSRobert Mustacchi 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)1547bc1f688bSRobert Mustacchi read_encoded_ptr(Dwarf_Debug dbg,
1548bc1f688bSRobert Mustacchi     Dwarf_Small * section_pointer,
1549bc1f688bSRobert Mustacchi     Dwarf_Small * input_field,
1550bc1f688bSRobert Mustacchi     int gnu_encoding,
1551*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_end,
1552bc1f688bSRobert Mustacchi     Dwarf_Half address_size,
1553bc1f688bSRobert Mustacchi     Dwarf_Unsigned * addr,
1554*4d9fdb46SRobert Mustacchi     Dwarf_Small ** input_field_updated,
1555*4d9fdb46SRobert Mustacchi     Dwarf_Error *error)
1556bc1f688bSRobert Mustacchi {
1557bc1f688bSRobert Mustacchi     int value_type = gnu_encoding & 0xf;
1558bc1f688bSRobert Mustacchi     Dwarf_Small *input_field_original = input_field;
1559bc1f688bSRobert Mustacchi 
1560bc1f688bSRobert Mustacchi     if (gnu_encoding == 0xff) {
1561bc1f688bSRobert Mustacchi         /* There is no data here. */
1562bc1f688bSRobert Mustacchi 
1563bc1f688bSRobert Mustacchi         *addr = 0;
1564bc1f688bSRobert Mustacchi         *input_field_updated = input_field;
1565bc1f688bSRobert Mustacchi         /* Should we return DW_DLV_NO_ENTRY? */
1566bc1f688bSRobert Mustacchi         return DW_DLV_OK;
1567bc1f688bSRobert Mustacchi     }
1568bc1f688bSRobert Mustacchi     switch (value_type) {
1569bc1f688bSRobert Mustacchi     case DW_EH_PE_absptr:{
1570bc1f688bSRobert Mustacchi         /* value_type is zero. Treat as pointer size of the object.
1571bc1f688bSRobert Mustacchi         */
1572bc1f688bSRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
1573bc1f688bSRobert Mustacchi 
1574*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1575*4d9fdb46SRobert Mustacchi             input_field, address_size,error,section_end);
1576bc1f688bSRobert Mustacchi         *addr = ret_value;
1577bc1f688bSRobert Mustacchi         *input_field_updated = input_field + address_size;
1578bc1f688bSRobert Mustacchi         }
1579bc1f688bSRobert Mustacchi         break;
1580bc1f688bSRobert Mustacchi     case DW_EH_PE_uleb128:{
1581*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned val = 0;
1582bc1f688bSRobert Mustacchi 
1583*4d9fdb46SRobert Mustacchi         DECODE_LEB128_UWORD_CK(input_field,val,dbg,error,section_end);
1584bc1f688bSRobert Mustacchi         *addr = val;
1585*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field;
1586bc1f688bSRobert Mustacchi         }
1587bc1f688bSRobert Mustacchi         break;
1588bc1f688bSRobert Mustacchi     case DW_EH_PE_udata2:{
1589bc1f688bSRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
1590bc1f688bSRobert Mustacchi 
1591*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1592*4d9fdb46SRobert Mustacchi             input_field, 2,error,section_end);
1593bc1f688bSRobert Mustacchi         *addr = ret_value;
1594bc1f688bSRobert Mustacchi         *input_field_updated = input_field + 2;
1595bc1f688bSRobert Mustacchi         }
1596bc1f688bSRobert Mustacchi         break;
1597bc1f688bSRobert Mustacchi 
1598bc1f688bSRobert Mustacchi     case DW_EH_PE_udata4:{
1599bc1f688bSRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
1600bc1f688bSRobert Mustacchi 
1601*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, ret_value, Dwarf_Unsigned,
1602*4d9fdb46SRobert Mustacchi             input_field, DWARF_32BIT_SIZE,error,section_end);
1603bc1f688bSRobert Mustacchi         *addr = ret_value;
1604*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + DWARF_32BIT_SIZE;
1605bc1f688bSRobert Mustacchi         }
1606bc1f688bSRobert Mustacchi         break;
1607bc1f688bSRobert Mustacchi 
1608bc1f688bSRobert Mustacchi     case DW_EH_PE_udata8:{
1609bc1f688bSRobert Mustacchi         Dwarf_Unsigned ret_value = 0;
1610bc1f688bSRobert Mustacchi 
1611bc1f688bSRobert 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);
1614bc1f688bSRobert Mustacchi         *addr = ret_value;
1615*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field +  DWARF_64BIT_SIZE;
1616bc1f688bSRobert Mustacchi         }
1617bc1f688bSRobert Mustacchi         break;
1618bc1f688bSRobert Mustacchi 
1619bc1f688bSRobert Mustacchi     case DW_EH_PE_sleb128:{
1620*4d9fdb46SRobert Mustacchi         Dwarf_Signed val = 0;
1621bc1f688bSRobert Mustacchi 
1622*4d9fdb46SRobert Mustacchi         DECODE_LEB128_SWORD_CK(input_field,val,dbg,error,section_end);
1623bc1f688bSRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1624*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field;
1625bc1f688bSRobert Mustacchi         }
1626bc1f688bSRobert Mustacchi         break;
1627bc1f688bSRobert Mustacchi     case DW_EH_PE_sdata2:{
1628bc1f688bSRobert Mustacchi         Dwarf_Unsigned val = 0;
1629bc1f688bSRobert Mustacchi 
1630*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, val, Dwarf_Unsigned, input_field, 2,
1631*4d9fdb46SRobert Mustacchi             error,section_end);
1632bc1f688bSRobert Mustacchi         SIGN_EXTEND(val, 2);
1633bc1f688bSRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1634bc1f688bSRobert Mustacchi         *input_field_updated = input_field + 2;
1635bc1f688bSRobert Mustacchi         }
1636bc1f688bSRobert Mustacchi         break;
1637bc1f688bSRobert Mustacchi 
1638bc1f688bSRobert Mustacchi     case DW_EH_PE_sdata4:{
1639bc1f688bSRobert Mustacchi         Dwarf_Unsigned val = 0;
1640bc1f688bSRobert Mustacchi 
1641*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, val,
1642bc1f688bSRobert Mustacchi             Dwarf_Unsigned, input_field,
1643*4d9fdb46SRobert Mustacchi             DWARF_32BIT_SIZE,error,section_end);
1644*4d9fdb46SRobert Mustacchi         SIGN_EXTEND(val, DWARF_32BIT_SIZE);
1645bc1f688bSRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1646*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + DWARF_32BIT_SIZE;
1647bc1f688bSRobert Mustacchi         }
1648bc1f688bSRobert Mustacchi         break;
1649bc1f688bSRobert Mustacchi     case DW_EH_PE_sdata8:{
1650bc1f688bSRobert Mustacchi         Dwarf_Unsigned val = 0;
1651bc1f688bSRobert Mustacchi 
1652bc1f688bSRobert Mustacchi         /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
1653*4d9fdb46SRobert Mustacchi         READ_UNALIGNED_CK(dbg, val,
1654bc1f688bSRobert Mustacchi             Dwarf_Unsigned, input_field,
1655*4d9fdb46SRobert Mustacchi             DWARF_64BIT_SIZE,error,section_end);
1656bc1f688bSRobert Mustacchi         *addr = (Dwarf_Unsigned) val;
1657*4d9fdb46SRobert Mustacchi         *input_field_updated = input_field + DWARF_64BIT_SIZE;
1658bc1f688bSRobert Mustacchi         }
1659bc1f688bSRobert Mustacchi         break;
1660bc1f688bSRobert Mustacchi     default:
1661*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1662bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
1663bc1f688bSRobert Mustacchi 
1664bc1f688bSRobert Mustacchi     };
1665bc1f688bSRobert Mustacchi     /*  The ELF ABI for gnu does not document the meaning of
1666bc1f688bSRobert Mustacchi         DW_EH_PE_pcrel, which is awkward.  It apparently means the value
1667bc1f688bSRobert Mustacchi         we got above is pc-relative (meaning section-relative), so we
1668bc1f688bSRobert Mustacchi         adjust the value. Section_pointer may be null if it is known
1669bc1f688bSRobert Mustacchi         DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an
1670bc1f688bSRobert Mustacchi         address-range value. */
1671bc1f688bSRobert Mustacchi     if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
1672bc1f688bSRobert Mustacchi         /*  Address (*addr) above is pc relative with respect to a
1673bc1f688bSRobert Mustacchi             section. Add to the offset the base address (from elf) of
1674bc1f688bSRobert Mustacchi             section and the distance of the field we are reading from
1675bc1f688bSRobert Mustacchi             the section-beginning to get the actual address. */
1676bc1f688bSRobert Mustacchi         /*  ASSERT: input_field_original >= section_pointer */
1677bc1f688bSRobert Mustacchi         Dwarf_Unsigned distance =
1678bc1f688bSRobert Mustacchi             input_field_original - section_pointer;
1679bc1f688bSRobert Mustacchi         *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
1680bc1f688bSRobert Mustacchi     }
1681bc1f688bSRobert Mustacchi     return DW_DLV_OK;
1682bc1f688bSRobert Mustacchi }
1683bc1f688bSRobert Mustacchi 
1684*4d9fdb46SRobert Mustacchi /*  All augmentation string checking done here now.
1685bc1f688bSRobert Mustacchi 
1686bc1f688bSRobert Mustacchi     For .eh_frame, gcc from 3.3 uses the z style, earlier used
1687bc1f688bSRobert Mustacchi     only "eh" as augmentation.  We don't yet handle
1688bc1f688bSRobert Mustacchi     decoding .eh_frame with the z style extensions like L P.
1689*4d9fdb46SRobert Mustacchi     gnu_aug_encodings() does handle L P.
1690bc1f688bSRobert Mustacchi 
1691bc1f688bSRobert Mustacchi     These are nasty heuristics, but then that's life
1692*4d9fdb46SRobert Mustacchi     as augmentations are implementation specific.  */
1693bc1f688bSRobert Mustacchi /* ARGSUSED */
1694bc1f688bSRobert Mustacchi 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,
1696bc1f688bSRobert Mustacchi     Dwarf_Small * augmentation_string,
1697bc1f688bSRobert Mustacchi     int is_gcc_eh_frame)
1698bc1f688bSRobert Mustacchi {
1699bc1f688bSRobert Mustacchi     enum Dwarf_augmentation_type t = aug_unknown;
1700bc1f688bSRobert Mustacchi     char *ag_string = (char *) augmentation_string;
1701bc1f688bSRobert Mustacchi 
1702bc1f688bSRobert Mustacchi     if (ag_string[0] == 0) {
1703bc1f688bSRobert Mustacchi         /*  Empty string. We'll just guess that we know what this means:
1704bc1f688bSRobert Mustacchi             standard dwarf2/3 with no implementation-defined fields.  */
1705bc1f688bSRobert Mustacchi         t = aug_empty_string;
1706bc1f688bSRobert Mustacchi     } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
1707bc1f688bSRobert Mustacchi         /*  The string is "mti v1". Used internally at SGI, probably
1708bc1f688bSRobert Mustacchi             never shipped. Replaced by "z". Treat like 'nothing
1709bc1f688bSRobert Mustacchi             special'.  */
1710bc1f688bSRobert Mustacchi         t = aug_irix_mti_v1;
1711bc1f688bSRobert Mustacchi     } else if (ag_string[0] == 'z') {
1712bc1f688bSRobert Mustacchi         /*  If it's IRIX cc, z means aug_irix_exception_table. z1 z2
1713bc1f688bSRobert Mustacchi             were designed as for IRIX CC, but never implemented */
1714bc1f688bSRobert Mustacchi         /*  If it's gcc, z may be any of several things. "z" or z
1715bc1f688bSRobert Mustacchi             followed optionally followed by one or more of L R P, each
1716bc1f688bSRobert Mustacchi             of which means a value may be present. Should be in eh_frame
1717bc1f688bSRobert Mustacchi             only, I think. */
1718bc1f688bSRobert Mustacchi         if (is_gcc_eh_frame) {
1719bc1f688bSRobert Mustacchi             t = aug_gcc_eh_z;
1720bc1f688bSRobert Mustacchi         } else if (ag_string[1] == 0) {
1721bc1f688bSRobert Mustacchi             /*  This is the normal IRIX C++ case, where there is an
1722bc1f688bSRobert Mustacchi                 offset into a table in each fde. The table being for
1723bc1f688bSRobert Mustacchi                 IRIX CC exception handling.  */
1724bc1f688bSRobert Mustacchi             /*  DW_CIE_AUGMENTER_STRING_V0 "z" */
1725bc1f688bSRobert Mustacchi             t = aug_irix_exception_table;
1726bc1f688bSRobert Mustacchi         }                       /* Else unknown. */
1727bc1f688bSRobert Mustacchi     } else if (strncmp(ag_string, "eh", 2) == 0) {
1728bc1f688bSRobert Mustacchi         /*  gcc .eh_frame augmentation for egcs and gcc 2.x, at least
1729bc1f688bSRobert Mustacchi             for x86. */
1730bc1f688bSRobert Mustacchi         t = aug_eh;
1731bc1f688bSRobert Mustacchi     } else if (strcmp(ag_string, "armcc+") == 0) {
1732bc1f688bSRobert Mustacchi         /*  Arm  uses this string to mean a bug in
1733bc1f688bSRobert Mustacchi             in Arm compilers was fixed, changing to the standard
1734bc1f688bSRobert Mustacchi             calculation of the CFA.  See
1735bc1f688bSRobert Mustacchi             http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
1736bc1f688bSRobert Mustacchi             for details. */
1737bc1f688bSRobert Mustacchi         t = aug_armcc;
1738*4d9fdb46SRobert Mustacchi     } else if (strcmp(ag_string, "HC") == 0) {
1739*4d9fdb46SRobert Mustacchi         t = aug_metaware;
1740bc1f688bSRobert Mustacchi     } else {
1741bc1f688bSRobert Mustacchi     }
1742bc1f688bSRobert Mustacchi     return t;
1743bc1f688bSRobert Mustacchi }
1744bc1f688bSRobert Mustacchi 
1745bc1f688bSRobert Mustacchi /*  Using augmentation, and version
1746bc1f688bSRobert Mustacchi     read in the augmentation data for GNU eh.
1747bc1f688bSRobert Mustacchi 
1748bc1f688bSRobert Mustacchi     Return DW_DLV_OK if we succeeded,
1749bc1f688bSRobert Mustacchi     DW_DLV_ERR if we fail.
1750bc1f688bSRobert Mustacchi 
1751bc1f688bSRobert Mustacchi     On success, update  'size_of_augmentation_data' with
1752bc1f688bSRobert Mustacchi     the length of the fields that are part of augmentation (so the
1753bc1f688bSRobert Mustacchi     caller can increment frame_ptr appropriately).
1754bc1f688bSRobert Mustacchi 
1755bc1f688bSRobert Mustacchi     'frame_ptr' points within section.
1756*4d9fdb46SRobert Mustacchi     'section_end' points to end of section area of interest.
1757*4d9fdb46SRobert Mustacchi 
1758bc1f688bSRobert Mustacchi */
1759bc1f688bSRobert Mustacchi /* ARGSUSED */
1760bc1f688bSRobert Mustacchi 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)1761bc1f688bSRobert Mustacchi get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
1762bc1f688bSRobert Mustacchi     unsigned long *size_of_augmentation_data,
1763bc1f688bSRobert Mustacchi     enum Dwarf_augmentation_type augtype,
1764*4d9fdb46SRobert Mustacchi     Dwarf_Small * section_ptr_end,
1765*4d9fdb46SRobert Mustacchi     char *augmentation,
1766*4d9fdb46SRobert Mustacchi     Dwarf_Error *error)
1767bc1f688bSRobert Mustacchi {
1768bc1f688bSRobert Mustacchi     char *suffix = 0;
1769bc1f688bSRobert Mustacchi     unsigned long augdata_size = 0;
1770bc1f688bSRobert Mustacchi 
1771bc1f688bSRobert Mustacchi     if (augtype == aug_gcc_eh_z) {
1772bc1f688bSRobert Mustacchi         /* Has leading 'z'. */
1773*4d9fdb46SRobert Mustacchi         UNUSEDARG Dwarf_Unsigned val = 0;
1774*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned leb128_length = 0;
1775bc1f688bSRobert Mustacchi 
1776bc1f688bSRobert Mustacchi         /* 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);
1779bc1f688bSRobert Mustacchi         augdata_size += leb128_length;
1780bc1f688bSRobert Mustacchi         suffix = augmentation + 1;
1781bc1f688bSRobert Mustacchi     } else {
1782bc1f688bSRobert Mustacchi         /*  Prefix is 'eh'.  As in gcc 3.2. No suffix present
1783bc1f688bSRobert Mustacchi             apparently. */
1784bc1f688bSRobert Mustacchi         suffix = augmentation + 2;
1785bc1f688bSRobert Mustacchi     }
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
1791bc1f688bSRobert Mustacchi             dwarf exist which we do not yet handle. */
1792*4d9fdb46SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
1793bc1f688bSRobert Mustacchi         return DW_DLV_ERROR;
1794bc1f688bSRobert Mustacchi 
1795bc1f688bSRobert Mustacchi     }
1796bc1f688bSRobert Mustacchi 
1797bc1f688bSRobert Mustacchi     *size_of_augmentation_data = augdata_size;
1798bc1f688bSRobert Mustacchi     return DW_DLV_OK;
1799bc1f688bSRobert Mustacchi }
1800bc1f688bSRobert Mustacchi 
1801bc1f688bSRobert Mustacchi 
1802bc1f688bSRobert Mustacchi /* To properly release all spaced used.
1803bc1f688bSRobert Mustacchi    Earlier approaches (before July 15, 2005)
1804bc1f688bSRobert Mustacchi    letting client do the dealloc directly left
1805bc1f688bSRobert Mustacchi    some data allocated.
1806bc1f688bSRobert Mustacchi    This is directly called by consumer code.
1807bc1f688bSRobert Mustacchi */
1808bc1f688bSRobert Mustacchi 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)1809bc1f688bSRobert Mustacchi dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
1810bc1f688bSRobert Mustacchi     Dwarf_Cie * cie_data,
1811bc1f688bSRobert Mustacchi     Dwarf_Signed cie_element_count,
1812bc1f688bSRobert Mustacchi     Dwarf_Fde * fde_data,
1813bc1f688bSRobert Mustacchi     Dwarf_Signed fde_element_count)
1814bc1f688bSRobert Mustacchi {
1815bc1f688bSRobert Mustacchi     Dwarf_Signed i = 0;
1816bc1f688bSRobert Mustacchi 
1817bc1f688bSRobert Mustacchi     for (i = 0; i < cie_element_count; ++i) {
1818bc1f688bSRobert Mustacchi         Dwarf_Frame frame = cie_data[i]->ci_initial_table;
1819bc1f688bSRobert Mustacchi 
1820*4d9fdb46SRobert Mustacchi         if (frame) {
1821bc1f688bSRobert Mustacchi             dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
1822*4d9fdb46SRobert Mustacchi         }
1823bc1f688bSRobert Mustacchi         dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
1824bc1f688bSRobert Mustacchi     }
1825bc1f688bSRobert Mustacchi     for (i = 0; i < fde_element_count; ++i) {
1826bc1f688bSRobert Mustacchi         dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
1827bc1f688bSRobert Mustacchi     }
1828*4d9fdb46SRobert Mustacchi     if (cie_data) {
1829bc1f688bSRobert Mustacchi         dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
1830*4d9fdb46SRobert Mustacchi     }
1831*4d9fdb46SRobert Mustacchi     if (fde_data) {
1832bc1f688bSRobert Mustacchi         dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
1833*4d9fdb46SRobert Mustacchi     }
1834bc1f688bSRobert Mustacchi }
1835