125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* FDE reading. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2009-2010, 2014 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "cfi.h" 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <search.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "encoded-value.h" 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 4025b3c049e70834cf33790a28643ab058b507b35cBen Chengcompare_fde (const void *a, const void *b) 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const struct dwarf_fde *fde1 = a; 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const struct dwarf_fde *fde2 = b; 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Find out which of the two arguments is the search value. 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng It has end offset 0. */ 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde1->end == 0) 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde1->start < fde2->start) 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde1->start >= fde2->end) 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde2->start < fde1->start) 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 1; 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde2->start >= fde1->end) 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct dwarf_fde * 6625b3c049e70834cf33790a28643ab058b507b35cBen Chengintern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry) 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Look up the new entry's CIE. */ 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct dwarf_cie *cie = __libdw_find_cie (cache, entry->CIE_pointer); 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cie == NULL) 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (void *) -1l; 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct dwarf_fde *fde = malloc (sizeof (struct dwarf_fde)); 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde == NULL) 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_NOMEM); 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng fde->instructions = entry->start; 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fde->instructions_end = entry->end; 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (read_encoded_value (cache, cie->fde_encoding, 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &fde->instructions, &fde->start)) 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely (read_encoded_value (cache, cie->fde_encoding & 0x0f, 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng &fde->instructions, &fde->end))) 8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (fde); 8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdw_seterrno (DWARF_E_INVALID_DWARF); 8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fde->end += fde->start; 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng fde->cie = cie; 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cie->sized_augmentation_data) 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The CIE augmentation says the FDE has a DW_FORM_block 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng before its actual instruction stream. */ 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Word len; 10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes get_uleb128 (len, fde->instructions, fde->instructions_end); 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((Dwarf_Word) (fde->instructions_end - fde->instructions) < len) 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (fde); 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_DWARF); 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng fde->instructions += len; 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We had to understand all of the CIE augmentation string. 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng We've recorded the number of data bytes in FDEs. */ 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng fde->instructions += cie->fde_augmentation_data_size; 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Add the new entry to the search tree. */ 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (tsearch (fde, &cache->fde_tree, &compare_fde) == NULL) 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (fde); 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_NOMEM); 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fde; 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12525b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct dwarf_fde * 12625b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset) 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI_Entry entry; 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Off next_offset; 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = INTUSE(dwarf_next_cfi) (cache->e_ident, 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng &cache->data->d, CFI_IS_EH (cache), 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset, &next_offset, &entry); 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result != 0) 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result > 0) 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng invalid: 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_INVALID_DWARF); 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (dwarf_cfi_cie_p (&entry))) 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto invalid; 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have a new FDE to consider. */ 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct dwarf_fde *fde = intern_fde (cache, &entry.fde); 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde == (void *) -1l || fde == NULL) 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this happened to be what we would have read next, notice it. */ 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cache->next_offset == offset) 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cache->next_offset = next_offset; 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fde; 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Use a binary search table in .eh_frame_hdr format, yield an FDE offset. */ 15825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwarf_Off 15925b3c049e70834cf33790a28643ab058b507b35cBen Chengbinary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address) 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident, 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cache->search_table_encoding, 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng NULL); 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Dummy used by read_encoded_value. */ 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI dummy_cfi = 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .e_ident = cache->e_ident, 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .datarel = cache->search_table_vaddr, 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng .frame_vaddr = cache->search_table_vaddr, 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t l = 0, u = cache->search_table_entries; 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (l < u) 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t idx = (l + u) / 2; 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const uint8_t *p = &cache->search_table[idx * size]; 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr start; 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (read_encoded_value (&dummy_cfi, 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng cache->search_table_encoding, &p, 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng &start))) 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (address < start) 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng u = idx; 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes l = idx + 1; 18903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr fde; 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (read_encoded_value (&dummy_cfi, 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng cache->search_table_encoding, &p, 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &fde))) 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 19503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 19603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If this is the last entry, its upper bound is assumed to be 19703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the end of the module. 19803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes XXX really should be end of containing PT_LOAD segment */ 19903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (l < cache->search_table_entries) 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 20103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Look at the start address in the following entry. */ 20203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr end; 20303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (read_encoded_value 20403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes (&dummy_cfi, cache->search_table_encoding, &p, 20503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &end))) 20603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 20703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (address >= end) 20803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes continue; 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 21103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return fde - cache->frame_vaddr; 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (Dwarf_Off) -1l; 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21825b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct dwarf_fde * 21925b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libdw_find_fde (Dwarf_CFI *cache, Dwarf_Addr address) 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Look for a cached FDE covering this address. */ 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const struct dwarf_fde fde_key = { .start = address, .end = 0 }; 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct dwarf_fde **found = tfind (&fde_key, &cache->fde_tree, &compare_fde); 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (found != NULL) 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *found; 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Use .eh_frame_hdr binary search table if possible. */ 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cache->search_table != NULL) 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Off offset = binary_search_fde (cache, address); 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (offset == (Dwarf_Off) -1l) 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto no_match; 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset); 23603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (likely (fde != NULL)) 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 23803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Sanity check the address range. */ 23903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (address < fde->start)) 24003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 24103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdw_seterrno (DWARF_E_INVALID_DWARF); 24203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return NULL; 24303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 24403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* .eh_frame_hdr does not indicate length covered by FDE. */ 24503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (address >= fde->end)) 24603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes goto no_match; 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fde; 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It's not there. Read more CFI entries until we find it. */ 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (1) 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Off last_offset = cache->next_offset; 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_CFI_Entry entry; 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = INTUSE(dwarf_next_cfi) (cache->e_ident, 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng &cache->data->d, CFI_IS_EH (cache), 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng last_offset, &cache->next_offset, 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng &entry); 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result > 0) 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (result < 0) 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (cache->next_offset == last_offset) 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We couldn't progress past the bogus FDE. */ 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Skip the loser and look at the next entry. */ 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwarf_cfi_cie_p (&entry)) 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is a CIE, not an FDE. We eagerly intern these 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng because the next FDE will usually refer to this CIE. */ 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_intern_cie (cache, last_offset, &entry.cie); 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have a new FDE to consider. */ 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct dwarf_fde *fde = intern_fde (cache, &entry.fde); 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde == (void *) -1l) /* Bad FDE, but we can keep looking. */ 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde == NULL) /* Bad data. */ 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Is this the one we're looking for? */ 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fde->start <= address && fde->end > address) 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fde; 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng no_match: 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We found no FDE covering this address. */ 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdw_seterrno (DWARF_E_NO_MATCH); 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 298