1*7304104dSAndroid Build Coastguard Worker /* FDE reading.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of either
7*7304104dSAndroid Build Coastguard Worker
8*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker your option) any later version
11*7304104dSAndroid Build Coastguard Worker
12*7304104dSAndroid Build Coastguard Worker or
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker your option) any later version
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23*7304104dSAndroid Build Coastguard Worker General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker
25*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
27*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
28*7304104dSAndroid Build Coastguard Worker
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker
33*7304104dSAndroid Build Coastguard Worker #include "cfi.h"
34*7304104dSAndroid Build Coastguard Worker #include <search.h>
35*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
36*7304104dSAndroid Build Coastguard Worker
37*7304104dSAndroid Build Coastguard Worker #include "encoded-value.h"
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker static int
compare_fde(const void * a,const void * b)40*7304104dSAndroid Build Coastguard Worker compare_fde (const void *a, const void *b)
41*7304104dSAndroid Build Coastguard Worker {
42*7304104dSAndroid Build Coastguard Worker const struct dwarf_fde *fde1 = a;
43*7304104dSAndroid Build Coastguard Worker const struct dwarf_fde *fde2 = b;
44*7304104dSAndroid Build Coastguard Worker
45*7304104dSAndroid Build Coastguard Worker /* Find out which of the two arguments is the search value.
46*7304104dSAndroid Build Coastguard Worker It has end offset 0. */
47*7304104dSAndroid Build Coastguard Worker if (fde1->end == 0)
48*7304104dSAndroid Build Coastguard Worker {
49*7304104dSAndroid Build Coastguard Worker if (fde1->start < fde2->start)
50*7304104dSAndroid Build Coastguard Worker return -1;
51*7304104dSAndroid Build Coastguard Worker if (fde1->start >= fde2->end)
52*7304104dSAndroid Build Coastguard Worker return 1;
53*7304104dSAndroid Build Coastguard Worker }
54*7304104dSAndroid Build Coastguard Worker else
55*7304104dSAndroid Build Coastguard Worker {
56*7304104dSAndroid Build Coastguard Worker if (fde2->start < fde1->start)
57*7304104dSAndroid Build Coastguard Worker return 1;
58*7304104dSAndroid Build Coastguard Worker if (fde2->start >= fde1->end)
59*7304104dSAndroid Build Coastguard Worker return -1;
60*7304104dSAndroid Build Coastguard Worker }
61*7304104dSAndroid Build Coastguard Worker
62*7304104dSAndroid Build Coastguard Worker return 0;
63*7304104dSAndroid Build Coastguard Worker }
64*7304104dSAndroid Build Coastguard Worker
65*7304104dSAndroid Build Coastguard Worker static struct dwarf_fde *
intern_fde(Dwarf_CFI * cache,const Dwarf_FDE * entry)66*7304104dSAndroid Build Coastguard Worker intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
67*7304104dSAndroid Build Coastguard Worker {
68*7304104dSAndroid Build Coastguard Worker /* Look up the new entry's CIE. */
69*7304104dSAndroid Build Coastguard Worker struct dwarf_cie *cie = __libdw_find_cie (cache, entry->CIE_pointer);
70*7304104dSAndroid Build Coastguard Worker if (cie == NULL)
71*7304104dSAndroid Build Coastguard Worker return (void *) -1l;
72*7304104dSAndroid Build Coastguard Worker
73*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *fde = malloc (sizeof (struct dwarf_fde));
74*7304104dSAndroid Build Coastguard Worker if (fde == NULL)
75*7304104dSAndroid Build Coastguard Worker {
76*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
77*7304104dSAndroid Build Coastguard Worker return NULL;
78*7304104dSAndroid Build Coastguard Worker }
79*7304104dSAndroid Build Coastguard Worker
80*7304104dSAndroid Build Coastguard Worker fde->instructions = entry->start;
81*7304104dSAndroid Build Coastguard Worker fde->instructions_end = entry->end;
82*7304104dSAndroid Build Coastguard Worker if (unlikely (read_encoded_value (cache, cie->fde_encoding,
83*7304104dSAndroid Build Coastguard Worker &fde->instructions, &fde->start))
84*7304104dSAndroid Build Coastguard Worker || unlikely (read_encoded_value (cache, cie->fde_encoding & 0x0f,
85*7304104dSAndroid Build Coastguard Worker &fde->instructions, &fde->end)))
86*7304104dSAndroid Build Coastguard Worker {
87*7304104dSAndroid Build Coastguard Worker free (fde);
88*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
89*7304104dSAndroid Build Coastguard Worker return NULL;
90*7304104dSAndroid Build Coastguard Worker }
91*7304104dSAndroid Build Coastguard Worker fde->end += fde->start;
92*7304104dSAndroid Build Coastguard Worker
93*7304104dSAndroid Build Coastguard Worker /* Make sure the fde actually covers a real code range. */
94*7304104dSAndroid Build Coastguard Worker if (fde->start >= fde->end)
95*7304104dSAndroid Build Coastguard Worker {
96*7304104dSAndroid Build Coastguard Worker free (fde);
97*7304104dSAndroid Build Coastguard Worker return (void *) -1;
98*7304104dSAndroid Build Coastguard Worker }
99*7304104dSAndroid Build Coastguard Worker
100*7304104dSAndroid Build Coastguard Worker fde->cie = cie;
101*7304104dSAndroid Build Coastguard Worker
102*7304104dSAndroid Build Coastguard Worker if (cie->sized_augmentation_data)
103*7304104dSAndroid Build Coastguard Worker {
104*7304104dSAndroid Build Coastguard Worker /* The CIE augmentation says the FDE has a DW_FORM_block
105*7304104dSAndroid Build Coastguard Worker before its actual instruction stream. */
106*7304104dSAndroid Build Coastguard Worker Dwarf_Word len;
107*7304104dSAndroid Build Coastguard Worker if (fde->instructions >= fde->instructions_end)
108*7304104dSAndroid Build Coastguard Worker goto invalid;
109*7304104dSAndroid Build Coastguard Worker get_uleb128 (len, fde->instructions, fde->instructions_end);
110*7304104dSAndroid Build Coastguard Worker if ((Dwarf_Word) (fde->instructions_end - fde->instructions) < len)
111*7304104dSAndroid Build Coastguard Worker {
112*7304104dSAndroid Build Coastguard Worker invalid:
113*7304104dSAndroid Build Coastguard Worker free (fde);
114*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
115*7304104dSAndroid Build Coastguard Worker return NULL;
116*7304104dSAndroid Build Coastguard Worker }
117*7304104dSAndroid Build Coastguard Worker fde->instructions += len;
118*7304104dSAndroid Build Coastguard Worker }
119*7304104dSAndroid Build Coastguard Worker else
120*7304104dSAndroid Build Coastguard Worker /* We had to understand all of the CIE augmentation string.
121*7304104dSAndroid Build Coastguard Worker We've recorded the number of data bytes in FDEs. */
122*7304104dSAndroid Build Coastguard Worker fde->instructions += cie->fde_augmentation_data_size;
123*7304104dSAndroid Build Coastguard Worker
124*7304104dSAndroid Build Coastguard Worker /* Add the new entry to the search tree. */
125*7304104dSAndroid Build Coastguard Worker struct dwarf_fde **tres = tsearch (fde, &cache->fde_tree, &compare_fde);
126*7304104dSAndroid Build Coastguard Worker if (tres == NULL)
127*7304104dSAndroid Build Coastguard Worker {
128*7304104dSAndroid Build Coastguard Worker free (fde);
129*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
130*7304104dSAndroid Build Coastguard Worker return NULL;
131*7304104dSAndroid Build Coastguard Worker }
132*7304104dSAndroid Build Coastguard Worker else if (*tres != fde)
133*7304104dSAndroid Build Coastguard Worker {
134*7304104dSAndroid Build Coastguard Worker /* There is already an FDE in the cache that covers the same
135*7304104dSAndroid Build Coastguard Worker address range. That is odd. Ignore this FDE. And just use
136*7304104dSAndroid Build Coastguard Worker the one in the cache for consistency. */
137*7304104dSAndroid Build Coastguard Worker free (fde);
138*7304104dSAndroid Build Coastguard Worker return *tres;
139*7304104dSAndroid Build Coastguard Worker }
140*7304104dSAndroid Build Coastguard Worker
141*7304104dSAndroid Build Coastguard Worker return fde;
142*7304104dSAndroid Build Coastguard Worker }
143*7304104dSAndroid Build Coastguard Worker
144*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *
145*7304104dSAndroid Build Coastguard Worker internal_function
__libdw_fde_by_offset(Dwarf_CFI * cache,Dwarf_Off offset)146*7304104dSAndroid Build Coastguard Worker __libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset)
147*7304104dSAndroid Build Coastguard Worker {
148*7304104dSAndroid Build Coastguard Worker Dwarf_CFI_Entry entry;
149*7304104dSAndroid Build Coastguard Worker Dwarf_Off next_offset;
150*7304104dSAndroid Build Coastguard Worker int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
151*7304104dSAndroid Build Coastguard Worker &cache->data->d, CFI_IS_EH (cache),
152*7304104dSAndroid Build Coastguard Worker offset, &next_offset, &entry);
153*7304104dSAndroid Build Coastguard Worker if (result != 0)
154*7304104dSAndroid Build Coastguard Worker {
155*7304104dSAndroid Build Coastguard Worker if (result > 0)
156*7304104dSAndroid Build Coastguard Worker invalid:
157*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
158*7304104dSAndroid Build Coastguard Worker return NULL;
159*7304104dSAndroid Build Coastguard Worker }
160*7304104dSAndroid Build Coastguard Worker
161*7304104dSAndroid Build Coastguard Worker if (unlikely (dwarf_cfi_cie_p (&entry)))
162*7304104dSAndroid Build Coastguard Worker goto invalid;
163*7304104dSAndroid Build Coastguard Worker
164*7304104dSAndroid Build Coastguard Worker /* We have a new FDE to consider. */
165*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *fde = intern_fde (cache, &entry.fde);
166*7304104dSAndroid Build Coastguard Worker if (fde == (void *) -1l || fde == NULL)
167*7304104dSAndroid Build Coastguard Worker return NULL;
168*7304104dSAndroid Build Coastguard Worker
169*7304104dSAndroid Build Coastguard Worker /* If this happened to be what we would have read next, notice it. */
170*7304104dSAndroid Build Coastguard Worker if (cache->next_offset == offset)
171*7304104dSAndroid Build Coastguard Worker cache->next_offset = next_offset;
172*7304104dSAndroid Build Coastguard Worker
173*7304104dSAndroid Build Coastguard Worker return fde;
174*7304104dSAndroid Build Coastguard Worker }
175*7304104dSAndroid Build Coastguard Worker
176*7304104dSAndroid Build Coastguard Worker /* Use a binary search table in .eh_frame_hdr format, yield an FDE offset. */
177*7304104dSAndroid Build Coastguard Worker static Dwarf_Off
binary_search_fde(Dwarf_CFI * cache,Dwarf_Addr address)178*7304104dSAndroid Build Coastguard Worker binary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address)
179*7304104dSAndroid Build Coastguard Worker {
180*7304104dSAndroid Build Coastguard Worker const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident,
181*7304104dSAndroid Build Coastguard Worker cache->search_table_encoding,
182*7304104dSAndroid Build Coastguard Worker NULL);
183*7304104dSAndroid Build Coastguard Worker if (unlikely (size == 0))
184*7304104dSAndroid Build Coastguard Worker return (Dwarf_Off) -1l;
185*7304104dSAndroid Build Coastguard Worker
186*7304104dSAndroid Build Coastguard Worker /* Dummy used by read_encoded_value. */
187*7304104dSAndroid Build Coastguard Worker Elf_Data_Scn dummy_cfi_hdr_data =
188*7304104dSAndroid Build Coastguard Worker {
189*7304104dSAndroid Build Coastguard Worker .d = { .d_buf = (void *) cache->search_table,
190*7304104dSAndroid Build Coastguard Worker .d_size = cache->search_table_len }
191*7304104dSAndroid Build Coastguard Worker };
192*7304104dSAndroid Build Coastguard Worker
193*7304104dSAndroid Build Coastguard Worker Dwarf_CFI dummy_cfi =
194*7304104dSAndroid Build Coastguard Worker {
195*7304104dSAndroid Build Coastguard Worker .e_ident = cache->e_ident,
196*7304104dSAndroid Build Coastguard Worker .datarel = cache->search_table_vaddr,
197*7304104dSAndroid Build Coastguard Worker .frame_vaddr = cache->search_table_vaddr,
198*7304104dSAndroid Build Coastguard Worker .data = &dummy_cfi_hdr_data
199*7304104dSAndroid Build Coastguard Worker };
200*7304104dSAndroid Build Coastguard Worker
201*7304104dSAndroid Build Coastguard Worker size_t l = 0, u = cache->search_table_entries;
202*7304104dSAndroid Build Coastguard Worker while (l < u)
203*7304104dSAndroid Build Coastguard Worker {
204*7304104dSAndroid Build Coastguard Worker size_t idx = (l + u) / 2;
205*7304104dSAndroid Build Coastguard Worker
206*7304104dSAndroid Build Coastguard Worker /* Max idx * size is checked against search_table len when
207*7304104dSAndroid Build Coastguard Worker loading eh_frame_hdr. */
208*7304104dSAndroid Build Coastguard Worker const uint8_t *p = &cache->search_table[idx * size];
209*7304104dSAndroid Build Coastguard Worker Dwarf_Addr start;
210*7304104dSAndroid Build Coastguard Worker if (unlikely (read_encoded_value (&dummy_cfi,
211*7304104dSAndroid Build Coastguard Worker cache->search_table_encoding, &p,
212*7304104dSAndroid Build Coastguard Worker &start)))
213*7304104dSAndroid Build Coastguard Worker break;
214*7304104dSAndroid Build Coastguard Worker if (address < start)
215*7304104dSAndroid Build Coastguard Worker u = idx;
216*7304104dSAndroid Build Coastguard Worker else
217*7304104dSAndroid Build Coastguard Worker {
218*7304104dSAndroid Build Coastguard Worker l = idx + 1;
219*7304104dSAndroid Build Coastguard Worker
220*7304104dSAndroid Build Coastguard Worker Dwarf_Addr fde;
221*7304104dSAndroid Build Coastguard Worker if (unlikely (read_encoded_value (&dummy_cfi,
222*7304104dSAndroid Build Coastguard Worker cache->search_table_encoding, &p,
223*7304104dSAndroid Build Coastguard Worker &fde)))
224*7304104dSAndroid Build Coastguard Worker break;
225*7304104dSAndroid Build Coastguard Worker
226*7304104dSAndroid Build Coastguard Worker /* If this is the last entry, its upper bound is assumed to be
227*7304104dSAndroid Build Coastguard Worker the end of the module.
228*7304104dSAndroid Build Coastguard Worker XXX really should be end of containing PT_LOAD segment */
229*7304104dSAndroid Build Coastguard Worker if (l < cache->search_table_entries)
230*7304104dSAndroid Build Coastguard Worker {
231*7304104dSAndroid Build Coastguard Worker /* Look at the start address in the following entry. */
232*7304104dSAndroid Build Coastguard Worker Dwarf_Addr end;
233*7304104dSAndroid Build Coastguard Worker if (unlikely (read_encoded_value
234*7304104dSAndroid Build Coastguard Worker (&dummy_cfi, cache->search_table_encoding, &p,
235*7304104dSAndroid Build Coastguard Worker &end)))
236*7304104dSAndroid Build Coastguard Worker break;
237*7304104dSAndroid Build Coastguard Worker if (address >= end)
238*7304104dSAndroid Build Coastguard Worker continue;
239*7304104dSAndroid Build Coastguard Worker }
240*7304104dSAndroid Build Coastguard Worker
241*7304104dSAndroid Build Coastguard Worker return fde - cache->frame_vaddr;
242*7304104dSAndroid Build Coastguard Worker }
243*7304104dSAndroid Build Coastguard Worker }
244*7304104dSAndroid Build Coastguard Worker
245*7304104dSAndroid Build Coastguard Worker return (Dwarf_Off) -1l;
246*7304104dSAndroid Build Coastguard Worker }
247*7304104dSAndroid Build Coastguard Worker
248*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *
249*7304104dSAndroid Build Coastguard Worker internal_function
__libdw_find_fde(Dwarf_CFI * cache,Dwarf_Addr address)250*7304104dSAndroid Build Coastguard Worker __libdw_find_fde (Dwarf_CFI *cache, Dwarf_Addr address)
251*7304104dSAndroid Build Coastguard Worker {
252*7304104dSAndroid Build Coastguard Worker /* Look for a cached FDE covering this address. */
253*7304104dSAndroid Build Coastguard Worker
254*7304104dSAndroid Build Coastguard Worker const struct dwarf_fde fde_key = { .start = address, .end = 0 };
255*7304104dSAndroid Build Coastguard Worker struct dwarf_fde **found = tfind (&fde_key, &cache->fde_tree, &compare_fde);
256*7304104dSAndroid Build Coastguard Worker if (found != NULL)
257*7304104dSAndroid Build Coastguard Worker return *found;
258*7304104dSAndroid Build Coastguard Worker
259*7304104dSAndroid Build Coastguard Worker /* Use .eh_frame_hdr binary search table if possible. */
260*7304104dSAndroid Build Coastguard Worker if (cache->search_table != NULL)
261*7304104dSAndroid Build Coastguard Worker {
262*7304104dSAndroid Build Coastguard Worker Dwarf_Off offset = binary_search_fde (cache, address);
263*7304104dSAndroid Build Coastguard Worker if (offset == (Dwarf_Off) -1l)
264*7304104dSAndroid Build Coastguard Worker goto no_match;
265*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset);
266*7304104dSAndroid Build Coastguard Worker if (likely (fde != NULL))
267*7304104dSAndroid Build Coastguard Worker {
268*7304104dSAndroid Build Coastguard Worker /* Sanity check the address range. */
269*7304104dSAndroid Build Coastguard Worker if (unlikely (address < fde->start))
270*7304104dSAndroid Build Coastguard Worker {
271*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
272*7304104dSAndroid Build Coastguard Worker return NULL;
273*7304104dSAndroid Build Coastguard Worker }
274*7304104dSAndroid Build Coastguard Worker /* .eh_frame_hdr does not indicate length covered by FDE. */
275*7304104dSAndroid Build Coastguard Worker if (unlikely (address >= fde->end))
276*7304104dSAndroid Build Coastguard Worker goto no_match;
277*7304104dSAndroid Build Coastguard Worker }
278*7304104dSAndroid Build Coastguard Worker return fde;
279*7304104dSAndroid Build Coastguard Worker }
280*7304104dSAndroid Build Coastguard Worker
281*7304104dSAndroid Build Coastguard Worker /* It's not there. Read more CFI entries until we find it. */
282*7304104dSAndroid Build Coastguard Worker while (1)
283*7304104dSAndroid Build Coastguard Worker {
284*7304104dSAndroid Build Coastguard Worker Dwarf_Off last_offset = cache->next_offset;
285*7304104dSAndroid Build Coastguard Worker Dwarf_CFI_Entry entry;
286*7304104dSAndroid Build Coastguard Worker int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
287*7304104dSAndroid Build Coastguard Worker &cache->data->d, CFI_IS_EH (cache),
288*7304104dSAndroid Build Coastguard Worker last_offset, &cache->next_offset,
289*7304104dSAndroid Build Coastguard Worker &entry);
290*7304104dSAndroid Build Coastguard Worker if (result > 0)
291*7304104dSAndroid Build Coastguard Worker break;
292*7304104dSAndroid Build Coastguard Worker if (result < 0)
293*7304104dSAndroid Build Coastguard Worker {
294*7304104dSAndroid Build Coastguard Worker if (cache->next_offset == last_offset)
295*7304104dSAndroid Build Coastguard Worker /* We couldn't progress past the bogus FDE. */
296*7304104dSAndroid Build Coastguard Worker break;
297*7304104dSAndroid Build Coastguard Worker /* Skip the loser and look at the next entry. */
298*7304104dSAndroid Build Coastguard Worker continue;
299*7304104dSAndroid Build Coastguard Worker }
300*7304104dSAndroid Build Coastguard Worker
301*7304104dSAndroid Build Coastguard Worker if (dwarf_cfi_cie_p (&entry))
302*7304104dSAndroid Build Coastguard Worker {
303*7304104dSAndroid Build Coastguard Worker /* This is a CIE, not an FDE. We eagerly intern these
304*7304104dSAndroid Build Coastguard Worker because the next FDE will usually refer to this CIE. */
305*7304104dSAndroid Build Coastguard Worker __libdw_intern_cie (cache, last_offset, &entry.cie);
306*7304104dSAndroid Build Coastguard Worker continue;
307*7304104dSAndroid Build Coastguard Worker }
308*7304104dSAndroid Build Coastguard Worker
309*7304104dSAndroid Build Coastguard Worker /* We have a new FDE to consider. */
310*7304104dSAndroid Build Coastguard Worker struct dwarf_fde *fde = intern_fde (cache, &entry.fde);
311*7304104dSAndroid Build Coastguard Worker
312*7304104dSAndroid Build Coastguard Worker if (fde == (void *) -1l) /* Bad FDE, but we can keep looking. */
313*7304104dSAndroid Build Coastguard Worker continue;
314*7304104dSAndroid Build Coastguard Worker
315*7304104dSAndroid Build Coastguard Worker if (fde == NULL) /* Bad data. */
316*7304104dSAndroid Build Coastguard Worker return NULL;
317*7304104dSAndroid Build Coastguard Worker
318*7304104dSAndroid Build Coastguard Worker /* Is this the one we're looking for? */
319*7304104dSAndroid Build Coastguard Worker if (fde->start <= address && fde->end > address)
320*7304104dSAndroid Build Coastguard Worker return fde;
321*7304104dSAndroid Build Coastguard Worker }
322*7304104dSAndroid Build Coastguard Worker
323*7304104dSAndroid Build Coastguard Worker no_match:
324*7304104dSAndroid Build Coastguard Worker /* We found no FDE covering this address. */
325*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NO_MATCH);
326*7304104dSAndroid Build Coastguard Worker return NULL;
327*7304104dSAndroid Build Coastguard Worker }
328