138fd1498Szrj /* Copyright (C) 2001-2018 Free Software Foundation, Inc.
238fd1498Szrj Contributed by Jakub Jelinek <jakub@redhat.com>.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify
738fd1498Szrj it under the terms of the GNU General Public License as published by
838fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj any later version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful,
1238fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1438fd1498Szrj GNU General Public License for more details.
1538fd1498Szrj
1638fd1498Szrj Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj 3.1, as published by the Free Software Foundation.
1938fd1498Szrj
2038fd1498Szrj You should have received a copy of the GNU General Public License and
2138fd1498Szrj a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2338fd1498Szrj <http://www.gnu.org/licenses/>. */
2438fd1498Szrj
2538fd1498Szrj /* Locate the FDE entry for a given address, using PT_GNU_EH_FRAME ELF
2638fd1498Szrj segment and dl_iterate_phdr to avoid register/deregister calls at
2738fd1498Szrj DSO load/unload. */
2838fd1498Szrj
2938fd1498Szrj #ifndef _GNU_SOURCE
3038fd1498Szrj #define _GNU_SOURCE 1
3138fd1498Szrj #endif
3238fd1498Szrj
3338fd1498Szrj #include "tconfig.h"
3438fd1498Szrj #include "tsystem.h"
3538fd1498Szrj #if !defined(inhibit_libc) && !defined(__OpenBSD__)
3638fd1498Szrj #include <elf.h> /* Get DT_CONFIG. */
3738fd1498Szrj #endif
3838fd1498Szrj #include "coretypes.h"
3938fd1498Szrj #include "tm.h"
4038fd1498Szrj #include "libgcc_tm.h"
4138fd1498Szrj #include "dwarf2.h"
4238fd1498Szrj #include "unwind.h"
4338fd1498Szrj #define NO_BASE_OF_ENCODED_VALUE
4438fd1498Szrj #include "unwind-pe.h"
4538fd1498Szrj #include "unwind-dw2-fde.h"
4638fd1498Szrj #include "unwind-compat.h"
4738fd1498Szrj #include "gthr.h"
4838fd1498Szrj
4938fd1498Szrj #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
5038fd1498Szrj && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
5138fd1498Szrj || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
5238fd1498Szrj # define USE_PT_GNU_EH_FRAME
5338fd1498Szrj #endif
5438fd1498Szrj
5538fd1498Szrj #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
5638fd1498Szrj && defined(__BIONIC__)
5738fd1498Szrj # define USE_PT_GNU_EH_FRAME
5838fd1498Szrj #endif
5938fd1498Szrj
6038fd1498Szrj #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
6138fd1498Szrj && defined(TARGET_DL_ITERATE_PHDR) \
6238fd1498Szrj && defined(__linux__)
6338fd1498Szrj # define USE_PT_GNU_EH_FRAME
6438fd1498Szrj #endif
6538fd1498Szrj
6638fd1498Szrj #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
6738fd1498Szrj && defined(TARGET_DL_ITERATE_PHDR) \
682007c584SSascha Wildner && (defined(__DragonFly__) || defined(__FreeBSD__))
69*fca8e87bSSascha Wildner #ifndef ElfW
7038fd1498Szrj # define ElfW __ElfN
719cf0c62dSSascha Wildner #endif
7238fd1498Szrj # define USE_PT_GNU_EH_FRAME
7338fd1498Szrj #endif
7438fd1498Szrj
7538fd1498Szrj #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
7638fd1498Szrj && (defined(__OpenBSD__) || defined(__NetBSD__))
7738fd1498Szrj # define ElfW(type) Elf_##type
7838fd1498Szrj # define USE_PT_GNU_EH_FRAME
7938fd1498Szrj #endif
8038fd1498Szrj
8138fd1498Szrj #if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) \
8238fd1498Szrj && defined(TARGET_DL_ITERATE_PHDR) \
8338fd1498Szrj && defined(__sun__) && defined(__svr4__)
8438fd1498Szrj # define USE_PT_GNU_EH_FRAME
8538fd1498Szrj #endif
8638fd1498Szrj
8738fd1498Szrj #if defined(USE_PT_GNU_EH_FRAME)
8838fd1498Szrj
8938fd1498Szrj #include <link.h>
9038fd1498Szrj
9138fd1498Szrj #ifndef __RELOC_POINTER
9238fd1498Szrj # define __RELOC_POINTER(ptr, base) ((ptr) + (base))
9338fd1498Szrj #endif
9438fd1498Szrj
9538fd1498Szrj static const fde * _Unwind_Find_registered_FDE (void *pc, struct dwarf_eh_bases *bases);
9638fd1498Szrj
9738fd1498Szrj #define _Unwind_Find_FDE _Unwind_Find_registered_FDE
9838fd1498Szrj #include "unwind-dw2-fde.c"
9938fd1498Szrj #undef _Unwind_Find_FDE
10038fd1498Szrj
10138fd1498Szrj #ifndef PT_GNU_EH_FRAME
10238fd1498Szrj #define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
10338fd1498Szrj #endif
10438fd1498Szrj
10538fd1498Szrj struct unw_eh_callback_data
10638fd1498Szrj {
10738fd1498Szrj _Unwind_Ptr pc;
10838fd1498Szrj void *tbase;
10938fd1498Szrj void *dbase;
11038fd1498Szrj void *func;
11138fd1498Szrj const fde *ret;
11238fd1498Szrj int check_cache;
11338fd1498Szrj };
11438fd1498Szrj
11538fd1498Szrj struct unw_eh_frame_hdr
11638fd1498Szrj {
11738fd1498Szrj unsigned char version;
11838fd1498Szrj unsigned char eh_frame_ptr_enc;
11938fd1498Szrj unsigned char fde_count_enc;
12038fd1498Szrj unsigned char table_enc;
12138fd1498Szrj };
12238fd1498Szrj
12338fd1498Szrj #define FRAME_HDR_CACHE_SIZE 8
12438fd1498Szrj
12538fd1498Szrj static struct frame_hdr_cache_element
12638fd1498Szrj {
12738fd1498Szrj _Unwind_Ptr pc_low;
12838fd1498Szrj _Unwind_Ptr pc_high;
12938fd1498Szrj #if defined __FRV_FDPIC__ || defined __BFIN_FDPIC__
13038fd1498Szrj struct elf32_fdpic_loadaddr load_base;
13138fd1498Szrj #else
13238fd1498Szrj _Unwind_Ptr load_base;
13338fd1498Szrj #endif
13438fd1498Szrj const ElfW(Phdr) *p_eh_frame_hdr;
13538fd1498Szrj const ElfW(Phdr) *p_dynamic;
13638fd1498Szrj struct frame_hdr_cache_element *link;
13738fd1498Szrj } frame_hdr_cache[FRAME_HDR_CACHE_SIZE];
13838fd1498Szrj
13938fd1498Szrj static struct frame_hdr_cache_element *frame_hdr_cache_head;
14038fd1498Szrj
14138fd1498Szrj /* Like base_of_encoded_value, but take the base from a struct
14238fd1498Szrj unw_eh_callback_data instead of an _Unwind_Context. */
14338fd1498Szrj
14438fd1498Szrj static _Unwind_Ptr
base_from_cb_data(unsigned char encoding,struct unw_eh_callback_data * data)14538fd1498Szrj base_from_cb_data (unsigned char encoding, struct unw_eh_callback_data *data)
14638fd1498Szrj {
14738fd1498Szrj if (encoding == DW_EH_PE_omit)
14838fd1498Szrj return 0;
14938fd1498Szrj
15038fd1498Szrj switch (encoding & 0x70)
15138fd1498Szrj {
15238fd1498Szrj case DW_EH_PE_absptr:
15338fd1498Szrj case DW_EH_PE_pcrel:
15438fd1498Szrj case DW_EH_PE_aligned:
15538fd1498Szrj return 0;
15638fd1498Szrj
15738fd1498Szrj case DW_EH_PE_textrel:
15838fd1498Szrj return (_Unwind_Ptr) data->tbase;
15938fd1498Szrj case DW_EH_PE_datarel:
16038fd1498Szrj return (_Unwind_Ptr) data->dbase;
16138fd1498Szrj default:
16238fd1498Szrj gcc_unreachable ();
16338fd1498Szrj }
16438fd1498Szrj }
16538fd1498Szrj
16638fd1498Szrj static int
_Unwind_IteratePhdrCallback(struct dl_phdr_info * info,size_t size,void * ptr)16738fd1498Szrj _Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
16838fd1498Szrj {
16938fd1498Szrj struct unw_eh_callback_data *data = (struct unw_eh_callback_data *) ptr;
17038fd1498Szrj const ElfW(Phdr) *phdr, *p_eh_frame_hdr, *p_dynamic;
17138fd1498Szrj long n, match;
17238fd1498Szrj #if defined __FRV_FDPIC__ || defined __BFIN_FDPIC__
17338fd1498Szrj struct elf32_fdpic_loadaddr load_base;
17438fd1498Szrj #else
17538fd1498Szrj _Unwind_Ptr load_base;
17638fd1498Szrj #endif
17738fd1498Szrj const unsigned char *p;
17838fd1498Szrj const struct unw_eh_frame_hdr *hdr;
17938fd1498Szrj _Unwind_Ptr eh_frame;
18038fd1498Szrj struct object ob;
18138fd1498Szrj _Unwind_Ptr pc_low = 0, pc_high = 0;
18238fd1498Szrj
18338fd1498Szrj struct ext_dl_phdr_info
18438fd1498Szrj {
18538fd1498Szrj ElfW(Addr) dlpi_addr;
18638fd1498Szrj const char *dlpi_name;
18738fd1498Szrj const ElfW(Phdr) *dlpi_phdr;
18838fd1498Szrj ElfW(Half) dlpi_phnum;
18938fd1498Szrj unsigned long long int dlpi_adds;
19038fd1498Szrj unsigned long long int dlpi_subs;
19138fd1498Szrj };
19238fd1498Szrj
19338fd1498Szrj match = 0;
19438fd1498Szrj phdr = info->dlpi_phdr;
19538fd1498Szrj load_base = info->dlpi_addr;
19638fd1498Szrj p_eh_frame_hdr = NULL;
19738fd1498Szrj p_dynamic = NULL;
19838fd1498Szrj
19938fd1498Szrj struct frame_hdr_cache_element *prev_cache_entry = NULL,
20038fd1498Szrj *last_cache_entry = NULL;
20138fd1498Szrj
20238fd1498Szrj if (data->check_cache && size >= sizeof (struct ext_dl_phdr_info))
20338fd1498Szrj {
20438fd1498Szrj static unsigned long long adds = -1ULL, subs;
20538fd1498Szrj struct ext_dl_phdr_info *einfo = (struct ext_dl_phdr_info *) info;
20638fd1498Szrj
20738fd1498Szrj /* We use a least recently used cache replacement policy. Also,
20838fd1498Szrj the most recently used cache entries are placed at the head
20938fd1498Szrj of the search chain. */
21038fd1498Szrj
21138fd1498Szrj if (einfo->dlpi_adds == adds && einfo->dlpi_subs == subs)
21238fd1498Szrj {
21338fd1498Szrj /* Find data->pc in shared library cache.
21438fd1498Szrj Set load_base, p_eh_frame_hdr and p_dynamic
21538fd1498Szrj plus match from the cache and goto
21638fd1498Szrj "Read .eh_frame_hdr header." below. */
21738fd1498Szrj
21838fd1498Szrj struct frame_hdr_cache_element *cache_entry;
21938fd1498Szrj
22038fd1498Szrj for (cache_entry = frame_hdr_cache_head;
22138fd1498Szrj cache_entry;
22238fd1498Szrj cache_entry = cache_entry->link)
22338fd1498Szrj {
22438fd1498Szrj if (data->pc >= cache_entry->pc_low
22538fd1498Szrj && data->pc < cache_entry->pc_high)
22638fd1498Szrj {
22738fd1498Szrj load_base = cache_entry->load_base;
22838fd1498Szrj p_eh_frame_hdr = cache_entry->p_eh_frame_hdr;
22938fd1498Szrj p_dynamic = cache_entry->p_dynamic;
23038fd1498Szrj
23138fd1498Szrj /* And move the entry we're using to the head. */
23238fd1498Szrj if (cache_entry != frame_hdr_cache_head)
23338fd1498Szrj {
23438fd1498Szrj prev_cache_entry->link = cache_entry->link;
23538fd1498Szrj cache_entry->link = frame_hdr_cache_head;
23638fd1498Szrj frame_hdr_cache_head = cache_entry;
23738fd1498Szrj }
23838fd1498Szrj goto found;
23938fd1498Szrj }
24038fd1498Szrj
24138fd1498Szrj last_cache_entry = cache_entry;
24238fd1498Szrj /* Exit early if we found an unused entry. */
24338fd1498Szrj if ((cache_entry->pc_low | cache_entry->pc_high) == 0)
24438fd1498Szrj break;
24538fd1498Szrj if (cache_entry->link != NULL)
24638fd1498Szrj prev_cache_entry = cache_entry;
24738fd1498Szrj }
24838fd1498Szrj }
24938fd1498Szrj else
25038fd1498Szrj {
25138fd1498Szrj adds = einfo->dlpi_adds;
25238fd1498Szrj subs = einfo->dlpi_subs;
25338fd1498Szrj /* Initialize the cache. Create a chain of cache entries,
25438fd1498Szrj with the final one terminated by a NULL link. */
25538fd1498Szrj int i;
25638fd1498Szrj for (i = 0; i < FRAME_HDR_CACHE_SIZE; i++)
25738fd1498Szrj {
25838fd1498Szrj frame_hdr_cache[i].pc_low = 0;
25938fd1498Szrj frame_hdr_cache[i].pc_high = 0;
26038fd1498Szrj frame_hdr_cache[i].link = &frame_hdr_cache[i+1];
26138fd1498Szrj }
26238fd1498Szrj frame_hdr_cache[i-1].link = NULL;
26338fd1498Szrj frame_hdr_cache_head = &frame_hdr_cache[0];
26438fd1498Szrj data->check_cache = 0;
26538fd1498Szrj }
26638fd1498Szrj }
26738fd1498Szrj
26838fd1498Szrj /* Make sure struct dl_phdr_info is at least as big as we need. */
26938fd1498Szrj if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
27038fd1498Szrj + sizeof (info->dlpi_phnum))
27138fd1498Szrj return -1;
27238fd1498Szrj
27338fd1498Szrj /* See if PC falls into one of the loaded segments. Find the eh_frame
27438fd1498Szrj segment at the same time. */
27538fd1498Szrj for (n = info->dlpi_phnum; --n >= 0; phdr++)
27638fd1498Szrj {
27738fd1498Szrj if (phdr->p_type == PT_LOAD)
27838fd1498Szrj {
27938fd1498Szrj _Unwind_Ptr vaddr = (_Unwind_Ptr)
28038fd1498Szrj __RELOC_POINTER (phdr->p_vaddr, load_base);
28138fd1498Szrj if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
28238fd1498Szrj {
28338fd1498Szrj match = 1;
28438fd1498Szrj pc_low = vaddr;
28538fd1498Szrj pc_high = vaddr + phdr->p_memsz;
28638fd1498Szrj }
28738fd1498Szrj }
28838fd1498Szrj else if (phdr->p_type == PT_GNU_EH_FRAME)
28938fd1498Szrj p_eh_frame_hdr = phdr;
29038fd1498Szrj #ifdef PT_SUNW_UNWIND
29138fd1498Szrj /* Sun ld emits PT_SUNW_UNWIND .eh_frame_hdr sections instead of
29238fd1498Szrj PT_SUNW_EH_FRAME/PT_GNU_EH_FRAME, so accept them as well. */
29338fd1498Szrj else if (phdr->p_type == PT_SUNW_UNWIND)
29438fd1498Szrj p_eh_frame_hdr = phdr;
29538fd1498Szrj #endif
29638fd1498Szrj else if (phdr->p_type == PT_DYNAMIC)
29738fd1498Szrj p_dynamic = phdr;
29838fd1498Szrj }
29938fd1498Szrj
30038fd1498Szrj if (!match)
30138fd1498Szrj return 0;
30238fd1498Szrj
30338fd1498Szrj if (size >= sizeof (struct ext_dl_phdr_info))
30438fd1498Szrj {
30538fd1498Szrj /* Move the cache entry we're about to overwrite to the head of
30638fd1498Szrj the list. If either last_cache_entry or prev_cache_entry are
30738fd1498Szrj NULL, that cache entry is already at the head. */
30838fd1498Szrj if (last_cache_entry != NULL && prev_cache_entry != NULL)
30938fd1498Szrj {
31038fd1498Szrj prev_cache_entry->link = last_cache_entry->link;
31138fd1498Szrj last_cache_entry->link = frame_hdr_cache_head;
31238fd1498Szrj frame_hdr_cache_head = last_cache_entry;
31338fd1498Szrj }
31438fd1498Szrj
31538fd1498Szrj frame_hdr_cache_head->load_base = load_base;
31638fd1498Szrj frame_hdr_cache_head->p_eh_frame_hdr = p_eh_frame_hdr;
31738fd1498Szrj frame_hdr_cache_head->p_dynamic = p_dynamic;
31838fd1498Szrj frame_hdr_cache_head->pc_low = pc_low;
31938fd1498Szrj frame_hdr_cache_head->pc_high = pc_high;
32038fd1498Szrj }
32138fd1498Szrj
32238fd1498Szrj found:
32338fd1498Szrj
32438fd1498Szrj if (!p_eh_frame_hdr)
32538fd1498Szrj return 0;
32638fd1498Szrj
32738fd1498Szrj /* Read .eh_frame_hdr header. */
32838fd1498Szrj hdr = (const struct unw_eh_frame_hdr *)
32938fd1498Szrj __RELOC_POINTER (p_eh_frame_hdr->p_vaddr, load_base);
33038fd1498Szrj if (hdr->version != 1)
33138fd1498Szrj return 1;
33238fd1498Szrj
33338fd1498Szrj #ifdef CRT_GET_RFIB_DATA
33438fd1498Szrj # ifdef __i386__
33538fd1498Szrj data->dbase = NULL;
33638fd1498Szrj if (p_dynamic)
33738fd1498Szrj {
33838fd1498Szrj /* For dynamically linked executables and shared libraries,
33938fd1498Szrj DT_PLTGOT is the gp value for that object. */
34038fd1498Szrj ElfW(Dyn) *dyn = (ElfW(Dyn) *)
34138fd1498Szrj __RELOC_POINTER (p_dynamic->p_vaddr, load_base);
34238fd1498Szrj for (; dyn->d_tag != DT_NULL ; dyn++)
34338fd1498Szrj if (dyn->d_tag == DT_PLTGOT)
34438fd1498Szrj {
34538fd1498Szrj data->dbase = (void *) dyn->d_un.d_ptr;
34638fd1498Szrj #if defined __linux__
34738fd1498Szrj /* On IA-32 Linux, _DYNAMIC is writable and GLIBC has
34838fd1498Szrj relocated it. */
34938fd1498Szrj #elif defined __sun__ && defined __svr4__
35038fd1498Szrj /* On Solaris 2/x86, we need to do this ourselves. */
35138fd1498Szrj data->dbase += load_base;
35238fd1498Szrj #endif
35338fd1498Szrj break;
35438fd1498Szrj }
35538fd1498Szrj }
35638fd1498Szrj # elif (defined __FRV_FDPIC__ || defined __BFIN_FDPIC__) && defined __linux__
35738fd1498Szrj data->dbase = load_base.got_value;
35838fd1498Szrj # else
35938fd1498Szrj # error What is DW_EH_PE_datarel base on this platform?
36038fd1498Szrj # endif
36138fd1498Szrj #endif
36238fd1498Szrj
36338fd1498Szrj p = read_encoded_value_with_base (hdr->eh_frame_ptr_enc,
36438fd1498Szrj base_from_cb_data (hdr->eh_frame_ptr_enc,
36538fd1498Szrj data),
36638fd1498Szrj (const unsigned char *) (hdr + 1),
36738fd1498Szrj &eh_frame);
36838fd1498Szrj
36938fd1498Szrj /* We require here specific table encoding to speed things up.
37038fd1498Szrj Also, DW_EH_PE_datarel here means using PT_GNU_EH_FRAME start
37138fd1498Szrj as base, not the processor specific DW_EH_PE_datarel. */
37238fd1498Szrj if (hdr->fde_count_enc != DW_EH_PE_omit
37338fd1498Szrj && hdr->table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
37438fd1498Szrj {
37538fd1498Szrj _Unwind_Ptr fde_count;
37638fd1498Szrj
37738fd1498Szrj p = read_encoded_value_with_base (hdr->fde_count_enc,
37838fd1498Szrj base_from_cb_data (hdr->fde_count_enc,
37938fd1498Szrj data),
38038fd1498Szrj p, &fde_count);
38138fd1498Szrj /* Shouldn't happen. */
38238fd1498Szrj if (fde_count == 0)
38338fd1498Szrj return 1;
38438fd1498Szrj if ((((_Unwind_Ptr) p) & 3) == 0)
38538fd1498Szrj {
38638fd1498Szrj struct fde_table {
38738fd1498Szrj signed initial_loc __attribute__ ((mode (SI)));
38838fd1498Szrj signed fde __attribute__ ((mode (SI)));
38938fd1498Szrj };
39038fd1498Szrj const struct fde_table *table = (const struct fde_table *) p;
39138fd1498Szrj size_t lo, hi, mid;
39238fd1498Szrj _Unwind_Ptr data_base = (_Unwind_Ptr) hdr;
39338fd1498Szrj fde *f;
39438fd1498Szrj unsigned int f_enc, f_enc_size;
39538fd1498Szrj _Unwind_Ptr range;
39638fd1498Szrj
39738fd1498Szrj mid = fde_count - 1;
39838fd1498Szrj if (data->pc < table[0].initial_loc + data_base)
39938fd1498Szrj return 1;
40038fd1498Szrj else if (data->pc < table[mid].initial_loc + data_base)
40138fd1498Szrj {
40238fd1498Szrj lo = 0;
40338fd1498Szrj hi = mid;
40438fd1498Szrj
40538fd1498Szrj while (lo < hi)
40638fd1498Szrj {
40738fd1498Szrj mid = (lo + hi) / 2;
40838fd1498Szrj if (data->pc < table[mid].initial_loc + data_base)
40938fd1498Szrj hi = mid;
41038fd1498Szrj else if (data->pc >= table[mid + 1].initial_loc + data_base)
41138fd1498Szrj lo = mid + 1;
41238fd1498Szrj else
41338fd1498Szrj break;
41438fd1498Szrj }
41538fd1498Szrj
41638fd1498Szrj gcc_assert (lo < hi);
41738fd1498Szrj }
41838fd1498Szrj
41938fd1498Szrj f = (fde *) (table[mid].fde + data_base);
42038fd1498Szrj f_enc = get_fde_encoding (f);
42138fd1498Szrj f_enc_size = size_of_encoded_value (f_enc);
42238fd1498Szrj read_encoded_value_with_base (f_enc & 0x0f, 0,
42338fd1498Szrj &f->pc_begin[f_enc_size], &range);
42438fd1498Szrj if (data->pc < table[mid].initial_loc + data_base + range)
42538fd1498Szrj data->ret = f;
42638fd1498Szrj data->func = (void *) (table[mid].initial_loc + data_base);
42738fd1498Szrj return 1;
42838fd1498Szrj }
42938fd1498Szrj }
43038fd1498Szrj
43138fd1498Szrj /* We have no sorted search table, so need to go the slow way.
43238fd1498Szrj As soon as GLIBC will provide API so to notify that a library has been
43338fd1498Szrj removed, we could cache this (and thus use search_object). */
43438fd1498Szrj ob.pc_begin = NULL;
43538fd1498Szrj ob.tbase = data->tbase;
43638fd1498Szrj ob.dbase = data->dbase;
43738fd1498Szrj ob.u.single = (fde *) eh_frame;
43838fd1498Szrj ob.s.i = 0;
43938fd1498Szrj ob.s.b.mixed_encoding = 1; /* Need to assume worst case. */
44038fd1498Szrj data->ret = linear_search_fdes (&ob, (fde *) eh_frame, (void *) data->pc);
44138fd1498Szrj if (data->ret != NULL)
44238fd1498Szrj {
44338fd1498Szrj _Unwind_Ptr func;
44438fd1498Szrj unsigned int encoding = get_fde_encoding (data->ret);
44538fd1498Szrj
44638fd1498Szrj read_encoded_value_with_base (encoding,
44738fd1498Szrj base_from_cb_data (encoding, data),
44838fd1498Szrj data->ret->pc_begin, &func);
44938fd1498Szrj data->func = (void *) func;
45038fd1498Szrj }
45138fd1498Szrj return 1;
45238fd1498Szrj }
45338fd1498Szrj
45438fd1498Szrj const fde *
_Unwind_Find_FDE(void * pc,struct dwarf_eh_bases * bases)45538fd1498Szrj _Unwind_Find_FDE (void *pc, struct dwarf_eh_bases *bases)
45638fd1498Szrj {
45738fd1498Szrj struct unw_eh_callback_data data;
45838fd1498Szrj const fde *ret;
45938fd1498Szrj
46038fd1498Szrj ret = _Unwind_Find_registered_FDE (pc, bases);
46138fd1498Szrj if (ret != NULL)
46238fd1498Szrj return ret;
46338fd1498Szrj
46438fd1498Szrj data.pc = (_Unwind_Ptr) pc;
46538fd1498Szrj data.tbase = NULL;
46638fd1498Szrj data.dbase = NULL;
46738fd1498Szrj data.func = NULL;
46838fd1498Szrj data.ret = NULL;
46938fd1498Szrj data.check_cache = 1;
47038fd1498Szrj
47138fd1498Szrj if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
47238fd1498Szrj return NULL;
47338fd1498Szrj
47438fd1498Szrj if (data.ret)
47538fd1498Szrj {
47638fd1498Szrj bases->tbase = data.tbase;
47738fd1498Szrj bases->dbase = data.dbase;
47838fd1498Szrj bases->func = data.func;
47938fd1498Szrj }
48038fd1498Szrj return data.ret;
48138fd1498Szrj }
48238fd1498Szrj
48338fd1498Szrj #else
48438fd1498Szrj /* Prevent multiple include of header files. */
48538fd1498Szrj #define _Unwind_Find_FDE _Unwind_Find_FDE
48638fd1498Szrj #include "unwind-dw2-fde.c"
48738fd1498Szrj #endif
48838fd1498Szrj
48938fd1498Szrj #if defined (USE_GAS_SYMVER) && defined (SHARED) && defined (USE_LIBUNWIND_EXCEPTIONS)
49038fd1498Szrj alias (_Unwind_Find_FDE);
49138fd1498Szrj #endif
492