2 Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
18 or both in parallel, as here.
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
37 #include "encoded-value.h"
40 compare_fde (const void *a, const void *b)
42 const struct dwarf_fde *fde1 = a;
43 const struct dwarf_fde *fde2 = b;
45 /* Find out which of the two arguments is the search value.
46 It has end offset 0. */
49 if (fde1->start < fde2->start)
51 if (fde1->start >= fde2->end)
56 if (fde2->start < fde1->start)
58 if (fde2->start >= fde1->end)
65 static struct dwarf_fde *
66 intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
68 /* Look up the new entry's CIE. */
69 struct dwarf_cie *cie = __libdw_find_cie (cache, entry->CIE_pointer);
73 struct dwarf_fde *fde = malloc (sizeof (struct dwarf_fde));
76 __libdw_seterrno (DWARF_E_NOMEM);
80 fde->instructions = entry->start;
81 fde->instructions_end = entry->end;
82 if (unlikely (read_encoded_value (cache, cie->fde_encoding,
83 &fde->instructions, &fde->start))
84 || unlikely (read_encoded_value (cache, cie->fde_encoding & 0x0f,
85 &fde->instructions, &fde->end)))
88 __libdw_seterrno (DWARF_E_INVALID_DWARF);
91 fde->end += fde->start;
93 /* Make sure the fde actually covers a real code range. */
94 if (fde->start >= fde->end)
102 if (cie->sized_augmentation_data)
104 /* The CIE augmentation says the FDE has a DW_FORM_block
105 before its actual instruction stream. */
107 get_uleb128 (len, fde->instructions, fde->instructions_end);
108 if ((Dwarf_Word) (fde->instructions_end - fde->instructions) < len)
111 __libdw_seterrno (DWARF_E_INVALID_DWARF);
114 fde->instructions += len;
117 /* We had to understand all of the CIE augmentation string.
118 We've recorded the number of data bytes in FDEs. */
119 fde->instructions += cie->fde_augmentation_data_size;
121 /* Add the new entry to the search tree. */
122 struct dwarf_fde **tres = tsearch (fde, &cache->fde_tree, &compare_fde);
126 __libdw_seterrno (DWARF_E_NOMEM);
129 else if (*tres != fde)
131 /* There is already an FDE in the cache that covers the same
132 address range. That is odd. Ignore this FDE. And just use
133 the one in the cache for consistency. */
143 __libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset)
145 Dwarf_CFI_Entry entry;
146 Dwarf_Off next_offset;
147 int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
148 &cache->data->d, CFI_IS_EH (cache),
149 offset, &next_offset, &entry);
154 __libdw_seterrno (DWARF_E_INVALID_DWARF);
158 if (unlikely (dwarf_cfi_cie_p (&entry)))
161 /* We have a new FDE to consider. */
162 struct dwarf_fde *fde = intern_fde (cache, &entry.fde);
163 if (fde == (void *) -1l || fde == NULL)
166 /* If this happened to be what we would have read next, notice it. */
167 if (cache->next_offset == offset)
168 cache->next_offset = next_offset;
173 /* Use a binary search table in .eh_frame_hdr format, yield an FDE offset. */
175 binary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address)
177 const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident,
178 cache->search_table_encoding,
180 if (unlikely (size == 0))
181 return (Dwarf_Off) -1l;
183 /* Dummy used by read_encoded_value. */
184 Elf_Data_Scn dummy_cfi_hdr_data =
186 .d = { .d_buf = (void *) cache->search_table,
187 .d_size = cache->search_table_len }
190 Dwarf_CFI dummy_cfi =
192 .e_ident = cache->e_ident,
193 .datarel = cache->search_table_vaddr,
194 .frame_vaddr = cache->search_table_vaddr,
195 .data = &dummy_cfi_hdr_data
198 size_t l = 0, u = cache->search_table_entries;
201 size_t idx = (l + u) / 2;
203 /* Max idx * size is checked against search_table len when
204 loading eh_frame_hdr. */
205 const uint8_t *p = &cache->search_table[idx * size];
207 if (unlikely (read_encoded_value (&dummy_cfi,
208 cache->search_table_encoding, &p,
218 if (unlikely (read_encoded_value (&dummy_cfi,
219 cache->search_table_encoding, &p,
223 /* If this is the last entry, its upper bound is assumed to be
224 the end of the module.
225 XXX really should be end of containing PT_LOAD segment */
226 if (l < cache->search_table_entries)
228 /* Look at the start address in the following entry. */
230 if (unlikely (read_encoded_value
231 (&dummy_cfi, cache->search_table_encoding, &p,
238 return fde - cache->frame_vaddr;
242 return (Dwarf_Off) -1l;
247 __libdw_find_fde (Dwarf_CFI *cache, Dwarf_Addr address)
249 /* Look for a cached FDE covering this address. */
251 const struct dwarf_fde fde_key = { .start = address, .end = 0 };
252 struct dwarf_fde **found = tfind (&fde_key, &cache->fde_tree, &compare_fde);
256 /* Use .eh_frame_hdr binary search table if possible. */
257 if (cache->search_table != NULL)
259 Dwarf_Off offset = binary_search_fde (cache, address);
260 if (offset == (Dwarf_Off) -1l)
262 struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset);
263 if (likely (fde != NULL))
265 /* Sanity check the address range. */
266 if (unlikely (address < fde->start))
268 __libdw_seterrno (DWARF_E_INVALID_DWARF);
271 /* .eh_frame_hdr does not indicate length covered by FDE. */
272 if (unlikely (address >= fde->end))
278 /* It's not there. Read more CFI entries until we find it. */
281 Dwarf_Off last_offset = cache->next_offset;
282 Dwarf_CFI_Entry entry;
283 int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
284 &cache->data->d, CFI_IS_EH (cache),
285 last_offset, &cache->next_offset,
291 if (cache->next_offset == last_offset)
292 /* We couldn't progress past the bogus FDE. */
294 /* Skip the loser and look at the next entry. */
298 if (dwarf_cfi_cie_p (&entry))
300 /* This is a CIE, not an FDE. We eagerly intern these
301 because the next FDE will usually refer to this CIE. */
302 __libdw_intern_cie (cache, last_offset, &entry.cie);
306 /* We have a new FDE to consider. */
307 struct dwarf_fde *fde = intern_fde (cache, &entry.fde);
309 if (fde == (void *) -1l) /* Bad FDE, but we can keep looking. */
312 if (fde == NULL) /* Bad data. */
315 /* Is this the one we're looking for? */
316 if (fde->start <= address && fde->end > address)
321 /* We found no FDE covering this address. */
322 __libdw_seterrno (DWARF_E_NO_MATCH);