xref: /titanic_52/usr/src/lib/libdwarf/common/dwarf_frame2.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi 
3*7fd79137SRobert Mustacchi   Copyright (C) 2000-2006 Silicon Graphics, Inc.  All Rights Reserved.
4*7fd79137SRobert Mustacchi   Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
5*7fd79137SRobert Mustacchi 
6*7fd79137SRobert Mustacchi   This program is free software; you can redistribute it and/or modify it
7*7fd79137SRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
8*7fd79137SRobert Mustacchi   as published by the Free Software Foundation.
9*7fd79137SRobert Mustacchi 
10*7fd79137SRobert Mustacchi   This program is distributed in the hope that it would be useful, but
11*7fd79137SRobert Mustacchi   WITHOUT ANY WARRANTY; without even the implied warranty of
12*7fd79137SRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13*7fd79137SRobert Mustacchi 
14*7fd79137SRobert Mustacchi   Further, this software is distributed without any warranty that it is
15*7fd79137SRobert Mustacchi   free of the rightful claim of any third person regarding infringement
16*7fd79137SRobert Mustacchi   or the like.  Any license provided herein, whether implied or
17*7fd79137SRobert Mustacchi   otherwise, applies only to this software file.  Patent licenses, if
18*7fd79137SRobert Mustacchi   any, provided herein do not apply to combinations of this program with
19*7fd79137SRobert Mustacchi   other software, or any other product whatsoever.
20*7fd79137SRobert Mustacchi 
21*7fd79137SRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
22*7fd79137SRobert Mustacchi   License along with this program; if not, write the Free Software
23*7fd79137SRobert Mustacchi   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
24*7fd79137SRobert Mustacchi   USA.
25*7fd79137SRobert Mustacchi 
26*7fd79137SRobert Mustacchi   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
27*7fd79137SRobert Mustacchi   Mountain View, CA 94043, or:
28*7fd79137SRobert Mustacchi 
29*7fd79137SRobert Mustacchi   http://www.sgi.com
30*7fd79137SRobert Mustacchi 
31*7fd79137SRobert Mustacchi   For further information regarding this notice, see:
32*7fd79137SRobert Mustacchi 
33*7fd79137SRobert Mustacchi   http://oss.sgi.com/projects/GenInfo/NoticeExplan
34*7fd79137SRobert Mustacchi 
35*7fd79137SRobert Mustacchi */
36*7fd79137SRobert Mustacchi /* The address of the Free Software Foundation is
37*7fd79137SRobert Mustacchi    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
38*7fd79137SRobert Mustacchi    Boston, MA 02110-1301, USA.
39*7fd79137SRobert Mustacchi    SGI has moved from the Crittenden Lane address.
40*7fd79137SRobert Mustacchi */
41*7fd79137SRobert Mustacchi 
42*7fd79137SRobert Mustacchi 
43*7fd79137SRobert Mustacchi /*
44*7fd79137SRobert Mustacchi         This  implements _dwarf_get_fde_list_internal()
45*7fd79137SRobert Mustacchi         and related helper functions for reading cie/fde data.
46*7fd79137SRobert Mustacchi */
47*7fd79137SRobert Mustacchi 
48*7fd79137SRobert Mustacchi 
49*7fd79137SRobert Mustacchi 
50*7fd79137SRobert Mustacchi #include "config.h"
51*7fd79137SRobert Mustacchi #include "dwarf_incl.h"
52*7fd79137SRobert Mustacchi #include <stdio.h>
53*7fd79137SRobert Mustacchi #include <stdlib.h>
54*7fd79137SRobert Mustacchi #include <sys/types.h>
55*7fd79137SRobert Mustacchi #include "dwarf_frame.h"
56*7fd79137SRobert Mustacchi #include "dwarf_arange.h"       /* using Arange as a way to build a
57*7fd79137SRobert Mustacchi                                    list */
58*7fd79137SRobert Mustacchi 
59*7fd79137SRobert Mustacchi 
60*7fd79137SRobert Mustacchi static int dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
61*7fd79137SRobert Mustacchi                                        Dwarf_Cie cur_cie_ptr,
62*7fd79137SRobert Mustacchi                                        Dwarf_Cie * cie_ptr_to_use_out,
63*7fd79137SRobert Mustacchi                                        Dwarf_Cie head_cie_ptr);
64*7fd79137SRobert Mustacchi static void dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
65*7fd79137SRobert Mustacchi                                           Dwarf_Cie head_cie_ptr);
66*7fd79137SRobert Mustacchi static int dwarf_create_cie_from_start(Dwarf_Debug dbg,
67*7fd79137SRobert Mustacchi                                        Dwarf_Small * cie_ptr_val,
68*7fd79137SRobert Mustacchi                                        Dwarf_Small * section_ptr,
69*7fd79137SRobert Mustacchi                                        Dwarf_Unsigned section_index,
70*7fd79137SRobert Mustacchi                                        Dwarf_Unsigned section_length,
71*7fd79137SRobert Mustacchi                                        Dwarf_Small * frame_ptr_end,
72*7fd79137SRobert Mustacchi                                        Dwarf_Unsigned cie_id_value,
73*7fd79137SRobert Mustacchi                                        Dwarf_Unsigned cie_count,
74*7fd79137SRobert Mustacchi                                        int use_gnu_cie_calc,
75*7fd79137SRobert Mustacchi                                        Dwarf_Cie * cie_ptr_to_use_out,
76*7fd79137SRobert Mustacchi                                        Dwarf_Error * error);
77*7fd79137SRobert Mustacchi 
78*7fd79137SRobert Mustacchi static Dwarf_Small *get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
79*7fd79137SRobert Mustacchi                                             int use_gnu_cie_calc,
80*7fd79137SRobert Mustacchi                                             Dwarf_Small * section_ptr,
81*7fd79137SRobert Mustacchi                                             Dwarf_Small * cie_id_addr);
82*7fd79137SRobert Mustacchi static int get_gcc_eh_augmentation(Dwarf_Debug dbg,
83*7fd79137SRobert Mustacchi                                    Dwarf_Small * frame_ptr,
84*7fd79137SRobert Mustacchi                                    unsigned long
85*7fd79137SRobert Mustacchi                                    *size_of_augmentation_data,
86*7fd79137SRobert Mustacchi                                    enum Dwarf_augmentation_type augtype,
87*7fd79137SRobert Mustacchi                                    Dwarf_Small * section_pointer,
88*7fd79137SRobert Mustacchi                                    Dwarf_Small * fde_eh_encoding_out,
89*7fd79137SRobert Mustacchi                                    char *augmentation);
90*7fd79137SRobert Mustacchi 
91*7fd79137SRobert Mustacchi static int
92*7fd79137SRobert Mustacchi   gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
93*7fd79137SRobert Mustacchi                     Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
94*7fd79137SRobert Mustacchi                     Dwarf_Half address_size,
95*7fd79137SRobert Mustacchi                     unsigned char *pers_hand_enc_out,
96*7fd79137SRobert Mustacchi                     unsigned char *lsda_enc_out,
97*7fd79137SRobert Mustacchi                     unsigned char *fde_begin_enc_out,
98*7fd79137SRobert Mustacchi                     Dwarf_Addr * gnu_pers_addr_out);
99*7fd79137SRobert Mustacchi 
100*7fd79137SRobert Mustacchi 
101*7fd79137SRobert Mustacchi static int read_encoded_ptr(Dwarf_Debug dbg,
102*7fd79137SRobert Mustacchi                             Dwarf_Small * section_pointer,
103*7fd79137SRobert Mustacchi                             Dwarf_Small * input_field,
104*7fd79137SRobert Mustacchi                             int gnu_encoding,
105*7fd79137SRobert Mustacchi                             Dwarf_Half address_size,
106*7fd79137SRobert Mustacchi                             Dwarf_Unsigned * addr,
107*7fd79137SRobert Mustacchi                             Dwarf_Small ** input_field_out);
108*7fd79137SRobert Mustacchi 
109*7fd79137SRobert Mustacchi 
110*7fd79137SRobert Mustacchi 
111*7fd79137SRobert Mustacchi static int qsort_compare(const void *elem1, const void *elem2);
112*7fd79137SRobert Mustacchi 
113*7fd79137SRobert Mustacchi 
114*7fd79137SRobert Mustacchi /* Adds 'newone' to the end of the list starting at 'head'
115*7fd79137SRobert Mustacchi    and makes the new one 'cur'rent. */
116*7fd79137SRobert Mustacchi static void
117*7fd79137SRobert Mustacchi chain_up_fde(Dwarf_Fde newone, Dwarf_Fde * head, Dwarf_Fde * cur)
118*7fd79137SRobert Mustacchi {
119*7fd79137SRobert Mustacchi     if (*head == NULL)
120*7fd79137SRobert Mustacchi         *head = newone;
121*7fd79137SRobert Mustacchi     else {
122*7fd79137SRobert Mustacchi         (*cur)->fd_next = newone;
123*7fd79137SRobert Mustacchi     }
124*7fd79137SRobert Mustacchi     *cur = newone;
125*7fd79137SRobert Mustacchi 
126*7fd79137SRobert Mustacchi }
127*7fd79137SRobert Mustacchi 
128*7fd79137SRobert Mustacchi /* Adds 'newone' to the end of the list starting at 'head'
129*7fd79137SRobert Mustacchi    and makes the new one 'cur'rent. */
130*7fd79137SRobert Mustacchi static void
131*7fd79137SRobert Mustacchi chain_up_cie(Dwarf_Cie newone, Dwarf_Cie * head, Dwarf_Cie * cur)
132*7fd79137SRobert Mustacchi {
133*7fd79137SRobert Mustacchi     if (*head == NULL) {
134*7fd79137SRobert Mustacchi         *head = newone;
135*7fd79137SRobert Mustacchi     } else {
136*7fd79137SRobert Mustacchi         (*cur)->ci_next = newone;
137*7fd79137SRobert Mustacchi     }
138*7fd79137SRobert Mustacchi     *cur = newone;
139*7fd79137SRobert Mustacchi }
140*7fd79137SRobert Mustacchi 
141*7fd79137SRobert Mustacchi /* The size of the length field plus the
142*7fd79137SRobert Mustacchi     value of length must be an integral
143*7fd79137SRobert Mustacchi     multiple of the address size.  Dwarf4 standard.
144*7fd79137SRobert Mustacchi 
145*7fd79137SRobert Mustacchi     A constant that gives the number of bytes of the CIE
146*7fd79137SRobert Mustacchi     structure, not including the length field itself
147*7fd79137SRobert Mustacchi     (where length mod <size of an address> == 0)
148*7fd79137SRobert Mustacchi     (see Section 7.2.2). Dwarf3 standard.
149*7fd79137SRobert Mustacchi 
150*7fd79137SRobert Mustacchi     A uword constant that gives the number of bytes of
151*7fd79137SRobert Mustacchi     the CIE structure, not including the
152*7fd79137SRobert Mustacchi     length field, itself (length mod <addressing unit size> == 0).
153*7fd79137SRobert Mustacchi     Dwarf2 standard.*/
154*7fd79137SRobert Mustacchi static void
155*7fd79137SRobert Mustacchi validate_length(Dwarf_Debug dbg,
156*7fd79137SRobert Mustacchi     Dwarf_Cie cieptr, Dwarf_Unsigned length,
157*7fd79137SRobert Mustacchi     Dwarf_Unsigned length_size,
158*7fd79137SRobert Mustacchi     Dwarf_Unsigned extension_size,
159*7fd79137SRobert Mustacchi     Dwarf_Small * section_ptr,
160*7fd79137SRobert Mustacchi     Dwarf_Small * ciefde_start,
161*7fd79137SRobert Mustacchi     const char * cieorfde)
162*7fd79137SRobert Mustacchi {
163*7fd79137SRobert Mustacchi     Dwarf_Unsigned address_size = cieptr->ci_address_size;
164*7fd79137SRobert Mustacchi     Dwarf_Unsigned length_field_summed = length_size + extension_size;
165*7fd79137SRobert Mustacchi     Dwarf_Unsigned total_len = length + length_field_summed;
166*7fd79137SRobert Mustacchi     Dwarf_Unsigned mod = total_len % address_size;
167*7fd79137SRobert Mustacchi 
168*7fd79137SRobert Mustacchi     if (mod != 0) {
169*7fd79137SRobert Mustacchi         char msg[DW_HARMLESS_ERROR_MSG_STRING_SIZE];
170*7fd79137SRobert Mustacchi         Dwarf_Unsigned sectionoffset = ciefde_start - section_ptr;
171*7fd79137SRobert Mustacchi         snprintf(msg,sizeof(msg),
172*7fd79137SRobert Mustacchi             "DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE"
173*7fd79137SRobert Mustacchi             " len=0x%" DW_PR_DUx
174*7fd79137SRobert Mustacchi             ", len size=0x%" DW_PR_DUx
175*7fd79137SRobert Mustacchi             ", extn size=0x%" DW_PR_DUx
176*7fd79137SRobert Mustacchi             ", totl length=0x%" DW_PR_DUx
177*7fd79137SRobert Mustacchi             ", addr size=0x%" DW_PR_DUx
178*7fd79137SRobert Mustacchi             ", mod=0x%" DW_PR_DUx " must be zero"
179*7fd79137SRobert Mustacchi             " in %s"
180*7fd79137SRobert Mustacchi             ", offset 0x%" DW_PR_DUx ".",
181*7fd79137SRobert Mustacchi             length,
182*7fd79137SRobert Mustacchi             length_size,
183*7fd79137SRobert Mustacchi             extension_size,
184*7fd79137SRobert Mustacchi             total_len,address_size, mod,
185*7fd79137SRobert Mustacchi             cieorfde,
186*7fd79137SRobert Mustacchi             sectionoffset);
187*7fd79137SRobert Mustacchi         dwarf_insert_harmless_error(dbg,msg);
188*7fd79137SRobert Mustacchi     }
189*7fd79137SRobert Mustacchi     return;
190*7fd79137SRobert Mustacchi }
191*7fd79137SRobert Mustacchi 
192*7fd79137SRobert Mustacchi 
193*7fd79137SRobert Mustacchi #if 0
194*7fd79137SRobert Mustacchi /* For debugging only. */
195*7fd79137SRobert Mustacchi static void
196*7fd79137SRobert Mustacchi print_prefix(struct cie_fde_prefix_s *prefix, int line)
197*7fd79137SRobert Mustacchi {
198*7fd79137SRobert Mustacchi     printf("prefix-print, prefix at 0x%lx, line %d\n",
199*7fd79137SRobert Mustacchi            (long) prefix, line);
200*7fd79137SRobert Mustacchi     printf("  start addr 0x%lx after prefix 0x%lx\n",
201*7fd79137SRobert Mustacchi            (long) prefix->cf_start_addr,
202*7fd79137SRobert Mustacchi            (long) prefix->cf_addr_after_prefix);
203*7fd79137SRobert Mustacchi     printf("  length 0x%" DW_PR_DUx ", len size %d ext size %d\n",
204*7fd79137SRobert Mustacchi            (Dwarf_Unsigned) prefix->cf_length,
205*7fd79137SRobert Mustacchi            prefix->cf_local_length_size,
206*7fd79137SRobert Mustacchi            prefix->cf_local_extension_size);
207*7fd79137SRobert Mustacchi     printf("  cie_id 0x%" DW_PR_DUx " cie_id  cie_id_addr 0x%lx\n",
208*7fd79137SRobert Mustacchi            (Dwarf_Unsigned) prefix->cf_cie_id,
209*7fd79137SRobert Mustacchi            (long) prefix->cf_cie_id_addr);
210*7fd79137SRobert Mustacchi     printf
211*7fd79137SRobert Mustacchi         ("  sec ptr 0x%lx sec index %" DW_PR_DSd " sec len 0x%" DW_PR_DUx " sec past end 0x%lx\n",
212*7fd79137SRobert Mustacchi          (long) prefix->cf_section_ptr,
213*7fd79137SRobert Mustacchi          (Dwarf_Signed) prefix->cf_section_index,
214*7fd79137SRobert Mustacchi          (Dwarf_Unsigned) prefix->cf_section_length,
215*7fd79137SRobert Mustacchi          (long) prefix->cf_section_ptr + prefix->cf_section_length);
216*7fd79137SRobert Mustacchi }
217*7fd79137SRobert Mustacchi #endif
218*7fd79137SRobert Mustacchi 
219*7fd79137SRobert Mustacchi 
220*7fd79137SRobert Mustacchi 
221*7fd79137SRobert Mustacchi /* Internal function called from various places to create
222*7fd79137SRobert Mustacchi    lists of CIEs and FDEs.  Not directly called
223*7fd79137SRobert Mustacchi    by consumer code */
224*7fd79137SRobert Mustacchi int
225*7fd79137SRobert Mustacchi _dwarf_get_fde_list_internal(Dwarf_Debug dbg, Dwarf_Cie ** cie_data,
226*7fd79137SRobert Mustacchi     Dwarf_Signed * cie_element_count,
227*7fd79137SRobert Mustacchi     Dwarf_Fde ** fde_data,
228*7fd79137SRobert Mustacchi     Dwarf_Signed * fde_element_count,
229*7fd79137SRobert Mustacchi     Dwarf_Small * section_ptr,
230*7fd79137SRobert Mustacchi     Dwarf_Unsigned section_index,
231*7fd79137SRobert Mustacchi     Dwarf_Unsigned section_length,
232*7fd79137SRobert Mustacchi     Dwarf_Unsigned cie_id_value,
233*7fd79137SRobert Mustacchi     int use_gnu_cie_calc, Dwarf_Error * error)
234*7fd79137SRobert Mustacchi {
235*7fd79137SRobert Mustacchi     /* Scans the debug_frame section. */
236*7fd79137SRobert Mustacchi     Dwarf_Small *frame_ptr = section_ptr;
237*7fd79137SRobert Mustacchi     Dwarf_Small *frame_ptr_end = section_ptr + section_length;
238*7fd79137SRobert Mustacchi 
239*7fd79137SRobert Mustacchi 
240*7fd79137SRobert Mustacchi 
241*7fd79137SRobert Mustacchi     /*
242*7fd79137SRobert Mustacchi        New_cie points to the Cie being read, and head_cie_ptr and
243*7fd79137SRobert Mustacchi        cur_cie_ptr are used for chaining them up in sequence.
244*7fd79137SRobert Mustacchi        In case cie's are reused aggressively we need tail_cie_ptr
245*7fd79137SRobert Mustacchi        to add to the chain.  If we re-use an early cie
246*7fd79137SRobert Mustacchi        later on, that does not mean we chain a new cie to the early one,
247*7fd79137SRobert Mustacchi        we always chain it to the tail.  */
248*7fd79137SRobert Mustacchi     Dwarf_Cie head_cie_ptr = NULL;
249*7fd79137SRobert Mustacchi     Dwarf_Cie cur_cie_ptr = NULL;
250*7fd79137SRobert Mustacchi     Dwarf_Cie tail_cie_ptr = NULL;
251*7fd79137SRobert Mustacchi     Dwarf_Word cie_count = 0;
252*7fd79137SRobert Mustacchi 
253*7fd79137SRobert Mustacchi     /*
254*7fd79137SRobert Mustacchi        Points to a list of contiguous pointers to Dwarf_Cie structures.
255*7fd79137SRobert Mustacchi      */
256*7fd79137SRobert Mustacchi     Dwarf_Cie *cie_list_ptr = 0;
257*7fd79137SRobert Mustacchi 
258*7fd79137SRobert Mustacchi 
259*7fd79137SRobert Mustacchi     /*
260*7fd79137SRobert Mustacchi        New_fde points to the Fde being created, and head_fde_ptr and
261*7fd79137SRobert Mustacchi        cur_fde_ptr are used to chain them up. */
262*7fd79137SRobert Mustacchi     Dwarf_Fde head_fde_ptr = NULL;
263*7fd79137SRobert Mustacchi     Dwarf_Fde cur_fde_ptr = NULL;
264*7fd79137SRobert Mustacchi     Dwarf_Word fde_count = 0;
265*7fd79137SRobert Mustacchi 
266*7fd79137SRobert Mustacchi     /*
267*7fd79137SRobert Mustacchi        Points to a list of contiguous pointers to Dwarf_Fde structures.
268*7fd79137SRobert Mustacchi      */
269*7fd79137SRobert Mustacchi     Dwarf_Fde *fde_list_ptr = NULL;
270*7fd79137SRobert Mustacchi 
271*7fd79137SRobert Mustacchi     Dwarf_Word i = 0;
272*7fd79137SRobert Mustacchi     int res = DW_DLV_ERROR;
273*7fd79137SRobert Mustacchi 
274*7fd79137SRobert Mustacchi     if (frame_ptr == 0) {
275*7fd79137SRobert Mustacchi         return DW_DLV_NO_ENTRY;
276*7fd79137SRobert Mustacchi     }
277*7fd79137SRobert Mustacchi 
278*7fd79137SRobert Mustacchi     /* We create the fde and cie arrays. Processing each CIE as we come
279*7fd79137SRobert Mustacchi        to it or as an FDE refers to it.  We cannot process 'late' CIEs
280*7fd79137SRobert Mustacchi        late as GNU .eh_frame complexities mean we need the whole CIE
281*7fd79137SRobert Mustacchi        before we can process the FDE correctly. */
282*7fd79137SRobert Mustacchi     while (frame_ptr < frame_ptr_end) {
283*7fd79137SRobert Mustacchi 
284*7fd79137SRobert Mustacchi         struct cie_fde_prefix_s prefix;
285*7fd79137SRobert Mustacchi 
286*7fd79137SRobert Mustacchi         /* First read in the 'common prefix' to figure out what we are
287*7fd79137SRobert Mustacchi            to do with this entry. */
288*7fd79137SRobert Mustacchi         memset(&prefix, 0, sizeof(prefix));
289*7fd79137SRobert Mustacchi         res = dwarf_read_cie_fde_prefix(dbg,
290*7fd79137SRobert Mustacchi                                         frame_ptr, section_ptr,
291*7fd79137SRobert Mustacchi                                         section_index,
292*7fd79137SRobert Mustacchi                                         section_length, &prefix, error);
293*7fd79137SRobert Mustacchi         if (res == DW_DLV_ERROR) {
294*7fd79137SRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
295*7fd79137SRobert Mustacchi             return res;
296*7fd79137SRobert Mustacchi         }
297*7fd79137SRobert Mustacchi         if (res == DW_DLV_NO_ENTRY)
298*7fd79137SRobert Mustacchi             break;
299*7fd79137SRobert Mustacchi         frame_ptr = prefix.cf_addr_after_prefix;
300*7fd79137SRobert Mustacchi         if (frame_ptr >= frame_ptr_end) {
301*7fd79137SRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
302*7fd79137SRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
303*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
304*7fd79137SRobert Mustacchi 
305*7fd79137SRobert Mustacchi         }
306*7fd79137SRobert Mustacchi 
307*7fd79137SRobert Mustacchi         if (prefix.cf_cie_id == cie_id_value) {
308*7fd79137SRobert Mustacchi             /* This is a CIE.  */
309*7fd79137SRobert Mustacchi             Dwarf_Cie cie_ptr_to_use = 0;
310*7fd79137SRobert Mustacchi 
311*7fd79137SRobert Mustacchi             int res = dwarf_find_existing_cie_ptr(prefix.cf_start_addr,
312*7fd79137SRobert Mustacchi                                                   cur_cie_ptr,
313*7fd79137SRobert Mustacchi                                                   &cie_ptr_to_use,
314*7fd79137SRobert Mustacchi                                                   head_cie_ptr);
315*7fd79137SRobert Mustacchi 
316*7fd79137SRobert Mustacchi             if (res == DW_DLV_OK) {
317*7fd79137SRobert Mustacchi                 cur_cie_ptr = cie_ptr_to_use;
318*7fd79137SRobert Mustacchi                 /* Ok. Seen already. */
319*7fd79137SRobert Mustacchi             } else if (res == DW_DLV_NO_ENTRY) {
320*7fd79137SRobert Mustacchi                 /* CIE before its FDE in this case. */
321*7fd79137SRobert Mustacchi                 res = dwarf_create_cie_from_after_start(dbg,
322*7fd79137SRobert Mustacchi                                                         &prefix,
323*7fd79137SRobert Mustacchi                                                         section_ptr,
324*7fd79137SRobert Mustacchi                                                         frame_ptr,
325*7fd79137SRobert Mustacchi                                                         cie_count,
326*7fd79137SRobert Mustacchi                                                         use_gnu_cie_calc,
327*7fd79137SRobert Mustacchi                                                         &cie_ptr_to_use,
328*7fd79137SRobert Mustacchi                                                         error);
329*7fd79137SRobert Mustacchi                 /* ASSERT: res==DW_DLV_NO_ENTRY impossible. */
330*7fd79137SRobert Mustacchi                 if (res == DW_DLV_ERROR) {
331*7fd79137SRobert Mustacchi                     dealloc_fde_cie_list_internal(head_fde_ptr,
332*7fd79137SRobert Mustacchi                                                   head_cie_ptr);
333*7fd79137SRobert Mustacchi                     return res;
334*7fd79137SRobert Mustacchi                 }
335*7fd79137SRobert Mustacchi                 /* ASSERT res != DW_DLV_NO_ENTRY */
336*7fd79137SRobert Mustacchi                 cie_count++;
337*7fd79137SRobert Mustacchi                 chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
338*7fd79137SRobert Mustacchi                              &tail_cie_ptr);
339*7fd79137SRobert Mustacchi                 cur_cie_ptr = tail_cie_ptr;
340*7fd79137SRobert Mustacchi             } else {            /* res == DW_DLV_ERROR */
341*7fd79137SRobert Mustacchi 
342*7fd79137SRobert Mustacchi                 dealloc_fde_cie_list_internal(head_fde_ptr,
343*7fd79137SRobert Mustacchi                                               head_cie_ptr);
344*7fd79137SRobert Mustacchi                 return res;
345*7fd79137SRobert Mustacchi             }
346*7fd79137SRobert Mustacchi             frame_ptr = cie_ptr_to_use->ci_cie_start +
347*7fd79137SRobert Mustacchi                 cie_ptr_to_use->ci_length +
348*7fd79137SRobert Mustacchi                 cie_ptr_to_use->ci_length_size +
349*7fd79137SRobert Mustacchi                 cie_ptr_to_use->ci_extension_size;
350*7fd79137SRobert Mustacchi             continue;
351*7fd79137SRobert Mustacchi         } else {
352*7fd79137SRobert Mustacchi             /* this is an FDE, Frame Description Entry, see the Dwarf
353*7fd79137SRobert Mustacchi                Spec, section 6.4.1 */
354*7fd79137SRobert Mustacchi             int res = DW_DLV_ERROR;
355*7fd79137SRobert Mustacchi             Dwarf_Cie cie_ptr_to_use = 0;
356*7fd79137SRobert Mustacchi             Dwarf_Fde fde_ptr_to_use = 0;
357*7fd79137SRobert Mustacchi 
358*7fd79137SRobert Mustacchi             /* Do not call this twice on one prefix, as
359*7fd79137SRobert Mustacchi                prefix.cf_cie_id_addr is altered as a side effect. */
360*7fd79137SRobert Mustacchi             Dwarf_Small *cieptr_val =
361*7fd79137SRobert Mustacchi                 get_cieptr_given_offset(prefix.cf_cie_id,
362*7fd79137SRobert Mustacchi                                         use_gnu_cie_calc,
363*7fd79137SRobert Mustacchi                                         section_ptr,
364*7fd79137SRobert Mustacchi                                         prefix.cf_cie_id_addr);
365*7fd79137SRobert Mustacchi 
366*7fd79137SRobert Mustacchi             res = dwarf_find_existing_cie_ptr(cieptr_val,
367*7fd79137SRobert Mustacchi                                               cur_cie_ptr,
368*7fd79137SRobert Mustacchi                                               &cie_ptr_to_use,
369*7fd79137SRobert Mustacchi                                               head_cie_ptr);
370*7fd79137SRobert Mustacchi             if (res == DW_DLV_OK) {
371*7fd79137SRobert Mustacchi                 cur_cie_ptr = cie_ptr_to_use;
372*7fd79137SRobert Mustacchi                 /* Ok. Seen CIE already. */
373*7fd79137SRobert Mustacchi             } else if (res == DW_DLV_NO_ENTRY) {
374*7fd79137SRobert Mustacchi                 res = dwarf_create_cie_from_start(dbg,
375*7fd79137SRobert Mustacchi                                                   cieptr_val,
376*7fd79137SRobert Mustacchi                                                   section_ptr,
377*7fd79137SRobert Mustacchi                                                   section_index,
378*7fd79137SRobert Mustacchi                                                   section_length,
379*7fd79137SRobert Mustacchi                                                   frame_ptr_end,
380*7fd79137SRobert Mustacchi                                                   cie_id_value,
381*7fd79137SRobert Mustacchi                                                   cie_count,
382*7fd79137SRobert Mustacchi                                                   use_gnu_cie_calc,
383*7fd79137SRobert Mustacchi                                                   &cie_ptr_to_use,
384*7fd79137SRobert Mustacchi                                                   error);
385*7fd79137SRobert Mustacchi                 if (res == DW_DLV_ERROR) {
386*7fd79137SRobert Mustacchi                     dealloc_fde_cie_list_internal(head_fde_ptr,
387*7fd79137SRobert Mustacchi                                                   head_cie_ptr);
388*7fd79137SRobert Mustacchi                     return res;
389*7fd79137SRobert Mustacchi                 } else if (res == DW_DLV_NO_ENTRY) {
390*7fd79137SRobert Mustacchi                     return res;
391*7fd79137SRobert Mustacchi                 }
392*7fd79137SRobert Mustacchi                 ++cie_count;
393*7fd79137SRobert Mustacchi                 chain_up_cie(cie_ptr_to_use, &head_cie_ptr,
394*7fd79137SRobert Mustacchi                              &tail_cie_ptr);
395*7fd79137SRobert Mustacchi                 cur_cie_ptr = tail_cie_ptr;
396*7fd79137SRobert Mustacchi 
397*7fd79137SRobert Mustacchi             } else {
398*7fd79137SRobert Mustacchi                 /* DW_DLV_ERROR */
399*7fd79137SRobert Mustacchi                 return res;
400*7fd79137SRobert Mustacchi             }
401*7fd79137SRobert Mustacchi 
402*7fd79137SRobert Mustacchi             res = dwarf_create_fde_from_after_start(dbg,
403*7fd79137SRobert Mustacchi                                                     &prefix,
404*7fd79137SRobert Mustacchi                                                     section_ptr,
405*7fd79137SRobert Mustacchi                                                     frame_ptr,
406*7fd79137SRobert Mustacchi                                                     use_gnu_cie_calc,
407*7fd79137SRobert Mustacchi                                                     cie_ptr_to_use,
408*7fd79137SRobert Mustacchi                                                     &fde_ptr_to_use,
409*7fd79137SRobert Mustacchi                                                     error);
410*7fd79137SRobert Mustacchi             if (res == DW_DLV_ERROR) {
411*7fd79137SRobert Mustacchi                 return res;
412*7fd79137SRobert Mustacchi             }
413*7fd79137SRobert Mustacchi             chain_up_fde(fde_ptr_to_use, &head_fde_ptr, &cur_fde_ptr);
414*7fd79137SRobert Mustacchi             fde_count++;
415*7fd79137SRobert Mustacchi             /* ASSERT: DW_DLV_OK. */
416*7fd79137SRobert Mustacchi             frame_ptr = fde_ptr_to_use->fd_fde_start +
417*7fd79137SRobert Mustacchi                 fde_ptr_to_use->fd_length +
418*7fd79137SRobert Mustacchi                 fde_ptr_to_use->fd_length_size +
419*7fd79137SRobert Mustacchi                 fde_ptr_to_use->fd_extension_size;
420*7fd79137SRobert Mustacchi             continue;
421*7fd79137SRobert Mustacchi 
422*7fd79137SRobert Mustacchi         }
423*7fd79137SRobert Mustacchi 
424*7fd79137SRobert Mustacchi     }
425*7fd79137SRobert Mustacchi 
426*7fd79137SRobert Mustacchi     /* Now build list of CIEs from the list. If there are no CIEs
427*7fd79137SRobert Mustacchi        there should be no FDEs. */
428*7fd79137SRobert Mustacchi     if (cie_count > 0) {
429*7fd79137SRobert Mustacchi         cie_list_ptr = (Dwarf_Cie *)
430*7fd79137SRobert Mustacchi             _dwarf_get_alloc(dbg, DW_DLA_LIST, cie_count);
431*7fd79137SRobert Mustacchi     } else {
432*7fd79137SRobert Mustacchi         if(fde_count > 0) {
433*7fd79137SRobert Mustacchi             dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
434*7fd79137SRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_ORPHAN_FDE);
435*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
436*7fd79137SRobert Mustacchi         }
437*7fd79137SRobert Mustacchi         dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
438*7fd79137SRobert Mustacchi         return DW_DLV_NO_ENTRY;
439*7fd79137SRobert Mustacchi     }
440*7fd79137SRobert Mustacchi     if (cie_list_ptr == NULL) {
441*7fd79137SRobert Mustacchi         dealloc_fde_cie_list_internal(head_fde_ptr, head_cie_ptr);
442*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
443*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
444*7fd79137SRobert Mustacchi     }
445*7fd79137SRobert Mustacchi     cur_cie_ptr = head_cie_ptr;
446*7fd79137SRobert Mustacchi     for (i = 0; i < cie_count; i++) {
447*7fd79137SRobert Mustacchi         *(cie_list_ptr + i) = cur_cie_ptr;
448*7fd79137SRobert Mustacchi         cur_cie_ptr = cur_cie_ptr->ci_next;
449*7fd79137SRobert Mustacchi     }
450*7fd79137SRobert Mustacchi 
451*7fd79137SRobert Mustacchi 
452*7fd79137SRobert Mustacchi 
453*7fd79137SRobert Mustacchi     /* Now build array of FDEs from the list.
454*7fd79137SRobert Mustacchi        With orphan CIEs (meaning no FDEs) lets not return DW_DLV_NO_ENTRY */
455*7fd79137SRobert Mustacchi     if (fde_count > 0) {
456*7fd79137SRobert Mustacchi         fde_list_ptr = (Dwarf_Fde *)
457*7fd79137SRobert Mustacchi             _dwarf_get_alloc(dbg, DW_DLA_LIST, fde_count);
458*7fd79137SRobert Mustacchi     }
459*7fd79137SRobert Mustacchi 
460*7fd79137SRobert Mustacchi     /* It is ok if fde_list_ptr is NULL, we just have no fdes. */
461*7fd79137SRobert Mustacchi     cur_fde_ptr = head_fde_ptr;
462*7fd79137SRobert Mustacchi     for (i = 0; i < fde_count; i++) {
463*7fd79137SRobert Mustacchi         *(fde_list_ptr + i) = cur_fde_ptr;
464*7fd79137SRobert Mustacchi         cur_fde_ptr = cur_fde_ptr->fd_next;
465*7fd79137SRobert Mustacchi     }
466*7fd79137SRobert Mustacchi 
467*7fd79137SRobert Mustacchi 
468*7fd79137SRobert Mustacchi     /* Return arguments. */
469*7fd79137SRobert Mustacchi     *cie_data = cie_list_ptr;
470*7fd79137SRobert Mustacchi     *cie_element_count = cie_count;
471*7fd79137SRobert Mustacchi 
472*7fd79137SRobert Mustacchi     *fde_data = fde_list_ptr;
473*7fd79137SRobert Mustacchi     *fde_element_count = fde_count;
474*7fd79137SRobert Mustacchi     if(use_gnu_cie_calc) {
475*7fd79137SRobert Mustacchi       dbg->de_fde_data_eh = fde_list_ptr;
476*7fd79137SRobert Mustacchi       dbg->de_fde_count_eh = fde_count;
477*7fd79137SRobert Mustacchi       dbg->de_cie_data_eh = cie_list_ptr;
478*7fd79137SRobert Mustacchi       dbg->de_cie_count_eh = cie_count;
479*7fd79137SRobert Mustacchi     } else {
480*7fd79137SRobert Mustacchi       dbg->de_fde_data = fde_list_ptr;
481*7fd79137SRobert Mustacchi       dbg->de_fde_count = fde_count;
482*7fd79137SRobert Mustacchi       dbg->de_cie_data = cie_list_ptr;
483*7fd79137SRobert Mustacchi       dbg->de_cie_count = cie_count;
484*7fd79137SRobert Mustacchi     }
485*7fd79137SRobert Mustacchi 
486*7fd79137SRobert Mustacchi     /* Sort the list by the address so that dwarf_get_fde_at_pc() can
487*7fd79137SRobert Mustacchi        binary search this list.  */
488*7fd79137SRobert Mustacchi     if(fde_count > 0) {
489*7fd79137SRobert Mustacchi         qsort((void *) fde_list_ptr, fde_count, sizeof(Dwarf_Ptr),
490*7fd79137SRobert Mustacchi            qsort_compare);
491*7fd79137SRobert Mustacchi     }
492*7fd79137SRobert Mustacchi 
493*7fd79137SRobert Mustacchi     return (DW_DLV_OK);
494*7fd79137SRobert Mustacchi }
495*7fd79137SRobert Mustacchi 
496*7fd79137SRobert Mustacchi /* Internal function, not called by consumer code.
497*7fd79137SRobert Mustacchi    'prefix' has accumulated the info up thru the cie-id
498*7fd79137SRobert Mustacchi    and now we consume the rest and build a Dwarf_Cie_s structure.
499*7fd79137SRobert Mustacchi */
500*7fd79137SRobert Mustacchi int
501*7fd79137SRobert Mustacchi dwarf_create_cie_from_after_start(Dwarf_Debug dbg,
502*7fd79137SRobert Mustacchi     struct cie_fde_prefix_s *prefix,
503*7fd79137SRobert Mustacchi     Dwarf_Small * section_pointer,
504*7fd79137SRobert Mustacchi     Dwarf_Small * frame_ptr,
505*7fd79137SRobert Mustacchi     Dwarf_Unsigned cie_count,
506*7fd79137SRobert Mustacchi     int use_gnu_cie_calc,
507*7fd79137SRobert Mustacchi     Dwarf_Cie * cie_ptr_out,
508*7fd79137SRobert Mustacchi     Dwarf_Error * error)
509*7fd79137SRobert Mustacchi {
510*7fd79137SRobert Mustacchi     Dwarf_Cie new_cie = 0;
511*7fd79137SRobert Mustacchi 
512*7fd79137SRobert Mustacchi     /* egcs-1.1.2 .eh_frame uses 0 as the distinguishing id. sgi uses
513*7fd79137SRobert Mustacchi        -1 (in .debug_frame). .eh_frame not quite identical to
514*7fd79137SRobert Mustacchi        .debug_frame */
515*7fd79137SRobert Mustacchi     /* We here default the address size as it is not present
516*7fd79137SRobert Mustacchi        in DWARF2 or DWARF3 cie data, below we set it right if
517*7fd79137SRobert Mustacchi        it is present. */
518*7fd79137SRobert Mustacchi     Dwarf_Half address_size = dbg->de_pointer_size;
519*7fd79137SRobert Mustacchi     Dwarf_Small eh_fde_encoding = 0;
520*7fd79137SRobert Mustacchi     Dwarf_Small *augmentation = 0;
521*7fd79137SRobert Mustacchi     Dwarf_Half segment_size = 0;
522*7fd79137SRobert Mustacchi     Dwarf_Sword data_alignment_factor = -1;
523*7fd79137SRobert Mustacchi     Dwarf_Word code_alignment_factor = 4;
524*7fd79137SRobert Mustacchi     Dwarf_Unsigned return_address_register = 31;
525*7fd79137SRobert Mustacchi     int local_length_size = 0;
526*7fd79137SRobert Mustacchi     Dwarf_Word leb128_length = 0;
527*7fd79137SRobert Mustacchi     Dwarf_Unsigned cie_aug_data_len = 0;
528*7fd79137SRobert Mustacchi     Dwarf_Small *cie_aug_data = 0;
529*7fd79137SRobert Mustacchi     Dwarf_Addr gnu_personality_handler_addr = 0;
530*7fd79137SRobert Mustacchi     unsigned char gnu_personality_handler_encoding = 0;
531*7fd79137SRobert Mustacchi     unsigned char gnu_lsda_encoding = 0;
532*7fd79137SRobert Mustacchi     unsigned char gnu_fde_begin_encoding = 0;
533*7fd79137SRobert Mustacchi 
534*7fd79137SRobert Mustacchi 
535*7fd79137SRobert Mustacchi     enum Dwarf_augmentation_type augt = aug_unknown;
536*7fd79137SRobert Mustacchi 
537*7fd79137SRobert Mustacchi 
538*7fd79137SRobert Mustacchi     /* this is a CIE, Common Information Entry: See the dwarf spec,
539*7fd79137SRobert Mustacchi        section 6.4.1 */
540*7fd79137SRobert Mustacchi     Dwarf_Small version = *(Dwarf_Small *) frame_ptr;
541*7fd79137SRobert Mustacchi 
542*7fd79137SRobert Mustacchi     frame_ptr++;
543*7fd79137SRobert Mustacchi     if (version != DW_CIE_VERSION && version != DW_CIE_VERSION3 &&
544*7fd79137SRobert Mustacchi         version != DW_CIE_VERSION4) {
545*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_VERSION_BAD);
546*7fd79137SRobert Mustacchi         return (DW_DLV_ERROR);
547*7fd79137SRobert Mustacchi     }
548*7fd79137SRobert Mustacchi 
549*7fd79137SRobert Mustacchi     augmentation = frame_ptr;
550*7fd79137SRobert Mustacchi     frame_ptr = frame_ptr + strlen((char *) frame_ptr) + 1;
551*7fd79137SRobert Mustacchi     augt = _dwarf_get_augmentation_type(dbg,
552*7fd79137SRobert Mustacchi                                         augmentation, use_gnu_cie_calc);
553*7fd79137SRobert Mustacchi     if (augt == aug_eh) {
554*7fd79137SRobert Mustacchi         /* REFERENCED *//* Not used in this instance */
555*7fd79137SRobert Mustacchi         Dwarf_Unsigned exception_table_addr;
556*7fd79137SRobert Mustacchi 
557*7fd79137SRobert Mustacchi         /* this is per egcs-1.1.2 as on RH 6.0 */
558*7fd79137SRobert Mustacchi         READ_UNALIGNED(dbg, exception_table_addr,
559*7fd79137SRobert Mustacchi                        Dwarf_Unsigned, frame_ptr, local_length_size);
560*7fd79137SRobert Mustacchi         frame_ptr += local_length_size;
561*7fd79137SRobert Mustacchi     }
562*7fd79137SRobert Mustacchi     {
563*7fd79137SRobert Mustacchi         Dwarf_Unsigned lreg = 0;
564*7fd79137SRobert Mustacchi         unsigned long size = 0;
565*7fd79137SRobert Mustacchi 
566*7fd79137SRobert Mustacchi         if( version == DW_CIE_VERSION4) {
567*7fd79137SRobert Mustacchi             address_size = *((unsigned char *)frame_ptr);
568*7fd79137SRobert Mustacchi             ++frame_ptr;
569*7fd79137SRobert Mustacchi             segment_size = *((unsigned char *)frame_ptr);
570*7fd79137SRobert Mustacchi             ++frame_ptr;
571*7fd79137SRobert Mustacchi         }
572*7fd79137SRobert Mustacchi 
573*7fd79137SRobert Mustacchi         DECODE_LEB128_UWORD(frame_ptr, lreg);
574*7fd79137SRobert Mustacchi         code_alignment_factor = (Dwarf_Word) lreg;
575*7fd79137SRobert Mustacchi 
576*7fd79137SRobert Mustacchi         data_alignment_factor =
577*7fd79137SRobert Mustacchi             (Dwarf_Sword) _dwarf_decode_s_leb128(frame_ptr,
578*7fd79137SRobert Mustacchi                                                  &leb128_length);
579*7fd79137SRobert Mustacchi 
580*7fd79137SRobert Mustacchi         frame_ptr = frame_ptr + leb128_length;
581*7fd79137SRobert Mustacchi 
582*7fd79137SRobert Mustacchi         return_address_register =
583*7fd79137SRobert Mustacchi             _dwarf_get_return_address_reg(frame_ptr, version, &size);
584*7fd79137SRobert Mustacchi         if (return_address_register > dbg->de_frame_reg_rules_entry_count) {
585*7fd79137SRobert Mustacchi             _dwarf_error(dbg, error, DW_DLE_CIE_RET_ADDR_REG_ERROR);
586*7fd79137SRobert Mustacchi             return (DW_DLV_ERROR);
587*7fd79137SRobert Mustacchi         }
588*7fd79137SRobert Mustacchi         frame_ptr += size;
589*7fd79137SRobert Mustacchi     }
590*7fd79137SRobert Mustacchi     switch (augt) {
591*7fd79137SRobert Mustacchi     case aug_empty_string:
592*7fd79137SRobert Mustacchi         break;
593*7fd79137SRobert Mustacchi     case aug_irix_mti_v1:
594*7fd79137SRobert Mustacchi         break;
595*7fd79137SRobert Mustacchi     case aug_irix_exception_table:{
596*7fd79137SRobert Mustacchi             Dwarf_Unsigned lreg = 0;
597*7fd79137SRobert Mustacchi             Dwarf_Word length_of_augmented_fields;
598*7fd79137SRobert Mustacchi 
599*7fd79137SRobert Mustacchi             /* Decode the length of augmented fields. */
600*7fd79137SRobert Mustacchi             DECODE_LEB128_UWORD(frame_ptr, lreg);
601*7fd79137SRobert Mustacchi             length_of_augmented_fields = (Dwarf_Word) lreg;
602*7fd79137SRobert Mustacchi 
603*7fd79137SRobert Mustacchi 
604*7fd79137SRobert Mustacchi             /* set the frame_ptr to point at the instruction start. */
605*7fd79137SRobert Mustacchi             frame_ptr += length_of_augmented_fields;
606*7fd79137SRobert Mustacchi         }
607*7fd79137SRobert Mustacchi         break;
608*7fd79137SRobert Mustacchi 
609*7fd79137SRobert Mustacchi     case aug_eh:{
610*7fd79137SRobert Mustacchi 
611*7fd79137SRobert Mustacchi             int err = 0;
612*7fd79137SRobert Mustacchi             unsigned long increment = 0;
613*7fd79137SRobert Mustacchi 
614*7fd79137SRobert Mustacchi             if (!use_gnu_cie_calc) {
615*7fd79137SRobert Mustacchi                 /* This should be impossible. */
616*7fd79137SRobert Mustacchi                 _dwarf_error(dbg, error,
617*7fd79137SRobert Mustacchi                              DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
618*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
619*7fd79137SRobert Mustacchi             }
620*7fd79137SRobert Mustacchi 
621*7fd79137SRobert Mustacchi             err = get_gcc_eh_augmentation(dbg, frame_ptr, &increment,
622*7fd79137SRobert Mustacchi                                           augt,
623*7fd79137SRobert Mustacchi                                           prefix->cf_section_ptr,
624*7fd79137SRobert Mustacchi                                           &eh_fde_encoding,
625*7fd79137SRobert Mustacchi                                           (char *) augmentation);
626*7fd79137SRobert Mustacchi             if (err == DW_DLV_ERROR) {
627*7fd79137SRobert Mustacchi                 _dwarf_error(dbg, error,
628*7fd79137SRobert Mustacchi                              DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
629*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
630*7fd79137SRobert Mustacchi             }
631*7fd79137SRobert Mustacchi             frame_ptr += increment;
632*7fd79137SRobert Mustacchi             break;
633*7fd79137SRobert Mustacchi         }
634*7fd79137SRobert Mustacchi     case aug_gcc_eh_z:{
635*7fd79137SRobert Mustacchi             /* Here we have Augmentation Data Length (uleb128) followed
636*7fd79137SRobert Mustacchi                by Augmentation Data bytes. */
637*7fd79137SRobert Mustacchi             int res = DW_DLV_ERROR;
638*7fd79137SRobert Mustacchi             Dwarf_Unsigned adlen = 0;
639*7fd79137SRobert Mustacchi 
640*7fd79137SRobert Mustacchi             DECODE_LEB128_UWORD(frame_ptr, adlen);
641*7fd79137SRobert Mustacchi             cie_aug_data_len = adlen;
642*7fd79137SRobert Mustacchi             cie_aug_data = frame_ptr;
643*7fd79137SRobert Mustacchi             res = gnu_aug_encodings(dbg,
644*7fd79137SRobert Mustacchi                                     (char *) augmentation,
645*7fd79137SRobert Mustacchi                                     cie_aug_data,
646*7fd79137SRobert Mustacchi                                     cie_aug_data_len,
647*7fd79137SRobert Mustacchi                                     address_size,
648*7fd79137SRobert Mustacchi                                     &gnu_personality_handler_encoding,
649*7fd79137SRobert Mustacchi                                     &gnu_lsda_encoding,
650*7fd79137SRobert Mustacchi                                     &gnu_fde_begin_encoding,
651*7fd79137SRobert Mustacchi                                     &gnu_personality_handler_addr);
652*7fd79137SRobert Mustacchi             if (res != DW_DLV_OK) {
653*7fd79137SRobert Mustacchi                 _dwarf_error(dbg, error,
654*7fd79137SRobert Mustacchi                              DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
655*7fd79137SRobert Mustacchi                 return res;
656*7fd79137SRobert Mustacchi             }
657*7fd79137SRobert Mustacchi 
658*7fd79137SRobert Mustacchi 
659*7fd79137SRobert Mustacchi             frame_ptr += adlen;
660*7fd79137SRobert Mustacchi             break;
661*7fd79137SRobert Mustacchi         }
662*7fd79137SRobert Mustacchi     case aug_armcc:
663*7fd79137SRobert Mustacchi         break;
664*7fd79137SRobert Mustacchi     default:{
665*7fd79137SRobert Mustacchi             /* We do not understand the augmentation string. No
666*7fd79137SRobert Mustacchi                assumption can be made about any fields other than what
667*7fd79137SRobert Mustacchi                we have already read. */
668*7fd79137SRobert Mustacchi             frame_ptr = prefix->cf_start_addr +
669*7fd79137SRobert Mustacchi                 prefix->cf_length + prefix->cf_local_length_size
670*7fd79137SRobert Mustacchi                 + prefix->cf_local_extension_size;
671*7fd79137SRobert Mustacchi             /* FIX -- What are the values of data_alignment_factor,
672*7fd79137SRobert Mustacchi                code_alignement_factor, return_address_register and
673*7fd79137SRobert Mustacchi                instruction start? They were clearly uninitalized in the
674*7fd79137SRobert Mustacchi                previous version and I am leaving them the same way. */
675*7fd79137SRobert Mustacchi             break;
676*7fd79137SRobert Mustacchi         }
677*7fd79137SRobert Mustacchi     }                           /* End switch on augmentation type. */
678*7fd79137SRobert Mustacchi 
679*7fd79137SRobert Mustacchi     new_cie = (Dwarf_Cie) _dwarf_get_alloc(dbg, DW_DLA_CIE, 1);
680*7fd79137SRobert Mustacchi     if (new_cie == NULL) {
681*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
682*7fd79137SRobert Mustacchi         return (DW_DLV_ERROR);
683*7fd79137SRobert Mustacchi     }
684*7fd79137SRobert Mustacchi 
685*7fd79137SRobert Mustacchi     new_cie->ci_cie_version_number = version;
686*7fd79137SRobert Mustacchi     new_cie->ci_initial_table = NULL;
687*7fd79137SRobert Mustacchi     new_cie->ci_length = (Dwarf_Word) prefix->cf_length;
688*7fd79137SRobert Mustacchi     new_cie->ci_length_size = prefix->cf_local_length_size;
689*7fd79137SRobert Mustacchi     new_cie->ci_extension_size = prefix->cf_local_extension_size;
690*7fd79137SRobert Mustacchi     new_cie->ci_augmentation = (char *) augmentation;
691*7fd79137SRobert Mustacchi 
692*7fd79137SRobert Mustacchi     new_cie->ci_data_alignment_factor =
693*7fd79137SRobert Mustacchi         (Dwarf_Sbyte) data_alignment_factor;
694*7fd79137SRobert Mustacchi     new_cie->ci_code_alignment_factor =
695*7fd79137SRobert Mustacchi         (Dwarf_Small) code_alignment_factor;
696*7fd79137SRobert Mustacchi     new_cie->ci_return_address_register = return_address_register;
697*7fd79137SRobert Mustacchi     new_cie->ci_cie_start = prefix->cf_start_addr;
698*7fd79137SRobert Mustacchi     new_cie->ci_cie_instr_start = frame_ptr;
699*7fd79137SRobert Mustacchi     new_cie->ci_dbg = dbg;
700*7fd79137SRobert Mustacchi     new_cie->ci_augmentation_type = augt;
701*7fd79137SRobert Mustacchi     new_cie->ci_gnu_eh_augmentation_len = cie_aug_data_len;
702*7fd79137SRobert Mustacchi     new_cie->ci_gnu_eh_augmentation_bytes = cie_aug_data;
703*7fd79137SRobert Mustacchi     new_cie->ci_gnu_personality_handler_encoding =
704*7fd79137SRobert Mustacchi         gnu_personality_handler_encoding;
705*7fd79137SRobert Mustacchi     new_cie->ci_gnu_personality_handler_addr =
706*7fd79137SRobert Mustacchi         gnu_personality_handler_addr;
707*7fd79137SRobert Mustacchi     new_cie->ci_gnu_lsda_encoding = gnu_lsda_encoding;
708*7fd79137SRobert Mustacchi     new_cie->ci_gnu_fde_begin_encoding = gnu_fde_begin_encoding;
709*7fd79137SRobert Mustacchi 
710*7fd79137SRobert Mustacchi     new_cie->ci_index = cie_count;
711*7fd79137SRobert Mustacchi     new_cie->ci_section_ptr = prefix->cf_section_ptr;
712*7fd79137SRobert Mustacchi     /* The Following new in DWARF4 */
713*7fd79137SRobert Mustacchi     new_cie->ci_address_size = address_size;
714*7fd79137SRobert Mustacchi     new_cie->ci_segment_size = segment_size;
715*7fd79137SRobert Mustacchi     validate_length(dbg,new_cie,new_cie->ci_length,
716*7fd79137SRobert Mustacchi         new_cie->ci_length_size, new_cie->ci_extension_size,
717*7fd79137SRobert Mustacchi         new_cie->ci_section_ptr,
718*7fd79137SRobert Mustacchi         new_cie->ci_cie_start,"cie");
719*7fd79137SRobert Mustacchi 
720*7fd79137SRobert Mustacchi     *cie_ptr_out = new_cie;
721*7fd79137SRobert Mustacchi     return DW_DLV_OK;
722*7fd79137SRobert Mustacchi 
723*7fd79137SRobert Mustacchi }
724*7fd79137SRobert Mustacchi 
725*7fd79137SRobert Mustacchi 
726*7fd79137SRobert Mustacchi /* Internal function, not called by consumer code.
727*7fd79137SRobert Mustacchi    'prefix' has accumulated the info up thru the cie-id
728*7fd79137SRobert Mustacchi    and now we consume the rest and build a Dwarf_Fde_s structure.
729*7fd79137SRobert Mustacchi */
730*7fd79137SRobert Mustacchi 
731*7fd79137SRobert Mustacchi int
732*7fd79137SRobert Mustacchi dwarf_create_fde_from_after_start(Dwarf_Debug dbg,
733*7fd79137SRobert Mustacchi     struct cie_fde_prefix_s *prefix,
734*7fd79137SRobert Mustacchi     Dwarf_Small * section_pointer,
735*7fd79137SRobert Mustacchi     Dwarf_Small * frame_ptr,
736*7fd79137SRobert Mustacchi     int use_gnu_cie_calc,
737*7fd79137SRobert Mustacchi     Dwarf_Cie cie_ptr_in,
738*7fd79137SRobert Mustacchi     Dwarf_Fde * fde_ptr_out,
739*7fd79137SRobert Mustacchi     Dwarf_Error * error)
740*7fd79137SRobert Mustacchi {
741*7fd79137SRobert Mustacchi     Dwarf_Fde new_fde = 0;
742*7fd79137SRobert Mustacchi     Dwarf_Cie cieptr = cie_ptr_in;
743*7fd79137SRobert Mustacchi     Dwarf_Small *saved_frame_ptr = 0;
744*7fd79137SRobert Mustacchi 
745*7fd79137SRobert Mustacchi     Dwarf_Small *initloc = frame_ptr;
746*7fd79137SRobert Mustacchi     Dwarf_Signed offset_into_exception_tables
747*7fd79137SRobert Mustacchi         /* must be min dwarf_sfixed in size */
748*7fd79137SRobert Mustacchi         = (Dwarf_Signed) DW_DLX_NO_EH_OFFSET;
749*7fd79137SRobert Mustacchi     Dwarf_Small *fde_aug_data = 0;
750*7fd79137SRobert Mustacchi     Dwarf_Unsigned fde_aug_data_len = 0;
751*7fd79137SRobert Mustacchi     Dwarf_Addr cie_base_offset = prefix->cf_cie_id;
752*7fd79137SRobert Mustacchi     Dwarf_Addr initial_location = 0;    /* must be min de_pointer_size
753*7fd79137SRobert Mustacchi                                            bytes in size */
754*7fd79137SRobert Mustacchi     Dwarf_Addr address_range = 0;       /* must be min de_pointer_size
755*7fd79137SRobert Mustacchi                                            bytes in size */
756*7fd79137SRobert Mustacchi     Dwarf_Half address_size = cie_ptr_in->ci_address_size;
757*7fd79137SRobert Mustacchi 
758*7fd79137SRobert Mustacchi     enum Dwarf_augmentation_type augt = cieptr->ci_augmentation_type;
759*7fd79137SRobert Mustacchi 
760*7fd79137SRobert Mustacchi     if (augt == aug_gcc_eh_z) {
761*7fd79137SRobert Mustacchi         /* If z augmentation this is eh_frame, and initial_location and
762*7fd79137SRobert Mustacchi            address_range in the FDE are read according to the CIE
763*7fd79137SRobert Mustacchi            augmentation string instructions.  */
764*7fd79137SRobert Mustacchi 
765*7fd79137SRobert Mustacchi         {
766*7fd79137SRobert Mustacchi             Dwarf_Small *fp_updated = 0;
767*7fd79137SRobert Mustacchi             int res = read_encoded_ptr(dbg,
768*7fd79137SRobert Mustacchi                 section_pointer,
769*7fd79137SRobert Mustacchi                 frame_ptr,
770*7fd79137SRobert Mustacchi                 cieptr-> ci_gnu_fde_begin_encoding,
771*7fd79137SRobert Mustacchi                 address_size,
772*7fd79137SRobert Mustacchi                 &initial_location,
773*7fd79137SRobert Mustacchi                 &fp_updated);
774*7fd79137SRobert Mustacchi             if (res != DW_DLV_OK) {
775*7fd79137SRobert Mustacchi                 _dwarf_error(dbg, error,
776*7fd79137SRobert Mustacchi                              DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
777*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
778*7fd79137SRobert Mustacchi             }
779*7fd79137SRobert Mustacchi             frame_ptr = fp_updated;
780*7fd79137SRobert Mustacchi             /* For the address-range it makes no sense to be
781*7fd79137SRobert Mustacchi                pc-relative, so we turn it off with a section_pointer of
782*7fd79137SRobert Mustacchi                NULL. Masking off DW_EH_PE_pcrel from the
783*7fd79137SRobert Mustacchi                ci_gnu_fde_begin_encoding in this call would also work
784*7fd79137SRobert Mustacchi                to turn off DW_EH_PE_pcrel. */
785*7fd79137SRobert Mustacchi             res = read_encoded_ptr(dbg, (Dwarf_Small *) NULL,
786*7fd79137SRobert Mustacchi                                    frame_ptr,
787*7fd79137SRobert Mustacchi                                    cieptr->ci_gnu_fde_begin_encoding,
788*7fd79137SRobert Mustacchi                                    address_size,
789*7fd79137SRobert Mustacchi                                    &address_range, &fp_updated);
790*7fd79137SRobert Mustacchi             if (res != DW_DLV_OK) {
791*7fd79137SRobert Mustacchi                 _dwarf_error(dbg, error,
792*7fd79137SRobert Mustacchi                              DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
793*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
794*7fd79137SRobert Mustacchi             }
795*7fd79137SRobert Mustacchi             frame_ptr = fp_updated;
796*7fd79137SRobert Mustacchi         }
797*7fd79137SRobert Mustacchi         {
798*7fd79137SRobert Mustacchi             Dwarf_Unsigned adlen = 0;
799*7fd79137SRobert Mustacchi 
800*7fd79137SRobert Mustacchi             DECODE_LEB128_UWORD(frame_ptr, adlen);
801*7fd79137SRobert Mustacchi             fde_aug_data_len = adlen;
802*7fd79137SRobert Mustacchi             fde_aug_data = frame_ptr;
803*7fd79137SRobert Mustacchi             frame_ptr += adlen;
804*7fd79137SRobert Mustacchi         }
805*7fd79137SRobert Mustacchi 
806*7fd79137SRobert Mustacchi     } else {
807*7fd79137SRobert Mustacchi         READ_UNALIGNED(dbg, initial_location, Dwarf_Addr,
808*7fd79137SRobert Mustacchi                        frame_ptr, address_size);
809*7fd79137SRobert Mustacchi         frame_ptr += address_size;
810*7fd79137SRobert Mustacchi 
811*7fd79137SRobert Mustacchi         READ_UNALIGNED(dbg, address_range, Dwarf_Addr,
812*7fd79137SRobert Mustacchi                        frame_ptr, address_size);
813*7fd79137SRobert Mustacchi         frame_ptr += address_size;
814*7fd79137SRobert Mustacchi     }
815*7fd79137SRobert Mustacchi 
816*7fd79137SRobert Mustacchi 
817*7fd79137SRobert Mustacchi 
818*7fd79137SRobert Mustacchi 
819*7fd79137SRobert Mustacchi 
820*7fd79137SRobert Mustacchi     switch (augt) {
821*7fd79137SRobert Mustacchi     case aug_irix_mti_v1:
822*7fd79137SRobert Mustacchi     case aug_empty_string:
823*7fd79137SRobert Mustacchi         break;
824*7fd79137SRobert Mustacchi     case aug_irix_exception_table:{
825*7fd79137SRobert Mustacchi             Dwarf_Unsigned lreg = 0;
826*7fd79137SRobert Mustacchi             Dwarf_Word length_of_augmented_fields = 0;
827*7fd79137SRobert Mustacchi 
828*7fd79137SRobert Mustacchi             DECODE_LEB128_UWORD(frame_ptr, lreg);
829*7fd79137SRobert Mustacchi             length_of_augmented_fields = (Dwarf_Word) lreg;
830*7fd79137SRobert Mustacchi 
831*7fd79137SRobert Mustacchi             saved_frame_ptr = frame_ptr;
832*7fd79137SRobert Mustacchi             /* The first word is an offset into exception tables.
833*7fd79137SRobert Mustacchi                Defined as a 32bit offset even for CC -64. */
834*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, offset_into_exception_tables,
835*7fd79137SRobert Mustacchi                            Dwarf_Addr, frame_ptr, sizeof(Dwarf_sfixed));
836*7fd79137SRobert Mustacchi             SIGN_EXTEND(offset_into_exception_tables,
837*7fd79137SRobert Mustacchi                         sizeof(Dwarf_sfixed));
838*7fd79137SRobert Mustacchi             frame_ptr = saved_frame_ptr + length_of_augmented_fields;
839*7fd79137SRobert Mustacchi         }
840*7fd79137SRobert Mustacchi         break;
841*7fd79137SRobert Mustacchi     case aug_eh:{
842*7fd79137SRobert Mustacchi             Dwarf_Unsigned eh_table_value = 0;
843*7fd79137SRobert Mustacchi 
844*7fd79137SRobert Mustacchi             if (!use_gnu_cie_calc) {
845*7fd79137SRobert Mustacchi                 /* This should be impossible. */
846*7fd79137SRobert Mustacchi                 _dwarf_error(dbg, error,
847*7fd79137SRobert Mustacchi                              DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
848*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
849*7fd79137SRobert Mustacchi             }
850*7fd79137SRobert Mustacchi 
851*7fd79137SRobert Mustacchi             /* gnu eh fde case. we do not need to do anything */
852*7fd79137SRobert Mustacchi              /*REFERENCED*/     /* Not used in this instance of the
853*7fd79137SRobert Mustacchi                                    macro */
854*7fd79137SRobert Mustacchi                 READ_UNALIGNED(dbg, eh_table_value,
855*7fd79137SRobert Mustacchi                                Dwarf_Unsigned, frame_ptr,
856*7fd79137SRobert Mustacchi                                address_size);
857*7fd79137SRobert Mustacchi             frame_ptr += address_size;
858*7fd79137SRobert Mustacchi         }
859*7fd79137SRobert Mustacchi         break;
860*7fd79137SRobert Mustacchi 
861*7fd79137SRobert Mustacchi     case aug_gcc_eh_z:{
862*7fd79137SRobert Mustacchi             /* The Augmentation Data Length is here, followed by the
863*7fd79137SRobert Mustacchi                Augmentation Data bytes themselves. */
864*7fd79137SRobert Mustacchi         }
865*7fd79137SRobert Mustacchi         break;
866*7fd79137SRobert Mustacchi     case aug_armcc:
867*7fd79137SRobert Mustacchi         break;
868*7fd79137SRobert Mustacchi     case aug_past_last:
869*7fd79137SRobert Mustacchi         break;
870*7fd79137SRobert Mustacchi     case aug_unknown:
871*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_AUGMENTATION_UNKNOWN);
872*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
873*7fd79137SRobert Mustacchi     }                           /* End switch on augmentation type */
874*7fd79137SRobert Mustacchi     new_fde = (Dwarf_Fde) _dwarf_get_alloc(dbg, DW_DLA_FDE, 1);
875*7fd79137SRobert Mustacchi     if (new_fde == NULL) {
876*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
877*7fd79137SRobert Mustacchi         return (DW_DLV_ERROR);
878*7fd79137SRobert Mustacchi     }
879*7fd79137SRobert Mustacchi 
880*7fd79137SRobert Mustacchi     new_fde->fd_length = prefix->cf_length;
881*7fd79137SRobert Mustacchi     new_fde->fd_length_size = prefix->cf_local_length_size;
882*7fd79137SRobert Mustacchi     new_fde->fd_extension_size = prefix->cf_local_extension_size;
883*7fd79137SRobert Mustacchi     new_fde->fd_is_eh = use_gnu_cie_calc;
884*7fd79137SRobert Mustacchi     new_fde->fd_cie_offset = cie_base_offset;
885*7fd79137SRobert Mustacchi     new_fde->fd_cie_index = cieptr->ci_index;
886*7fd79137SRobert Mustacchi     new_fde->fd_cie = cieptr;
887*7fd79137SRobert Mustacchi     new_fde->fd_initial_location = initial_location;
888*7fd79137SRobert Mustacchi     new_fde->fd_initial_loc_pos = initloc;
889*7fd79137SRobert Mustacchi     new_fde->fd_address_range = address_range;
890*7fd79137SRobert Mustacchi     new_fde->fd_fde_start = prefix->cf_start_addr;
891*7fd79137SRobert Mustacchi     new_fde->fd_fde_instr_start = frame_ptr;
892*7fd79137SRobert Mustacchi     new_fde->fd_dbg = dbg;
893*7fd79137SRobert Mustacchi     new_fde->fd_offset_into_exception_tables =
894*7fd79137SRobert Mustacchi         offset_into_exception_tables;
895*7fd79137SRobert Mustacchi 
896*7fd79137SRobert Mustacchi     new_fde->fd_section_ptr = prefix->cf_section_ptr;
897*7fd79137SRobert Mustacchi     new_fde->fd_section_index = prefix->cf_section_index;
898*7fd79137SRobert Mustacchi     new_fde->fd_section_length = prefix->cf_section_length;
899*7fd79137SRobert Mustacchi 
900*7fd79137SRobert Mustacchi     new_fde->fd_gnu_eh_augmentation_bytes = fde_aug_data;
901*7fd79137SRobert Mustacchi     new_fde->fd_gnu_eh_augmentation_len = fde_aug_data_len;
902*7fd79137SRobert Mustacchi     validate_length(dbg,cieptr,new_fde->fd_length,
903*7fd79137SRobert Mustacchi         new_fde->fd_length_size, new_fde->fd_extension_size,
904*7fd79137SRobert Mustacchi         new_fde->fd_section_ptr,new_fde->fd_fde_start,"fde");
905*7fd79137SRobert Mustacchi 
906*7fd79137SRobert Mustacchi 
907*7fd79137SRobert Mustacchi     *fde_ptr_out = new_fde;
908*7fd79137SRobert Mustacchi     return DW_DLV_OK;
909*7fd79137SRobert Mustacchi }
910*7fd79137SRobert Mustacchi 
911*7fd79137SRobert Mustacchi /* called by qsort to compare FDE entries.
912*7fd79137SRobert Mustacchi    Consumer code expects the array of FDE pointers to be in address order.
913*7fd79137SRobert Mustacchi */
914*7fd79137SRobert Mustacchi static int
915*7fd79137SRobert Mustacchi qsort_compare(const void *elem1, const void *elem2)
916*7fd79137SRobert Mustacchi {
917*7fd79137SRobert Mustacchi     Dwarf_Fde fde1 = *(Dwarf_Fde *) elem1;
918*7fd79137SRobert Mustacchi     Dwarf_Fde fde2 = *(Dwarf_Fde *) elem2;
919*7fd79137SRobert Mustacchi     Dwarf_Addr addr1 = fde1->fd_initial_location;
920*7fd79137SRobert Mustacchi     Dwarf_Addr addr2 = fde2->fd_initial_location;
921*7fd79137SRobert Mustacchi 
922*7fd79137SRobert Mustacchi     if (addr1 < addr2) {
923*7fd79137SRobert Mustacchi         return -1;
924*7fd79137SRobert Mustacchi     } else if (addr1 > addr2) {
925*7fd79137SRobert Mustacchi         return 1;
926*7fd79137SRobert Mustacchi     }
927*7fd79137SRobert Mustacchi     return 0;
928*7fd79137SRobert Mustacchi }
929*7fd79137SRobert Mustacchi 
930*7fd79137SRobert Mustacchi 
931*7fd79137SRobert Mustacchi /* Read in the common cie/fde prefix, including reading
932*7fd79137SRobert Mustacchi  * the cie-value which shows which this is: cie or fde.
933*7fd79137SRobert Mustacchi  * */
934*7fd79137SRobert Mustacchi int
935*7fd79137SRobert Mustacchi dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,
936*7fd79137SRobert Mustacchi                           Dwarf_Small * frame_ptr_in,
937*7fd79137SRobert Mustacchi                           Dwarf_Small * section_ptr_in,
938*7fd79137SRobert Mustacchi                           Dwarf_Unsigned section_index_in,
939*7fd79137SRobert Mustacchi                           Dwarf_Unsigned section_length_in,
940*7fd79137SRobert Mustacchi                           struct cie_fde_prefix_s *data_out,
941*7fd79137SRobert Mustacchi                           Dwarf_Error * error)
942*7fd79137SRobert Mustacchi {
943*7fd79137SRobert Mustacchi     Dwarf_Unsigned length = 0;
944*7fd79137SRobert Mustacchi     int local_length_size = 0;
945*7fd79137SRobert Mustacchi     int local_extension_size = 0;
946*7fd79137SRobert Mustacchi     Dwarf_Small *frame_ptr = frame_ptr_in;
947*7fd79137SRobert Mustacchi     Dwarf_Small *cie_ptr_addr = 0;
948*7fd79137SRobert Mustacchi     Dwarf_Unsigned cie_id = 0;
949*7fd79137SRobert Mustacchi 
950*7fd79137SRobert Mustacchi     /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
951*7fd79137SRobert Mustacchi     READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
952*7fd79137SRobert Mustacchi                      frame_ptr, local_length_size,
953*7fd79137SRobert Mustacchi                      local_extension_size);
954*7fd79137SRobert Mustacchi 
955*7fd79137SRobert Mustacchi     if (length == 0) {
956*7fd79137SRobert Mustacchi         /* nul bytes at end of section, seen at end of egcs eh_frame
957*7fd79137SRobert Mustacchi            sections (in a.out). Take this as meaning no more CIE/FDE
958*7fd79137SRobert Mustacchi            data. We should be very close to end of section. */
959*7fd79137SRobert Mustacchi         return DW_DLV_NO_ENTRY;
960*7fd79137SRobert Mustacchi     }
961*7fd79137SRobert Mustacchi 
962*7fd79137SRobert Mustacchi     cie_ptr_addr = frame_ptr;
963*7fd79137SRobert Mustacchi     READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
964*7fd79137SRobert Mustacchi                    frame_ptr, local_length_size);
965*7fd79137SRobert Mustacchi     SIGN_EXTEND(cie_id, local_length_size);
966*7fd79137SRobert Mustacchi     frame_ptr += local_length_size;
967*7fd79137SRobert Mustacchi 
968*7fd79137SRobert Mustacchi     data_out->cf_start_addr = frame_ptr_in;
969*7fd79137SRobert Mustacchi     data_out->cf_addr_after_prefix = frame_ptr;
970*7fd79137SRobert Mustacchi 
971*7fd79137SRobert Mustacchi     data_out->cf_length = length;
972*7fd79137SRobert Mustacchi     data_out->cf_local_length_size = local_length_size;
973*7fd79137SRobert Mustacchi     data_out->cf_local_extension_size = local_extension_size;
974*7fd79137SRobert Mustacchi     data_out->cf_cie_id = cie_id;
975*7fd79137SRobert Mustacchi     data_out->cf_cie_id_addr = cie_ptr_addr;
976*7fd79137SRobert Mustacchi     data_out->cf_section_ptr = section_ptr_in;
977*7fd79137SRobert Mustacchi     data_out->cf_section_index = section_index_in;
978*7fd79137SRobert Mustacchi     data_out->cf_section_length = section_length_in;
979*7fd79137SRobert Mustacchi     return DW_DLV_OK;
980*7fd79137SRobert Mustacchi }
981*7fd79137SRobert Mustacchi 
982*7fd79137SRobert Mustacchi /* On various errors previously-allocated CIEs and FDEs
983*7fd79137SRobert Mustacchi    must be cleaned up.
984*7fd79137SRobert Mustacchi    This helps avoid leaks in case of errors.
985*7fd79137SRobert Mustacchi */
986*7fd79137SRobert Mustacchi static void
987*7fd79137SRobert Mustacchi dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,
988*7fd79137SRobert Mustacchi     Dwarf_Cie head_cie_ptr)
989*7fd79137SRobert Mustacchi {
990*7fd79137SRobert Mustacchi     Dwarf_Fde curfde = 0;
991*7fd79137SRobert Mustacchi     Dwarf_Cie curcie = 0;
992*7fd79137SRobert Mustacchi     Dwarf_Fde nextfde = 0;
993*7fd79137SRobert Mustacchi     Dwarf_Cie nextcie = 0;
994*7fd79137SRobert Mustacchi 
995*7fd79137SRobert Mustacchi     for (curfde = head_fde_ptr; curfde; curfde = nextfde) {
996*7fd79137SRobert Mustacchi         nextfde = curfde->fd_next;
997*7fd79137SRobert Mustacchi         dwarf_dealloc(curfde->fd_dbg, curfde, DW_DLA_FDE);
998*7fd79137SRobert Mustacchi     }
999*7fd79137SRobert Mustacchi     for (curcie = head_cie_ptr; curcie; curcie = nextcie) {
1000*7fd79137SRobert Mustacchi         Dwarf_Frame frame = curcie->ci_initial_table;
1001*7fd79137SRobert Mustacchi 
1002*7fd79137SRobert Mustacchi         nextcie = curcie->ci_next;
1003*7fd79137SRobert Mustacchi         if (frame)
1004*7fd79137SRobert Mustacchi             dwarf_dealloc(curcie->ci_dbg, frame, DW_DLA_FRAME);
1005*7fd79137SRobert Mustacchi         dwarf_dealloc(curcie->ci_dbg, curcie, DW_DLA_CIE);
1006*7fd79137SRobert Mustacchi     }
1007*7fd79137SRobert Mustacchi }
1008*7fd79137SRobert Mustacchi 
1009*7fd79137SRobert Mustacchi /* Find the cie whose id value is given: the id
1010*7fd79137SRobert Mustacchi  * value is, per DWARF2/3, an offset in the section.
1011*7fd79137SRobert Mustacchi  * For .debug_frame, zero is a legal offset. For
1012*7fd79137SRobert Mustacchi  * GNU .eh_frame it is not a legal offset.
1013*7fd79137SRobert Mustacchi  * 'cie_ptr' is a pointer into our section, not an offset. */
1014*7fd79137SRobert Mustacchi static int
1015*7fd79137SRobert Mustacchi dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,
1016*7fd79137SRobert Mustacchi                             Dwarf_Cie cur_cie_ptr,
1017*7fd79137SRobert Mustacchi                             Dwarf_Cie * cie_ptr_to_use_out,
1018*7fd79137SRobert Mustacchi                             Dwarf_Cie head_cie_ptr)
1019*7fd79137SRobert Mustacchi {
1020*7fd79137SRobert Mustacchi     Dwarf_Cie next = 0;
1021*7fd79137SRobert Mustacchi 
1022*7fd79137SRobert Mustacchi     if (cur_cie_ptr && cie_ptr == cur_cie_ptr->ci_cie_start) {
1023*7fd79137SRobert Mustacchi         /* Usually, we use the same cie again and again. */
1024*7fd79137SRobert Mustacchi         *cie_ptr_to_use_out = cur_cie_ptr;
1025*7fd79137SRobert Mustacchi         return DW_DLV_OK;
1026*7fd79137SRobert Mustacchi     }
1027*7fd79137SRobert Mustacchi     for (next = head_cie_ptr; next; next = next->ci_next) {
1028*7fd79137SRobert Mustacchi         if (cie_ptr == next->ci_cie_start) {
1029*7fd79137SRobert Mustacchi             *cie_ptr_to_use_out = next;
1030*7fd79137SRobert Mustacchi             return DW_DLV_OK;
1031*7fd79137SRobert Mustacchi         }
1032*7fd79137SRobert Mustacchi     }
1033*7fd79137SRobert Mustacchi     return DW_DLV_NO_ENTRY;
1034*7fd79137SRobert Mustacchi }
1035*7fd79137SRobert Mustacchi 
1036*7fd79137SRobert Mustacchi 
1037*7fd79137SRobert Mustacchi /* We have a valid cie_ptr_val that has not been
1038*7fd79137SRobert Mustacchi  * turned into an internal Cie yet. Do so now.
1039*7fd79137SRobert Mustacchi  * Returns DW_DLV_OK or DW_DLV_ERROR, never
1040*7fd79137SRobert Mustacchi  * DW_DLV_NO_ENTRY.
1041*7fd79137SRobert Mustacchi 
1042*7fd79137SRobert Mustacchi  'section_ptr'    - Points to first byte of section data.
1043*7fd79137SRobert Mustacchi  'section_length' - Length of the section, in bytes.
1044*7fd79137SRobert Mustacchi  'frame_ptr_end'  - Points 1-past last byte of section data.
1045*7fd79137SRobert Mustacchi  * */
1046*7fd79137SRobert Mustacchi static int
1047*7fd79137SRobert Mustacchi dwarf_create_cie_from_start(Dwarf_Debug dbg,
1048*7fd79137SRobert Mustacchi     Dwarf_Small * cie_ptr_val,
1049*7fd79137SRobert Mustacchi     Dwarf_Small * section_ptr,
1050*7fd79137SRobert Mustacchi     Dwarf_Unsigned section_index,
1051*7fd79137SRobert Mustacchi     Dwarf_Unsigned section_length,
1052*7fd79137SRobert Mustacchi     Dwarf_Small * frame_ptr_end,
1053*7fd79137SRobert Mustacchi     Dwarf_Unsigned cie_id_value,
1054*7fd79137SRobert Mustacchi     Dwarf_Unsigned cie_count,
1055*7fd79137SRobert Mustacchi     int use_gnu_cie_calc,
1056*7fd79137SRobert Mustacchi     Dwarf_Cie * cie_ptr_to_use_out,
1057*7fd79137SRobert Mustacchi     Dwarf_Error * error)
1058*7fd79137SRobert Mustacchi {
1059*7fd79137SRobert Mustacchi     struct cie_fde_prefix_s prefix;
1060*7fd79137SRobert Mustacchi     int res = DW_DLV_ERROR;
1061*7fd79137SRobert Mustacchi     Dwarf_Small *frame_ptr = cie_ptr_val;
1062*7fd79137SRobert Mustacchi 
1063*7fd79137SRobert Mustacchi     if (frame_ptr < section_ptr || frame_ptr > frame_ptr_end) {
1064*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
1065*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
1066*7fd79137SRobert Mustacchi     }
1067*7fd79137SRobert Mustacchi     /* First read in the 'common prefix' to figure out what * we are to
1068*7fd79137SRobert Mustacchi        do with this entry. If it is not a cie * we are in big trouble. */
1069*7fd79137SRobert Mustacchi     memset(&prefix, 0, sizeof(prefix));
1070*7fd79137SRobert Mustacchi     res = dwarf_read_cie_fde_prefix(dbg, frame_ptr, section_ptr,
1071*7fd79137SRobert Mustacchi         section_index, section_length,
1072*7fd79137SRobert Mustacchi         &prefix, error);
1073*7fd79137SRobert Mustacchi     if (res == DW_DLV_ERROR) {
1074*7fd79137SRobert Mustacchi         return res;
1075*7fd79137SRobert Mustacchi     }
1076*7fd79137SRobert Mustacchi     if (res == DW_DLV_NO_ENTRY) {
1077*7fd79137SRobert Mustacchi         /* error. */
1078*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
1079*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
1080*7fd79137SRobert Mustacchi 
1081*7fd79137SRobert Mustacchi     }
1082*7fd79137SRobert Mustacchi 
1083*7fd79137SRobert Mustacchi     if (prefix.cf_cie_id != cie_id_value) {
1084*7fd79137SRobert Mustacchi         _dwarf_error(dbg, error, DW_DLE_FRAME_CIE_DECODE_ERROR);
1085*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
1086*7fd79137SRobert Mustacchi     }
1087*7fd79137SRobert Mustacchi     frame_ptr = prefix.cf_addr_after_prefix;
1088*7fd79137SRobert Mustacchi     res = dwarf_create_cie_from_after_start(dbg,
1089*7fd79137SRobert Mustacchi         &prefix,
1090*7fd79137SRobert Mustacchi         section_ptr,
1091*7fd79137SRobert Mustacchi         frame_ptr,
1092*7fd79137SRobert Mustacchi         cie_count,
1093*7fd79137SRobert Mustacchi         use_gnu_cie_calc,
1094*7fd79137SRobert Mustacchi         cie_ptr_to_use_out, error);
1095*7fd79137SRobert Mustacchi     return res;
1096*7fd79137SRobert Mustacchi 
1097*7fd79137SRobert Mustacchi }
1098*7fd79137SRobert Mustacchi 
1099*7fd79137SRobert Mustacchi 
1100*7fd79137SRobert Mustacchi /* This is for gnu eh frames, the 'z' case.
1101*7fd79137SRobert Mustacchi    We find the letter involved
1102*7fd79137SRobert Mustacchi    Return the augmentation character and, if applicable,
1103*7fd79137SRobert Mustacchi    the personality routine address.
1104*7fd79137SRobert Mustacchi 
1105*7fd79137SRobert Mustacchi    personality_routine_out -
1106*7fd79137SRobert Mustacchi         if 'P' is augchar, is personality handler addr.
1107*7fd79137SRobert Mustacchi         Otherwise is not set.
1108*7fd79137SRobert Mustacchi    aug_data  - if 'P' points  to data space of the
1109*7fd79137SRobert Mustacchi    aug_data_len - length of areas aug_data points to.
1110*7fd79137SRobert Mustacchi 
1111*7fd79137SRobert Mustacchi */
1112*7fd79137SRobert Mustacchi #if 0
1113*7fd79137SRobert Mustacchi /* For debugging only. */
1114*7fd79137SRobert Mustacchi void
1115*7fd79137SRobert Mustacchi dump_bytes(Dwarf_Small * start, long len)
1116*7fd79137SRobert Mustacchi {
1117*7fd79137SRobert Mustacchi     Dwarf_Small *end = start + len;
1118*7fd79137SRobert Mustacchi     Dwarf_Small *cur = start;
1119*7fd79137SRobert Mustacchi 
1120*7fd79137SRobert Mustacchi     for (; cur < end; cur++) {
1121*7fd79137SRobert Mustacchi         printf(" byte %d, data %02x\n", (int) (cur - start), *cur);
1122*7fd79137SRobert Mustacchi     }
1123*7fd79137SRobert Mustacchi 
1124*7fd79137SRobert Mustacchi }
1125*7fd79137SRobert Mustacchi #endif
1126*7fd79137SRobert Mustacchi static int
1127*7fd79137SRobert Mustacchi gnu_aug_encodings(Dwarf_Debug dbg, char *augmentation,
1128*7fd79137SRobert Mustacchi     Dwarf_Small * aug_data, Dwarf_Unsigned aug_data_len,
1129*7fd79137SRobert Mustacchi     Dwarf_Half address_size,
1130*7fd79137SRobert Mustacchi     unsigned char *pers_hand_enc_out,
1131*7fd79137SRobert Mustacchi     unsigned char *lsda_enc_out,
1132*7fd79137SRobert Mustacchi     unsigned char *fde_begin_enc_out,
1133*7fd79137SRobert Mustacchi     Dwarf_Addr * gnu_pers_addr_out)
1134*7fd79137SRobert Mustacchi {
1135*7fd79137SRobert Mustacchi     char *nc = 0;
1136*7fd79137SRobert Mustacchi     Dwarf_Small *cur_aug_p = aug_data;
1137*7fd79137SRobert Mustacchi     Dwarf_Small *end_aug_p = aug_data + aug_data_len;
1138*7fd79137SRobert Mustacchi 
1139*7fd79137SRobert Mustacchi     for (nc = augmentation; *nc; ++nc) {
1140*7fd79137SRobert Mustacchi         char c = *nc;
1141*7fd79137SRobert Mustacchi 
1142*7fd79137SRobert Mustacchi         switch (c) {
1143*7fd79137SRobert Mustacchi         case 'z':
1144*7fd79137SRobert Mustacchi             /* Means that the augmentation data is present. */
1145*7fd79137SRobert Mustacchi             continue;
1146*7fd79137SRobert Mustacchi 
1147*7fd79137SRobert Mustacchi         case 'S':
1148*7fd79137SRobert Mustacchi             /* Indicates this is a signal stack frame.  Debuggers have to do
1149*7fd79137SRobert Mustacchi                special handling.  We don't need to do more than print this flag at
1150*7fd79137SRobert Mustacchi                the right time, though (see dwarfdump where it prints the augmentation
1151*7fd79137SRobert Mustacchi                string).
1152*7fd79137SRobert Mustacchi                A signal stack frame (in some OS's) can only be
1153*7fd79137SRobert Mustacchi                unwound (backtraced) by knowing it is a signal stack frame
1154*7fd79137SRobert Mustacchi                (perhaps by noticing the name of the function for the stack frame
1155*7fd79137SRobert Mustacchi                if the name can be found somehow) and figuring
1156*7fd79137SRobert Mustacchi                out (or knowing) how the kernel and libc pushed a structure
1157*7fd79137SRobert Mustacchi                onto the stack and loading registers from that structure.
1158*7fd79137SRobert Mustacchi                Totally different from normal stack unwinding.
1159*7fd79137SRobert Mustacchi                This flag gives an unwinder a big leg up by decoupling the
1160*7fd79137SRobert Mustacchi                'hint: this is a stack frame' from knowledge like
1161*7fd79137SRobert Mustacchi                the function name (the name might be unavailable at unwind time).
1162*7fd79137SRobert Mustacchi             */
1163*7fd79137SRobert Mustacchi             break;
1164*7fd79137SRobert Mustacchi 
1165*7fd79137SRobert Mustacchi         case 'L':
1166*7fd79137SRobert Mustacchi             if (cur_aug_p > end_aug_p) {
1167*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
1168*7fd79137SRobert Mustacchi             }
1169*7fd79137SRobert Mustacchi             *lsda_enc_out = *(unsigned char *) cur_aug_p;
1170*7fd79137SRobert Mustacchi             ++cur_aug_p;
1171*7fd79137SRobert Mustacchi             break;
1172*7fd79137SRobert Mustacchi         case 'R':
1173*7fd79137SRobert Mustacchi             /* Followed by a one byte argument giving the
1174*7fd79137SRobert Mustacchi                pointer encoding for the address pointers in the fde. */
1175*7fd79137SRobert Mustacchi             if (cur_aug_p >= end_aug_p) {
1176*7fd79137SRobert Mustacchi                 return DW_DLV_ERROR;
1177*7fd79137SRobert Mustacchi             }
1178*7fd79137SRobert Mustacchi             *fde_begin_enc_out = *(unsigned char *) cur_aug_p;
1179*7fd79137SRobert Mustacchi             ++cur_aug_p;
1180*7fd79137SRobert Mustacchi             break;
1181*7fd79137SRobert Mustacchi         case 'P':{
1182*7fd79137SRobert Mustacchi                 int res = DW_DLV_ERROR;
1183*7fd79137SRobert Mustacchi                 Dwarf_Small *updated_aug_p = 0;
1184*7fd79137SRobert Mustacchi                 unsigned char encoding = 0;
1185*7fd79137SRobert Mustacchi 
1186*7fd79137SRobert Mustacchi                 if (cur_aug_p >= end_aug_p) {
1187*7fd79137SRobert Mustacchi                     return DW_DLV_ERROR;
1188*7fd79137SRobert Mustacchi                 }
1189*7fd79137SRobert Mustacchi                 encoding = *(unsigned char *) cur_aug_p;
1190*7fd79137SRobert Mustacchi                 *pers_hand_enc_out = encoding;
1191*7fd79137SRobert Mustacchi                 ++cur_aug_p;
1192*7fd79137SRobert Mustacchi                 if (cur_aug_p > end_aug_p) {
1193*7fd79137SRobert Mustacchi                     return DW_DLV_ERROR;
1194*7fd79137SRobert Mustacchi                 }
1195*7fd79137SRobert Mustacchi                 /* DW_EH_PE_pcrel makes no sense here, so we turn it
1196*7fd79137SRobert Mustacchi                    off via a section pointer of NULL. */
1197*7fd79137SRobert Mustacchi                 res = read_encoded_ptr(dbg,
1198*7fd79137SRobert Mustacchi                                        (Dwarf_Small *) NULL,
1199*7fd79137SRobert Mustacchi                                        cur_aug_p,
1200*7fd79137SRobert Mustacchi                                        encoding,
1201*7fd79137SRobert Mustacchi                                        address_size,
1202*7fd79137SRobert Mustacchi                                        gnu_pers_addr_out,
1203*7fd79137SRobert Mustacchi                                        &updated_aug_p);
1204*7fd79137SRobert Mustacchi                 if (res != DW_DLV_OK) {
1205*7fd79137SRobert Mustacchi                     return res;
1206*7fd79137SRobert Mustacchi                 }
1207*7fd79137SRobert Mustacchi                 cur_aug_p = updated_aug_p;
1208*7fd79137SRobert Mustacchi                 if (cur_aug_p > end_aug_p) {
1209*7fd79137SRobert Mustacchi                     return DW_DLV_ERROR;
1210*7fd79137SRobert Mustacchi                 }
1211*7fd79137SRobert Mustacchi             }
1212*7fd79137SRobert Mustacchi             break;
1213*7fd79137SRobert Mustacchi         default:
1214*7fd79137SRobert Mustacchi             return DW_DLV_ERROR;
1215*7fd79137SRobert Mustacchi 
1216*7fd79137SRobert Mustacchi         }
1217*7fd79137SRobert Mustacchi     }
1218*7fd79137SRobert Mustacchi 
1219*7fd79137SRobert Mustacchi     return DW_DLV_OK;
1220*7fd79137SRobert Mustacchi }
1221*7fd79137SRobert Mustacchi 
1222*7fd79137SRobert Mustacchi /* Given augmentation character (the encoding) giving the
1223*7fd79137SRobert Mustacchi address format, read the address from input_field
1224*7fd79137SRobert Mustacchi and return an incremented value 1 past the input bytes of the
1225*7fd79137SRobert Mustacchi address.
1226*7fd79137SRobert Mustacchi Push the address read back thru the *addr pointer.
1227*7fd79137SRobert Mustacchi See LSB (Linux Standar Base)  exception handling documents.
1228*7fd79137SRobert Mustacchi */
1229*7fd79137SRobert Mustacchi static int
1230*7fd79137SRobert Mustacchi read_encoded_ptr(Dwarf_Debug dbg,
1231*7fd79137SRobert Mustacchi     Dwarf_Small * section_pointer,
1232*7fd79137SRobert Mustacchi     Dwarf_Small * input_field,
1233*7fd79137SRobert Mustacchi     int gnu_encoding,
1234*7fd79137SRobert Mustacchi     Dwarf_Half address_size,
1235*7fd79137SRobert Mustacchi     Dwarf_Unsigned * addr,
1236*7fd79137SRobert Mustacchi     Dwarf_Small ** input_field_updated)
1237*7fd79137SRobert Mustacchi {
1238*7fd79137SRobert Mustacchi     Dwarf_Word length = 0;
1239*7fd79137SRobert Mustacchi     int value_type = gnu_encoding & 0xf;
1240*7fd79137SRobert Mustacchi     Dwarf_Small *input_field_original = input_field;
1241*7fd79137SRobert Mustacchi 
1242*7fd79137SRobert Mustacchi     if (gnu_encoding == 0xff) {
1243*7fd79137SRobert Mustacchi         /* There is no data here. */
1244*7fd79137SRobert Mustacchi 
1245*7fd79137SRobert Mustacchi         *addr = 0;
1246*7fd79137SRobert Mustacchi         *input_field_updated = input_field;
1247*7fd79137SRobert Mustacchi         /* Should we return DW_DLV_NO_ENTRY? */
1248*7fd79137SRobert Mustacchi         return DW_DLV_OK;
1249*7fd79137SRobert Mustacchi     }
1250*7fd79137SRobert Mustacchi     switch (value_type) {
1251*7fd79137SRobert Mustacchi     case DW_EH_PE_absptr:{
1252*7fd79137SRobert Mustacchi             /* value_type is zero. Treat as pointer size of the object.
1253*7fd79137SRobert Mustacchi              */
1254*7fd79137SRobert Mustacchi             Dwarf_Unsigned ret_value = 0;
1255*7fd79137SRobert Mustacchi 
1256*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
1257*7fd79137SRobert Mustacchi                            input_field, address_size);
1258*7fd79137SRobert Mustacchi             *addr = ret_value;
1259*7fd79137SRobert Mustacchi             *input_field_updated = input_field + address_size;
1260*7fd79137SRobert Mustacchi         }
1261*7fd79137SRobert Mustacchi         break;
1262*7fd79137SRobert Mustacchi     case DW_EH_PE_uleb128:{
1263*7fd79137SRobert Mustacchi             Dwarf_Unsigned val = _dwarf_decode_u_leb128(input_field,
1264*7fd79137SRobert Mustacchi                                                         &length);
1265*7fd79137SRobert Mustacchi 
1266*7fd79137SRobert Mustacchi             *addr = val;
1267*7fd79137SRobert Mustacchi             *input_field_updated = input_field + length;
1268*7fd79137SRobert Mustacchi         }
1269*7fd79137SRobert Mustacchi         break;
1270*7fd79137SRobert Mustacchi     case DW_EH_PE_udata2:{
1271*7fd79137SRobert Mustacchi             Dwarf_Unsigned ret_value = 0;
1272*7fd79137SRobert Mustacchi 
1273*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
1274*7fd79137SRobert Mustacchi                            input_field, 2);
1275*7fd79137SRobert Mustacchi             *addr = ret_value;
1276*7fd79137SRobert Mustacchi             *input_field_updated = input_field + 2;
1277*7fd79137SRobert Mustacchi         }
1278*7fd79137SRobert Mustacchi         break;
1279*7fd79137SRobert Mustacchi 
1280*7fd79137SRobert Mustacchi     case DW_EH_PE_udata4:{
1281*7fd79137SRobert Mustacchi 
1282*7fd79137SRobert Mustacchi             Dwarf_Unsigned ret_value = 0;
1283*7fd79137SRobert Mustacchi 
1284*7fd79137SRobert Mustacchi             /* ASSERT: sizeof(Dwarf_ufixed) == 4 */
1285*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
1286*7fd79137SRobert Mustacchi                            input_field, sizeof(Dwarf_ufixed));
1287*7fd79137SRobert Mustacchi             *addr = ret_value;
1288*7fd79137SRobert Mustacchi             *input_field_updated = input_field + sizeof(Dwarf_ufixed);
1289*7fd79137SRobert Mustacchi         }
1290*7fd79137SRobert Mustacchi         break;
1291*7fd79137SRobert Mustacchi 
1292*7fd79137SRobert Mustacchi     case DW_EH_PE_udata8:{
1293*7fd79137SRobert Mustacchi             Dwarf_Unsigned ret_value = 0;
1294*7fd79137SRobert Mustacchi 
1295*7fd79137SRobert Mustacchi             /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
1296*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, ret_value, Dwarf_Unsigned,
1297*7fd79137SRobert Mustacchi                            input_field, sizeof(Dwarf_Unsigned));
1298*7fd79137SRobert Mustacchi             *addr = ret_value;
1299*7fd79137SRobert Mustacchi             *input_field_updated = input_field + sizeof(Dwarf_Unsigned);
1300*7fd79137SRobert Mustacchi         }
1301*7fd79137SRobert Mustacchi         break;
1302*7fd79137SRobert Mustacchi 
1303*7fd79137SRobert Mustacchi     case DW_EH_PE_sleb128:{
1304*7fd79137SRobert Mustacchi             Dwarf_Signed val = _dwarf_decode_s_leb128(input_field,
1305*7fd79137SRobert Mustacchi                                                       &length);
1306*7fd79137SRobert Mustacchi 
1307*7fd79137SRobert Mustacchi             *addr = (Dwarf_Unsigned) val;
1308*7fd79137SRobert Mustacchi             *input_field_updated = input_field + length;
1309*7fd79137SRobert Mustacchi         }
1310*7fd79137SRobert Mustacchi         break;
1311*7fd79137SRobert Mustacchi     case DW_EH_PE_sdata2:{
1312*7fd79137SRobert Mustacchi             Dwarf_Unsigned val = 0;
1313*7fd79137SRobert Mustacchi 
1314*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, val, Dwarf_Unsigned, input_field, 2);
1315*7fd79137SRobert Mustacchi             SIGN_EXTEND(val, 2);
1316*7fd79137SRobert Mustacchi             *addr = (Dwarf_Unsigned) val;
1317*7fd79137SRobert Mustacchi             *input_field_updated = input_field + 2;
1318*7fd79137SRobert Mustacchi         }
1319*7fd79137SRobert Mustacchi         break;
1320*7fd79137SRobert Mustacchi 
1321*7fd79137SRobert Mustacchi     case DW_EH_PE_sdata4:{
1322*7fd79137SRobert Mustacchi             Dwarf_Unsigned val = 0;
1323*7fd79137SRobert Mustacchi 
1324*7fd79137SRobert Mustacchi             /* ASSERT: sizeof(Dwarf_ufixed) == 4 */
1325*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, val,
1326*7fd79137SRobert Mustacchi                            Dwarf_Unsigned, input_field,
1327*7fd79137SRobert Mustacchi                            sizeof(Dwarf_ufixed));
1328*7fd79137SRobert Mustacchi             SIGN_EXTEND(val, sizeof(Dwarf_ufixed));
1329*7fd79137SRobert Mustacchi             *addr = (Dwarf_Unsigned) val;
1330*7fd79137SRobert Mustacchi             *input_field_updated = input_field + sizeof(Dwarf_ufixed);
1331*7fd79137SRobert Mustacchi         }
1332*7fd79137SRobert Mustacchi         break;
1333*7fd79137SRobert Mustacchi     case DW_EH_PE_sdata8:{
1334*7fd79137SRobert Mustacchi             Dwarf_Unsigned val = 0;
1335*7fd79137SRobert Mustacchi 
1336*7fd79137SRobert Mustacchi             /* ASSERT: sizeof(Dwarf_Unsigned) == 8 */
1337*7fd79137SRobert Mustacchi             READ_UNALIGNED(dbg, val,
1338*7fd79137SRobert Mustacchi                            Dwarf_Unsigned, input_field,
1339*7fd79137SRobert Mustacchi                            sizeof(Dwarf_Unsigned));
1340*7fd79137SRobert Mustacchi             *addr = (Dwarf_Unsigned) val;
1341*7fd79137SRobert Mustacchi             *input_field_updated = input_field + sizeof(Dwarf_Unsigned);
1342*7fd79137SRobert Mustacchi         }
1343*7fd79137SRobert Mustacchi         break;
1344*7fd79137SRobert Mustacchi     default:
1345*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
1346*7fd79137SRobert Mustacchi 
1347*7fd79137SRobert Mustacchi     };
1348*7fd79137SRobert Mustacchi     /* The ELF ABI for gnu does not document the meaning of
1349*7fd79137SRobert Mustacchi        DW_EH_PE_pcrel, which is awkward.  It apparently means the value
1350*7fd79137SRobert Mustacchi        we got above is pc-relative (meaning section-relative), so we
1351*7fd79137SRobert Mustacchi        adjust the value. Section_pointer may be null if it is known
1352*7fd79137SRobert Mustacchi        DW_EH_PE_pcrel cannot apply, such as for .debug_frame or for an
1353*7fd79137SRobert Mustacchi        address-range value. */
1354*7fd79137SRobert Mustacchi     if (section_pointer && ((gnu_encoding & 0x70) == DW_EH_PE_pcrel)) {
1355*7fd79137SRobert Mustacchi         /* Address (*addr) above is pc relative with respect to a
1356*7fd79137SRobert Mustacchi            section. Add to the offset the base address (from elf) of
1357*7fd79137SRobert Mustacchi            section and the distance of the field we are reading from
1358*7fd79137SRobert Mustacchi            the section-beginning to get the actual address. */
1359*7fd79137SRobert Mustacchi         /* ASSERT: input_field_original >= section_pointer */
1360*7fd79137SRobert Mustacchi         Dwarf_Unsigned distance =
1361*7fd79137SRobert Mustacchi             input_field_original - section_pointer;
1362*7fd79137SRobert Mustacchi         *addr += dbg->de_debug_frame_eh_gnu.dss_addr + distance;
1363*7fd79137SRobert Mustacchi     }
1364*7fd79137SRobert Mustacchi 
1365*7fd79137SRobert Mustacchi     return DW_DLV_OK;
1366*7fd79137SRobert Mustacchi }
1367*7fd79137SRobert Mustacchi 
1368*7fd79137SRobert Mustacchi 
1369*7fd79137SRobert Mustacchi 
1370*7fd79137SRobert Mustacchi 
1371*7fd79137SRobert Mustacchi /*
1372*7fd79137SRobert Mustacchi         All augmentation string checking done here now.
1373*7fd79137SRobert Mustacchi 
1374*7fd79137SRobert Mustacchi         For .eh_frame, gcc from 3.3 uses the z style, earlier used
1375*7fd79137SRobert Mustacchi         only "eh" as augmentation.  We don't yet handle
1376*7fd79137SRobert Mustacchi         decoding .eh_frame with the z style extensions like L P.
1377*7fd79137SRobert Mustacchi 
1378*7fd79137SRobert Mustacchi         These are nasty heuristics, but then that's life
1379*7fd79137SRobert Mustacchi         as augmentations are implementation specific.
1380*7fd79137SRobert Mustacchi */
1381*7fd79137SRobert Mustacchi /* ARGSUSED */
1382*7fd79137SRobert Mustacchi enum Dwarf_augmentation_type
1383*7fd79137SRobert Mustacchi _dwarf_get_augmentation_type(Dwarf_Debug dbg,
1384*7fd79137SRobert Mustacchi     Dwarf_Small * augmentation_string,
1385*7fd79137SRobert Mustacchi     int is_gcc_eh_frame)
1386*7fd79137SRobert Mustacchi {
1387*7fd79137SRobert Mustacchi     enum Dwarf_augmentation_type t = aug_unknown;
1388*7fd79137SRobert Mustacchi     char *ag_string = (char *) augmentation_string;
1389*7fd79137SRobert Mustacchi 
1390*7fd79137SRobert Mustacchi     if (ag_string[0] == 0) {
1391*7fd79137SRobert Mustacchi         /* Empty string. We'll just guess that we know what this means:
1392*7fd79137SRobert Mustacchi            standard dwarf2/3 with no implementation-defined fields.  */
1393*7fd79137SRobert Mustacchi         t = aug_empty_string;
1394*7fd79137SRobert Mustacchi     } else if (strcmp(ag_string, DW_DEBUG_FRAME_AUGMENTER_STRING) == 0) {
1395*7fd79137SRobert Mustacchi         /* The string is "mti v1". Used internally at SGI, probably
1396*7fd79137SRobert Mustacchi            never shipped. Replaced by "z". Treat like 'nothing
1397*7fd79137SRobert Mustacchi            special'.  */
1398*7fd79137SRobert Mustacchi         t = aug_irix_mti_v1;
1399*7fd79137SRobert Mustacchi     } else if (ag_string[0] == 'z') {
1400*7fd79137SRobert Mustacchi         /* If it's IRIX cc, z means aug_irix_exception_table. z1 z2
1401*7fd79137SRobert Mustacchi            were designed as for IRIX CC, but never implemented */
1402*7fd79137SRobert Mustacchi         /* If it's gcc, z may be any of several things. "z" or z
1403*7fd79137SRobert Mustacchi            followed optionally followed by one or more of L R P, each
1404*7fd79137SRobert Mustacchi            of which means a value may be present. Should be in eh_frame
1405*7fd79137SRobert Mustacchi            only, I think. */
1406*7fd79137SRobert Mustacchi         if (is_gcc_eh_frame) {
1407*7fd79137SRobert Mustacchi             t = aug_gcc_eh_z;
1408*7fd79137SRobert Mustacchi         } else if (ag_string[1] == 0) {
1409*7fd79137SRobert Mustacchi             /* This is the normal IRIX C++ case, where there is an
1410*7fd79137SRobert Mustacchi                offset into a table in each fde. The table being for
1411*7fd79137SRobert Mustacchi                IRIX CC exception handling.  */
1412*7fd79137SRobert Mustacchi             /* DW_CIE_AUGMENTER_STRING_V0 "z" */
1413*7fd79137SRobert Mustacchi             t = aug_irix_exception_table;
1414*7fd79137SRobert Mustacchi         }                       /* Else unknown. */
1415*7fd79137SRobert Mustacchi     } else if (strncmp(ag_string, "eh", 2) == 0) {
1416*7fd79137SRobert Mustacchi         /* gcc .eh_frame augmentation for egcs and gcc 2.x, at least
1417*7fd79137SRobert Mustacchi            for x86. */
1418*7fd79137SRobert Mustacchi         t = aug_eh;
1419*7fd79137SRobert Mustacchi     } else if (strcmp(ag_string, "armcc+") == 0) {
1420*7fd79137SRobert Mustacchi         /* Arm  uses this string to mean a bug in
1421*7fd79137SRobert Mustacchi            in Arm compilers was fixed, changing to the standard
1422*7fd79137SRobert Mustacchi            calculation of the CFA.  See
1423*7fd79137SRobert Mustacchi            http://sourceware.org/ml/gdb-patches/2006-12/msg00249.html
1424*7fd79137SRobert Mustacchi            for details. */
1425*7fd79137SRobert Mustacchi         t = aug_armcc;
1426*7fd79137SRobert Mustacchi     } else {
1427*7fd79137SRobert Mustacchi 
1428*7fd79137SRobert Mustacchi     }
1429*7fd79137SRobert Mustacchi     return t;
1430*7fd79137SRobert Mustacchi }
1431*7fd79137SRobert Mustacchi 
1432*7fd79137SRobert Mustacchi /* Using augmentation, and version
1433*7fd79137SRobert Mustacchi    read in the augmentation data for GNU eh.
1434*7fd79137SRobert Mustacchi 
1435*7fd79137SRobert Mustacchi    Return DW_DLV_OK if we succeeded,
1436*7fd79137SRobert Mustacchi    DW_DLV_ERR if we fail.
1437*7fd79137SRobert Mustacchi 
1438*7fd79137SRobert Mustacchi    On success, update  'size_of_augmentation_data' with
1439*7fd79137SRobert Mustacchi    the length of the fields that are part of augmentation (so the
1440*7fd79137SRobert Mustacchi    caller can increment frame_ptr appropriately).
1441*7fd79137SRobert Mustacchi 
1442*7fd79137SRobert Mustacchi    'frame_ptr' points within section.
1443*7fd79137SRobert Mustacchi    'section_pointer' points to section base address in memory.
1444*7fd79137SRobert Mustacchi */
1445*7fd79137SRobert Mustacchi /* ARGSUSED */
1446*7fd79137SRobert Mustacchi static int
1447*7fd79137SRobert Mustacchi get_gcc_eh_augmentation(Dwarf_Debug dbg, Dwarf_Small * frame_ptr,
1448*7fd79137SRobert Mustacchi     unsigned long *size_of_augmentation_data,
1449*7fd79137SRobert Mustacchi     enum Dwarf_augmentation_type augtype,
1450*7fd79137SRobert Mustacchi     Dwarf_Small * section_pointer,
1451*7fd79137SRobert Mustacchi     Dwarf_Small * fde_eh_encoding_out,
1452*7fd79137SRobert Mustacchi     char *augmentation)
1453*7fd79137SRobert Mustacchi {
1454*7fd79137SRobert Mustacchi     char *suffix = 0;
1455*7fd79137SRobert Mustacchi     unsigned long augdata_size = 0;
1456*7fd79137SRobert Mustacchi 
1457*7fd79137SRobert Mustacchi     if (augtype == aug_gcc_eh_z) {
1458*7fd79137SRobert Mustacchi         /* Has leading 'z'. */
1459*7fd79137SRobert Mustacchi         Dwarf_Word leb128_length = 0;
1460*7fd79137SRobert Mustacchi 
1461*7fd79137SRobert Mustacchi         /* Dwarf_Unsigned eh_value = */
1462*7fd79137SRobert Mustacchi         _dwarf_decode_u_leb128(frame_ptr, &leb128_length);
1463*7fd79137SRobert Mustacchi         augdata_size += leb128_length;
1464*7fd79137SRobert Mustacchi         frame_ptr += leb128_length;
1465*7fd79137SRobert Mustacchi         suffix = augmentation + 1;
1466*7fd79137SRobert Mustacchi     } else {
1467*7fd79137SRobert Mustacchi         /* Prefix is 'eh'.  As in gcc 3.2. No suffix present
1468*7fd79137SRobert Mustacchi            apparently. */
1469*7fd79137SRobert Mustacchi         suffix = augmentation + 2;
1470*7fd79137SRobert Mustacchi     }
1471*7fd79137SRobert Mustacchi     for (; *suffix; ++suffix) {
1472*7fd79137SRobert Mustacchi         /* We have no idea what this is as yet. Some extensions beyond
1473*7fd79137SRobert Mustacchi            dwarf exist which we do not yet handle. */
1474*7fd79137SRobert Mustacchi         return DW_DLV_ERROR;
1475*7fd79137SRobert Mustacchi 
1476*7fd79137SRobert Mustacchi     }
1477*7fd79137SRobert Mustacchi 
1478*7fd79137SRobert Mustacchi     *size_of_augmentation_data = augdata_size;
1479*7fd79137SRobert Mustacchi     return DW_DLV_OK;
1480*7fd79137SRobert Mustacchi }
1481*7fd79137SRobert Mustacchi 
1482*7fd79137SRobert Mustacchi 
1483*7fd79137SRobert Mustacchi /* Make the 'cie_id_addr' consistent across .debug_frame and .eh_frame.
1484*7fd79137SRobert Mustacchi    Calculate a pointer into section bytes given a cie_id, which is
1485*7fd79137SRobert Mustacchi    trivial for .debug_frame, but a bit more work for .eh_frame.
1486*7fd79137SRobert Mustacchi */
1487*7fd79137SRobert Mustacchi static Dwarf_Small *
1488*7fd79137SRobert Mustacchi get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,
1489*7fd79137SRobert Mustacchi     int use_gnu_cie_calc,
1490*7fd79137SRobert Mustacchi     Dwarf_Small * section_ptr,
1491*7fd79137SRobert Mustacchi     Dwarf_Small * cie_id_addr)
1492*7fd79137SRobert Mustacchi {
1493*7fd79137SRobert Mustacchi     Dwarf_Small *cieptr = 0;
1494*7fd79137SRobert Mustacchi 
1495*7fd79137SRobert Mustacchi     if (use_gnu_cie_calc) {
1496*7fd79137SRobert Mustacchi         /* cie_id value is offset, in section, of the cie_id itself, to
1497*7fd79137SRobert Mustacchi            use vm ptr of the value, less the value, to get to the cie
1498*7fd79137SRobert Mustacchi            itself. In addition, munge *cie_id_addr to look *as if* it
1499*7fd79137SRobert Mustacchi            was from real dwarf. */
1500*7fd79137SRobert Mustacchi         cieptr = (Dwarf_Small *)(uintptr_t)
1501*7fd79137SRobert Mustacchi           ((Dwarf_Unsigned)(uintptr_t)cie_id_addr) -
1502*7fd79137SRobert Mustacchi           ((Dwarf_Unsigned) cie_id_value);
1503*7fd79137SRobert Mustacchi     } else {
1504*7fd79137SRobert Mustacchi         /* Traditional dwarf section offset is in cie_id */
1505*7fd79137SRobert Mustacchi         cieptr = (section_ptr + cie_id_value);
1506*7fd79137SRobert Mustacchi     }
1507*7fd79137SRobert Mustacchi     return cieptr;
1508*7fd79137SRobert Mustacchi }
1509*7fd79137SRobert Mustacchi 
1510*7fd79137SRobert Mustacchi /* To properly release all spaced used.
1511*7fd79137SRobert Mustacchi    Earlier approaches (before July 15, 2005)
1512*7fd79137SRobert Mustacchi    letting client do the dealloc directly left
1513*7fd79137SRobert Mustacchi    some data allocated.
1514*7fd79137SRobert Mustacchi    This is directly called by consumer code.
1515*7fd79137SRobert Mustacchi */
1516*7fd79137SRobert Mustacchi void
1517*7fd79137SRobert Mustacchi dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,
1518*7fd79137SRobert Mustacchi     Dwarf_Cie * cie_data,
1519*7fd79137SRobert Mustacchi     Dwarf_Signed cie_element_count,
1520*7fd79137SRobert Mustacchi     Dwarf_Fde * fde_data,
1521*7fd79137SRobert Mustacchi     Dwarf_Signed fde_element_count)
1522*7fd79137SRobert Mustacchi {
1523*7fd79137SRobert Mustacchi     Dwarf_Signed i = 0;
1524*7fd79137SRobert Mustacchi 
1525*7fd79137SRobert Mustacchi     for (i = 0; i < cie_element_count; ++i) {
1526*7fd79137SRobert Mustacchi         Dwarf_Frame frame = cie_data[i]->ci_initial_table;
1527*7fd79137SRobert Mustacchi 
1528*7fd79137SRobert Mustacchi         if (frame)
1529*7fd79137SRobert Mustacchi             dwarf_dealloc(dbg, frame, DW_DLA_FRAME);
1530*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, cie_data[i], DW_DLA_CIE);
1531*7fd79137SRobert Mustacchi     }
1532*7fd79137SRobert Mustacchi     for (i = 0; i < fde_element_count; ++i) {
1533*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, fde_data[i], DW_DLA_FDE);
1534*7fd79137SRobert Mustacchi     }
1535*7fd79137SRobert Mustacchi     if (cie_data)
1536*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, cie_data, DW_DLA_LIST);
1537*7fd79137SRobert Mustacchi     if (fde_data)
1538*7fd79137SRobert Mustacchi         dwarf_dealloc(dbg, fde_data, DW_DLA_LIST);
1539*7fd79137SRobert Mustacchi 
1540*7fd79137SRobert Mustacchi }
1541