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