1*2f055536Smrg /* Copyright (C) 2001-2020 Free Software Foundation, Inc.
2af526226Smrg Contributed by Jakub Jelinek <jakub@redhat.com>.
3af526226Smrg
4af526226Smrg This file is part of GCC.
5af526226Smrg
6af526226Smrg GCC is free software; you can redistribute it and/or modify
7af526226Smrg it under the terms of the GNU General Public License as published by
8af526226Smrg the Free Software Foundation; either version 3, or (at your option)
9af526226Smrg any later version.
10af526226Smrg
11af526226Smrg GCC is distributed in the hope that it will be useful,
12af526226Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
13af526226Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14af526226Smrg GNU General Public License for more details.
15af526226Smrg
16af526226Smrg Under Section 7 of GPL version 3, you are granted additional
17af526226Smrg permissions described in the GCC Runtime Library Exception, version
18af526226Smrg 3.1, as published by the Free Software Foundation.
19af526226Smrg
20af526226Smrg You should have received a copy of the GNU General Public License and
21af526226Smrg a copy of the GCC Runtime Library Exception along with this program;
22af526226Smrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23af526226Smrg <http://www.gnu.org/licenses/>. */
24af526226Smrg
25af526226Smrg /* Locate the FDE entry for a given address, using PT_GNU_EH_FRAME ELF
26af526226Smrg segment and dl_iterate_phdr to avoid register/deregister calls at
27af526226Smrg DSO load/unload. */
28af526226Smrg
29af526226Smrg #ifndef _GNU_SOURCE
30af526226Smrg #define _GNU_SOURCE 1
31af526226Smrg #endif
32af526226Smrg
33af526226Smrg #include "tconfig.h"
34af526226Smrg #include "tsystem.h"
352b1b424dSmrg #if !defined(inhibit_libc) && defined(__GLIBC__)
36af526226Smrg #include <elf.h> /* Get DT_CONFIG. */
37af526226Smrg #endif
38af526226Smrg #include "coretypes.h"
39af526226Smrg #include "tm.h"
40af526226Smrg #include "libgcc_tm.h"
41af526226Smrg #include "dwarf2.h"
42af526226Smrg #include "unwind.h"
43af526226Smrg #define NO_BASE_OF_ENCODED_VALUE
44af526226Smrg #include "unwind-pe.h"
45af526226Smrg #include "unwind-dw2-fde.h"
46af526226Smrg #include "unwind-compat.h"
47af526226Smrg #include "gthr.h"
48af526226Smrg
49af526226Smrg #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
50af526226Smrg && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
51af526226Smrg || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
52af526226Smrg # define USE_PT_GNU_EH_FRAME
53af526226Smrg #endif
54af526226Smrg
55af526226Smrg #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
56af526226Smrg && defined(__BIONIC__)
57af526226Smrg # define USE_PT_GNU_EH_FRAME
58af526226Smrg #endif
59af526226Smrg
60af526226Smrg #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
614646d632Smrg && defined(TARGET_DL_ITERATE_PHDR) \
62bb2a37e4Smrg && defined(__linux__)
63bb2a37e4Smrg # define USE_PT_GNU_EH_FRAME
64bb2a37e4Smrg #endif
65bb2a37e4Smrg
66bb2a37e4Smrg #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
67bb2a37e4Smrg && defined(TARGET_DL_ITERATE_PHDR) \
684646d632Smrg && (defined(__DragonFly__) || defined(__FreeBSD__))
69af526226Smrg # define ElfW __ElfN
70af526226Smrg # define USE_PT_GNU_EH_FRAME
71af526226Smrg #endif
72af526226Smrg
73af526226Smrg #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
743bf62c3fSmrg && (defined(__OpenBSD__) || defined(__NetBSD__))
75af526226Smrg # define ElfW(type) Elf_##type
76af526226Smrg # define USE_PT_GNU_EH_FRAME
77af526226Smrg #endif
78af526226Smrg
79af526226Smrg #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
80af526226Smrg && defined(TARGET_DL_ITERATE_PHDR) \
81af526226Smrg && defined(__sun__) && defined(__svr4__)
82af526226Smrg # define USE_PT_GNU_EH_FRAME
83af526226Smrg #endif
84af526226Smrg
85af526226Smrg #if defined(USE_PT_GNU_EH_FRAME)
86af526226Smrg
87af526226Smrg #include <link.h>
88af526226Smrg
89af526226Smrg #ifndef __RELOC_POINTER
90af526226Smrg # define __RELOC_POINTER(ptr, base) ((ptr) + (base))
91af526226Smrg #endif
92af526226Smrg
93af526226Smrg static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases *bases);
94af526226Smrg
95af526226Smrg #define _Unwind_Find_FDE _Unwind_Find_registered_FDE
96af526226Smrg #include "unwind-dw2-fde.c"
97af526226Smrg #undef _Unwind_Find_FDE
98af526226Smrg
99af526226Smrg #ifndef PT_GNU_EH_FRAME
100af526226Smrg #define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
101af526226Smrg #endif
102af526226Smrg
103af526226Smrg struct unw_eh_callback_data
104af526226Smrg {
105af526226Smrg _Unwind_Ptr pc;
106af526226Smrg void *tbase;
107af526226Smrg void *dbase;
108af526226Smrg void *func;
109af526226Smrg const fde *ret;
110af526226Smrg int check_cache;
111af526226Smrg };
112af526226Smrg
113af526226Smrg struct unw_eh_frame_hdr
114af526226Smrg {
115af526226Smrg unsigned char version;
116af526226Smrg unsigned char eh_frame_ptr_enc;
117af526226Smrg unsigned char fde_count_enc;
118af526226Smrg unsigned char table_enc;
119af526226Smrg };
120af526226Smrg
121af526226Smrg #define FRAME_HDR_CACHE_SIZE 8
122af526226Smrg
123af526226Smrg static struct frame_hdr_cache_element
124af526226Smrg {
125af526226Smrg _Unwind_Ptr pc_low;
126af526226Smrg _Unwind_Ptr pc_high;
1273bf62c3fSmrg #if defined __FRV_FDPIC__ || defined __BFIN_FDPIC__
1283bf62c3fSmrg struct elf32_fdpic_loadaddr load_base;
1293bf62c3fSmrg #else
130af526226Smrg _Unwind_Ptr load_base;
1313bf62c3fSmrg #endif
132af526226Smrg const ElfW(Phdr) *p_eh_frame_hdr;
133af526226Smrg const ElfW(Phdr) *p_dynamic;
134af526226Smrg struct frame_hdr_cache_element *link;
135af526226Smrg } frame_hdr_cache[FRAME_HDR_CACHE_SIZE];
136af526226Smrg
137af526226Smrg static struct frame_hdr_cache_element *frame_hdr_cache_head;
138af526226Smrg
139af526226Smrg /* Like base_of_encoded_value, but take the base from a struct
140af526226Smrg unw_eh_callback_data instead of an _Unwind_Context. */
141af526226Smrg
142af526226Smrg static _Unwind_Ptr
base_from_cb_data(unsigned char encoding,struct unw_eh_callback_data * data)143af526226Smrg base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
144af526226Smrg {
145af526226Smrg if (encoding == DW_EH_PE_omit)
146af526226Smrg return 0;
147af526226Smrg
148af526226Smrg switch (encoding & 0x70)
149af526226Smrg {
150af526226Smrg case DW_EH_PE_absptr:
151af526226Smrg case DW_EH_PE_pcrel:
152af526226Smrg case DW_EH_PE_aligned:
153af526226Smrg return 0;
154af526226Smrg
155af526226Smrg case DW_EH_PE_textrel:
156af526226Smrg return (_Unwind_Ptr) data->tbase;
157af526226Smrg case DW_EH_PE_datarel:
158af526226Smrg return (_Unwind_Ptr) data->dbase;
159af526226Smrg default:
160af526226Smrg gcc_unreachable ();
161af526226Smrg }
162af526226Smrg }
163af526226Smrg
164af526226Smrg static int
_Unwind_IteratePhdrCallback(struct dl_phdr_info * info,size_t size,void * ptr)165af526226Smrg _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
166af526226Smrg {
167af526226Smrg struct unw_eh_callback_data *data = (struct unw_eh_callback_data *) ptr;
168af526226Smrg const ElfW(Phdr) *phdr, *p_eh_frame_hdr, *p_dynamic;
169af526226Smrg long n, match;
1703bf62c3fSmrg #if defined __FRV_FDPIC__ || defined __BFIN_FDPIC__
171af526226Smrg struct elf32_fdpic_loadaddr load_base;
172af526226Smrg #else
173af526226Smrg _Unwind_Ptr load_base;
174af526226Smrg #endif
175af526226Smrg const unsigned char *p;
176af526226Smrg const struct unw_eh_frame_hdr *hdr;
177af526226Smrg _Unwind_Ptr eh_frame;
178af526226Smrg struct object ob;
179af526226Smrg _Unwind_Ptr pc_low = 0, pc_high = 0;
180af526226Smrg
181af526226Smrg struct ext_dl_phdr_info
182af526226Smrg {
183af526226Smrg ElfW(Addr) dlpi_addr;
184af526226Smrg const char *dlpi_name;
185af526226Smrg const ElfW(Phdr) *dlpi_phdr;
186af526226Smrg ElfW(Half) dlpi_phnum;
187af526226Smrg unsigned long long int dlpi_adds;
188af526226Smrg unsigned long long int dlpi_subs;
189af526226Smrg };
190af526226Smrg
191af526226Smrg match = 0;
192af526226Smrg phdr = info->dlpi_phdr;
193af526226Smrg load_base = info->dlpi_addr;
194af526226Smrg p_eh_frame_hdr = NULL;
195af526226Smrg p_dynamic = NULL;
196af526226Smrg
197af526226Smrg struct frame_hdr_cache_element *prev_cache_entry = NULL,
198af526226Smrg *last_cache_entry = NULL;
199af526226Smrg
200af526226Smrg if (data->check_cache && size >= sizeof (struct ext_dl_phdr_info))
201af526226Smrg {
202af526226Smrg static unsigned long long adds = -1ULL, subs;
203af526226Smrg struct ext_dl_phdr_info *einfo = (struct ext_dl_phdr_info *) info;
204af526226Smrg
205af526226Smrg /* We use a least recently used cache replacement policy. Also,
206af526226Smrg the most recently used cache entries are placed at the head
207af526226Smrg of the search chain. */
208af526226Smrg
209af526226Smrg if (einfo->dlpi_adds == adds && einfo->dlpi_subs == subs)
210af526226Smrg {
211af526226Smrg /* Find data->pc in shared library cache.
212af526226Smrg Set load_base, p_eh_frame_hdr and p_dynamic
213af526226Smrg plus match from the cache and goto
214af526226Smrg "Read .eh_frame_hdr header." below. */
215af526226Smrg
216af526226Smrg struct frame_hdr_cache_element *cache_entry;
217af526226Smrg
218af526226Smrg for (cache_entry = frame_hdr_cache_head;
219af526226Smrg cache_entry;
220af526226Smrg cache_entry = cache_entry->link)
221af526226Smrg {
222af526226Smrg if (data->pc >= cache_entry->pc_low
223af526226Smrg && data->pc < cache_entry->pc_high)
224af526226Smrg {
225af526226Smrg load_base = cache_entry->load_base;
226af526226Smrg p_eh_frame_hdr = cache_entry->p_eh_frame_hdr;
227af526226Smrg p_dynamic = cache_entry->p_dynamic;
228af526226Smrg
229af526226Smrg /* And move the entry we're using to the head. */
230af526226Smrg if (cache_entry != frame_hdr_cache_head)
231af526226Smrg {
232af526226Smrg prev_cache_entry->link = cache_entry->link;
233af526226Smrg cache_entry->link = frame_hdr_cache_head;
234af526226Smrg frame_hdr_cache_head = cache_entry;
235af526226Smrg }
236af526226Smrg goto found;
237af526226Smrg }
238af526226Smrg
239af526226Smrg last_cache_entry = cache_entry;
240af526226Smrg /* Exit early if we found an unused entry. */
241af526226Smrg if ((cache_entry->pc_low | cache_entry->pc_high) == 0)
242af526226Smrg break;
243af526226Smrg if (cache_entry->link != NULL)
244af526226Smrg prev_cache_entry = cache_entry;
245af526226Smrg }
246af526226Smrg }
247af526226Smrg else
248af526226Smrg {
249af526226Smrg adds = einfo->dlpi_adds;
250af526226Smrg subs = einfo->dlpi_subs;
251af526226Smrg /* Initialize the cache. Create a chain of cache entries,
252af526226Smrg with the final one terminated by a NULL link. */
253af526226Smrg int i;
254af526226Smrg for (i = 0; i < FRAME_HDR_CACHE_SIZE; i++)
255af526226Smrg {
256af526226Smrg frame_hdr_cache[i].pc_low = 0;
257af526226Smrg frame_hdr_cache[i].pc_high = 0;
258af526226Smrg frame_hdr_cache[i].link = &frame_hdr_cache[i+1];
259af526226Smrg }
260af526226Smrg frame_hdr_cache[i-1].link = NULL;
261af526226Smrg frame_hdr_cache_head = &frame_hdr_cache[0];
262af526226Smrg data->check_cache = 0;
263af526226Smrg }
264af526226Smrg }
265af526226Smrg
266af526226Smrg /* Make sure struct dl_phdr_info is at least as big as we need. */
267af526226Smrg if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
268af526226Smrg + sizeof (info->dlpi_phnum))
269af526226Smrg return -1;
270af526226Smrg
271af526226Smrg /* See if PC falls into one of the loaded segments. Find the eh_frame
272af526226Smrg segment at the same time. */
273af526226Smrg for (n = info->dlpi_phnum; --n >= 0; phdr++)
274af526226Smrg {
275af526226Smrg if (phdr->p_type == PT_LOAD)
276af526226Smrg {
277af526226Smrg _Unwind_Ptr vaddr = (_Unwind_Ptr)
278af526226Smrg __RELOC_POINTER (phdr->p_vaddr, load_base);
279af526226Smrg if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
280af526226Smrg {
281af526226Smrg match = 1;
282af526226Smrg pc_low = vaddr;
283af526226Smrg pc_high = vaddr + phdr->p_memsz;
284af526226Smrg }
285af526226Smrg }
286af526226Smrg else if (phdr->p_type == PT_GNU_EH_FRAME)
287af526226Smrg p_eh_frame_hdr = phdr;
288af526226Smrg #ifdef PT_SUNW_UNWIND
289af526226Smrg /* Sun ld emits PT_SUNW_UNWIND .eh_frame_hdr sections instead of
290af526226Smrg PT_SUNW_EH_FRAME/PT_GNU_EH_FRAME, so accept them as well. */
291af526226Smrg else if (phdr->p_type == PT_SUNW_UNWIND)
292af526226Smrg p_eh_frame_hdr = phdr;
293af526226Smrg #endif
294af526226Smrg else if (phdr->p_type == PT_DYNAMIC)
295af526226Smrg p_dynamic = phdr;
296af526226Smrg }
297af526226Smrg
298af526226Smrg if (!match)
299af526226Smrg return 0;
300af526226Smrg
301af526226Smrg if (size >= sizeof (struct ext_dl_phdr_info))
302af526226Smrg {
303af526226Smrg /* Move the cache entry we're about to overwrite to the head of
304af526226Smrg the list. If either last_cache_entry or prev_cache_entry are
305af526226Smrg NULL, that cache entry is already at the head. */
306af526226Smrg if (last_cache_entry != NULL && prev_cache_entry != NULL)
307af526226Smrg {
308af526226Smrg prev_cache_entry->link = last_cache_entry->link;
309af526226Smrg last_cache_entry->link = frame_hdr_cache_head;
310af526226Smrg frame_hdr_cache_head = last_cache_entry;
311af526226Smrg }
312af526226Smrg
313af526226Smrg frame_hdr_cache_head->load_base = load_base;
314af526226Smrg frame_hdr_cache_head->p_eh_frame_hdr = p_eh_frame_hdr;
315af526226Smrg frame_hdr_cache_head->p_dynamic = p_dynamic;
316af526226Smrg frame_hdr_cache_head->pc_low = pc_low;
317af526226Smrg frame_hdr_cache_head->pc_high = pc_high;
318af526226Smrg }
319af526226Smrg
320af526226Smrg found:
321af526226Smrg
322af526226Smrg if (!p_eh_frame_hdr)
323af526226Smrg return 0;
324af526226Smrg
325af526226Smrg /* Read .eh_frame_hdr header. */
326af526226Smrg hdr = (const struct unw_eh_frame_hdr *)
327af526226Smrg __RELOC_POINTER (p_eh_frame_hdr->p_vaddr, load_base);
328af526226Smrg if (hdr->version != 1)
329af526226Smrg return 1;
330af526226Smrg
331af526226Smrg #ifdef CRT_GET_RFIB_DATA
332*2f055536Smrg # if defined __i386__ || defined __nios2__
333af526226Smrg data->dbase = NULL;
334af526226Smrg if (p_dynamic)
335af526226Smrg {
336af526226Smrg /* For dynamically linked executables and shared libraries,
337af526226Smrg DT_PLTGOT is the gp value for that object. */
338af526226Smrg ElfW(Dyn) *dyn = (ElfW(Dyn) *)
339af526226Smrg __RELOC_POINTER (p_dynamic->p_vaddr, load_base);
340af526226Smrg for (; dyn->d_tag != DT_NULL ; dyn++)
341af526226Smrg if (dyn->d_tag == DT_PLTGOT)
342af526226Smrg {
343af526226Smrg data->dbase = (void *) dyn->d_un.d_ptr;
344af526226Smrg #if defined __linux__
345af526226Smrg /* On IA-32 Linux, _DYNAMIC is writable and GLIBC has
346af526226Smrg relocated it. */
347af526226Smrg #elif defined __sun__ && defined __svr4__
348af526226Smrg /* On Solaris 2/x86, we need to do this ourselves. */
349af526226Smrg data->dbase += load_base;
350af526226Smrg #endif
351af526226Smrg break;
352af526226Smrg }
353af526226Smrg }
3543bf62c3fSmrg # elif (defined __FRV_FDPIC__ || defined __BFIN_FDPIC__) && defined __linux__
355af526226Smrg data->dbase = load_base.got_value;
356af526226Smrg # else
357af526226Smrg # error What is DW_EH_PE_datarel base on this platform?
358af526226Smrg # endif
359af526226Smrg #endif
360af526226Smrg
361af526226Smrg p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
362af526226Smrg base_from_cb_data (hdr->eh_frame_ptr_enc,
363af526226Smrg data),
364af526226Smrg (const unsigned char *) (hdr + 1),
365af526226Smrg &eh_frame);
366af526226Smrg
367af526226Smrg /* We require here specific table encoding to speed things up.
368af526226Smrg Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
369af526226Smrg as base, not the processor specific DW_EH_PE_datarel. */
370af526226Smrg if (hdr->fde_count_enc != DW_EH_PE_omit
371af526226Smrg && hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
372af526226Smrg {
373af526226Smrg _Unwind_Ptr fde_count;
374af526226Smrg
375af526226Smrg p = read_encoded_value_with_base (hdr->fde_count_enc,
376af526226Smrg base_from_cb_data (hdr->fde_count_enc,
377af526226Smrg data),
378af526226Smrg p, &fde_count);
379af526226Smrg /* Shouldn't happen. */
380af526226Smrg if (fde_count == 0)
381af526226Smrg return 1;
382af526226Smrg if ((((_Unwind_Ptr) p) & 3) == 0)
383af526226Smrg {
384af526226Smrg struct fde_table {
385af526226Smrg signed initial_loc __attribute__ ((mode (SI)));
386af526226Smrg signed fde __attribute__ ((mode (SI)));
387af526226Smrg };
388af526226Smrg const struct fde_table *table = (const struct fde_table *) p;
389af526226Smrg size_t lo, hi, mid;
390af526226Smrg _Unwind_Ptr data_base = (_Unwind_Ptr) hdr;
391af526226Smrg fde *f;
392af526226Smrg unsigned int f_enc, f_enc_size;
393af526226Smrg _Unwind_Ptr range;
394af526226Smrg
395af526226Smrg mid = fde_count - 1;
396af526226Smrg if (data->pc < table[0].initial_loc + data_base)
397af526226Smrg return 1;
398af526226Smrg else if (data->pc < table[mid].initial_loc + data_base)
399af526226Smrg {
400af526226Smrg lo = 0;
401af526226Smrg hi = mid;
402af526226Smrg
403af526226Smrg while (lo < hi)
404af526226Smrg {
405af526226Smrg mid = (lo + hi) / 2;
406af526226Smrg if (data->pc < table[mid].initial_loc + data_base)
407af526226Smrg hi = mid;
408af526226Smrg else if (data->pc >= table[mid + 1].initial_loc + data_base)
409af526226Smrg lo = mid + 1;
410af526226Smrg else
411af526226Smrg break;
412af526226Smrg }
413af526226Smrg
414af526226Smrg gcc_assert (lo < hi);
415af526226Smrg }
416af526226Smrg
417af526226Smrg f = (fde *) (table[mid].fde + data_base);
418af526226Smrg f_enc = get_fde_encoding (f);
419af526226Smrg f_enc_size = size_of_encoded_value (f_enc);
420af526226Smrg read_encoded_value_with_base (f_enc & 0x0f, 0,
421af526226Smrg &f->pc_begin[f_enc_size], &range);
422af526226Smrg if (data->pc < table[mid].initial_loc + data_base + range)
423af526226Smrg data->ret = f;
424af526226Smrg data->func = (void *) (table[mid].initial_loc + data_base);
425af526226Smrg return 1;
426af526226Smrg }
427af526226Smrg }
428af526226Smrg
429af526226Smrg /* We have no sorted search table, so need to go the slow way.
430af526226Smrg As soon as GLIBC will provide API so to notify that a library has been
431af526226Smrg removed, we could cache this (and thus use search_object). */
432af526226Smrg ob.pc_begin = NULL;
433af526226Smrg ob.tbase = data->tbase;
434af526226Smrg ob.dbase = data->dbase;
435af526226Smrg ob.u.single = (fde *) eh_frame;
436af526226Smrg ob.s.i = 0;
437af526226Smrg ob.s.b.mixed_encoding = 1; /* Need to assume worst case. */
438af526226Smrg data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc);
439af526226Smrg if (data->ret != NULL)
440af526226Smrg {
441af526226Smrg _Unwind_Ptr func;
442af526226Smrg unsigned int encoding = get_fde_encoding (data->ret);
443af526226Smrg
444af526226Smrg read_encoded_value_with_base (encoding,
445af526226Smrg base_from_cb_data (encoding, data),
446af526226Smrg data->ret->pc_begin, &func);
447af526226Smrg data->func = (void *) func;
448af526226Smrg }
449af526226Smrg return 1;
450af526226Smrg }
451af526226Smrg
452af526226Smrg const fde *
_Unwind_Find_FDE(void * pc,struct dwarf_eh_bases * bases)453af526226Smrg _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
454af526226Smrg {
455af526226Smrg struct unw_eh_callback_data data;
456af526226Smrg const fde *ret;
457af526226Smrg
458af526226Smrg ret = _Unwind_Find_registered_FDE (pc, bases);
459af526226Smrg if (ret != NULL)
460af526226Smrg return ret;
461af526226Smrg
462af526226Smrg data.pc = (_Unwind_Ptr) pc;
463af526226Smrg data.tbase = NULL;
464af526226Smrg data.dbase = NULL;
465af526226Smrg data.func = NULL;
466af526226Smrg data.ret = NULL;
467af526226Smrg data.check_cache = 1;
468af526226Smrg
469af526226Smrg if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
470af526226Smrg return NULL;
471af526226Smrg
472af526226Smrg if (data.ret)
473af526226Smrg {
474af526226Smrg bases->tbase = data.tbase;
475af526226Smrg bases->dbase = data.dbase;
476af526226Smrg bases->func = data.func;
477af526226Smrg }
478af526226Smrg return data.ret;
479af526226Smrg }
480af526226Smrg
481af526226Smrg #else
482af526226Smrg /* Prevent multiple include of header files. */
483af526226Smrg #define _Unwind_Find_FDE _Unwind_Find_FDE
484af526226Smrg #include "unwind-dw2-fde.c"
485af526226Smrg #endif
486af526226Smrg
487af526226Smrg #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
488af526226Smrg alias (_Unwind_Find_FDE);
489af526226Smrg #endif
490