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
chain_up_fde(Dwarf_Fde newone,Dwarf_Fde * head,Dwarf_Fde * cur)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
chain_up_cie(Dwarf_Cie newone,Dwarf_Cie * head,Dwarf_Cie * cur)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
validate_length(Dwarf_Debug dbg,Dwarf_Cie cieptr,Dwarf_Unsigned length,Dwarf_Unsigned length_size,Dwarf_Unsigned extension_size,Dwarf_Small * section_ptr,Dwarf_Small * ciefde_start,const char * cieorfde)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
_dwarf_get_fde_list_internal(Dwarf_Debug dbg,Dwarf_Cie ** cie_data,Dwarf_Signed * cie_element_count,Dwarf_Fde ** fde_data,Dwarf_Signed * fde_element_count,Dwarf_Small * section_ptr,Dwarf_Unsigned section_index,Dwarf_Unsigned section_length,Dwarf_Unsigned cie_id_value,int use_gnu_cie_calc,Dwarf_Error * error)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
dwarf_create_cie_from_after_start(Dwarf_Debug dbg,struct cie_fde_prefix_s * prefix,Dwarf_Small * section_pointer,Dwarf_Small * frame_ptr,Dwarf_Unsigned cie_count,int use_gnu_cie_calc,Dwarf_Cie * cie_ptr_out,Dwarf_Error * error)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
dwarf_create_fde_from_after_start(Dwarf_Debug dbg,struct cie_fde_prefix_s * prefix,Dwarf_Small * section_pointer,Dwarf_Small * frame_ptr,int use_gnu_cie_calc,Dwarf_Cie cie_ptr_in,Dwarf_Fde * fde_ptr_out,Dwarf_Error * error)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
qsort_compare(const void * elem1,const void * elem2)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
dwarf_read_cie_fde_prefix(Dwarf_Debug dbg,Dwarf_Small * frame_ptr_in,Dwarf_Small * section_ptr_in,Dwarf_Unsigned section_index_in,Dwarf_Unsigned section_length_in,struct cie_fde_prefix_s * data_out,Dwarf_Error * error)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
dealloc_fde_cie_list_internal(Dwarf_Fde head_fde_ptr,Dwarf_Cie head_cie_ptr)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
dwarf_find_existing_cie_ptr(Dwarf_Small * cie_ptr,Dwarf_Cie cur_cie_ptr,Dwarf_Cie * cie_ptr_to_use_out,Dwarf_Cie head_cie_ptr)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
dwarf_create_cie_from_start(Dwarf_Debug dbg,Dwarf_Small * cie_ptr_val,Dwarf_Small * section_ptr,Dwarf_Unsigned section_index,Dwarf_Unsigned section_length,Dwarf_Small * frame_ptr_end,Dwarf_Unsigned cie_id_value,Dwarf_Unsigned cie_count,int use_gnu_cie_calc,Dwarf_Cie * cie_ptr_to_use_out,Dwarf_Error * error)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
gnu_aug_encodings(Dwarf_Debug dbg,char * augmentation,Dwarf_Small * aug_data,Dwarf_Unsigned aug_data_len,Dwarf_Half address_size,unsigned char * pers_hand_enc_out,unsigned char * lsda_enc_out,unsigned char * fde_begin_enc_out,Dwarf_Addr * gnu_pers_addr_out)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
read_encoded_ptr(Dwarf_Debug dbg,Dwarf_Small * section_pointer,Dwarf_Small * input_field,int gnu_encoding,Dwarf_Half address_size,Dwarf_Unsigned * addr,Dwarf_Small ** input_field_updated)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
_dwarf_get_augmentation_type(Dwarf_Debug dbg,Dwarf_Small * augmentation_string,int is_gcc_eh_frame)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
get_gcc_eh_augmentation(Dwarf_Debug dbg,Dwarf_Small * frame_ptr,unsigned long * size_of_augmentation_data,enum Dwarf_augmentation_type augtype,Dwarf_Small * section_pointer,Dwarf_Small * fde_eh_encoding_out,char * augmentation)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 *
get_cieptr_given_offset(Dwarf_Unsigned cie_id_value,int use_gnu_cie_calc,Dwarf_Small * section_ptr,Dwarf_Small * cie_id_addr)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
dwarf_fde_cie_list_dealloc(Dwarf_Debug dbg,Dwarf_Cie * cie_data,Dwarf_Signed cie_element_count,Dwarf_Fde * fde_data,Dwarf_Signed fde_element_count)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