xref: /aosp_15_r20/external/elfutils/libdw/fde.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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