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