]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Merge commit 'origin/master' into roland/unwind
authorRoland McGrath <roland@redhat.com>
Tue, 16 Jun 2009 04:50:08 +0000 (21:50 -0700)
committerRoland McGrath <roland@redhat.com>
Tue, 16 Jun 2009 04:50:08 +0000 (21:50 -0700)
Conflicts:
backends/ChangeLog
libdw/ChangeLog
libdw/dwarf_getlocation.c

1  2 
backends/ChangeLog
libdw/ChangeLog
libdw/dwarf_frame_cfa.c
libdw/dwarf_frame_register.c
libdw/dwarf_getcfi_elf.c
libdw/dwarf_getlocation.c
libdw/libdwP.h
libdwfl/ChangeLog

index 30c0c4c1e20d9a0557b677b6d2686473cab37ab2,a1aa351fc039a45793c17a7ad7e47fc7f8ba4c17..3793519b2a4867e44a21543134ff6f9d31bd93e9
@@@ -1,13 -1,8 +1,18 @@@
 +2009-04-19  Roland McGrath  <roland@redhat.com>
 +
 +      * x86_64_cfi.c (x86_64_abi_cfi): New file.
 +      * Makefile.am (x86_64_SRCS): Add it.
 +      * x86_64_init.c (x86_64_init): Add initializer.
 +
 +      * i386_cfi.c (i386_abi_cfi): New file.
 +      * Makefile.am (i386_SRCS): Add it.
 +      * i386_init.c (i386_init): Initialize abi_cfi hook.
 +
+ 2009-06-01  Ulrich Drepper  <drepper@redhat.com>
+       * i386_reloc.def: Add IRELATIVE entry.
+       * x86_64_reloc.def: Likewise.
  2009-04-16  Roland McGrath  <roland@redhat.com>
  
        * arm_regs.c (arm_register_info): Handle VFP registers.
diff --cc libdw/ChangeLog
index a5c8548a01774a548328f1f6ac0975418ec8c33c,525bb329b6629dc877fc411b19d0840a09c7e43f..40b1c61b581c4606aa34f2238624a88cd507c705
@@@ -1,57 -1,37 +1,91 @@@
 +2009-04-19  Roland McGrath  <roland@redhat.com>
 +
 +      * libdw.map (ELFUTILS_0.141): Add dwfl_addrframe,
 +      dwfl_module_dwarf_cfi, dwfl_module_eh_cfi.
 +
 +      * libdwP.h (struct Dwarf): Add member `cfi'.
 +      * dwarf_end.c (dwarf_end): Call __libdw_destroy_frame_cache on it.
 +      * dwarf_getcfi.c: New file.
 +      * dwarf_getcfi_elf.c: New file.
 +      * dwarf_cfi_end.c: New file.
 +      * dwarf_cfi_addrframe.c: New file.
 +      * dwarf_frame_cfa.c: New file.
 +      * dwarf_frame_register.c: New file.
 +      * dwarf_frame_return_address_register.c: New file.
 +      * Makefile.am (libdw_a_SOURCES): Add them.
 +      * unwind.h: Declare those functions.
 +      * libdw.map (ELFUTILS_0.141): Export them.
 +
 +      * dwarf_getlocation.c (__libdw_intern_expression): New function,
 +      broken out of ...
 +      (getlocation): ... here, call it.
 +      * libdwP.h: Declare it.
 +
 +      * cie.c: New file.
 +      * fde.c: New file.
 +      * frame-cache.c: New file.
 +      * cfi.c: New file.
 +      * cfi.h: New file.
 +      * encoded-value.h: New file.
 +      * Makefile.am (libdw_a_SOURCES, noinst_HEADERS): Add them.
 +      * libdwP.h: Add DWARF_E_INVALID_CFI to errors enum.
 +      * dwarf_error.c (errmsgs): Add element for it.
 +
 +      * dwarf_next_cfi.c: New file.
 +      * Makefile.am (libdw_a_SOURCES): Add it.
 +      * libdw.h (Dwarf_CIE, Dwarf_FDE, Dwarf_CIE_Entry): New types.
 +      Declare dwarf_next_cfi.
 +      * libdw.map (ELFUTILS_0.141): Add dwarf_next_cfi.
 +
 +      * memory-access.h [! ALLOW_UNALIGNED]
 +      (read_2ubyte_unaligned): Renamed to ...
 +      (read_2ubyte_unaligned_1): ... this.  Take bool rather than Dwarf *.
 +      (read_2ubyte_unaligned): Define as macro passing dbg->other_byte_order.
 +      (read_2sbyte_unaligned): Likewise.
 +      (read_4ubyte_unaligned): Likewise.
 +      (read_4sbyte_unaligned): Likewise.
 +      (read_8ubyte_unaligned): Likewise.
 +      (read_8sbyte_unaligned): Likewise.
 +
 +2009-04-03  Roland McGrath  <roland@redhat.com>
 +
 +      * libdwP.h (IDX_eh_frame): Remove it.
 +      * dwarf_begin_elf.c (dwarf_scnnames): Remove its element.
 +
+ 2009-05-05  Petr Machata  <pmachata@redhat.com>
+       * libdwP.h (__libdw_formptr): Declare new function.
+       * dwarf_formudata.c: Implement it here.
+       * dwarf_getlocation.c (dwarf_getlocation_addr):
+       Call it instead of hand-rolled offset handling code.
+       * dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+       * dwarf_ranges.c (dwarf_ranges): Likewise.
+ 2009-05-04  Petr Machata  <pmachata@redhat.com>
+       * libdwP.h (__libdw_read_begin_end_pair_inc): Declare new function.
+       * dwarf_ranges.c: Implement it here.
+       (dwarf_ranges): Call it.
+       * dwarf_getlocation.c (dwarf_getlocation_addr): Call it also here.
+ 2009-04-23  Petr Machata  <pmachata@redhat.com>
+       * dwarf_formaddr.c (dwarf_formaddr): Call __libdw_read_* instead
+       of read_*ubyte_unaligned.
+       * dwarf_formref_die.c (dwarf_formref_die): Likewise.
+       * dwarf_formstring.c (dwarf_formstring): Likewise.
+       * dwarf_formudate.c (dwarf_formudata): Likewise.
+       * dwarf_getaranges.c (dwarf_getaranges): Likewise.
+       * dwarf_getlocation.c (dwarf_getlocation_addr): Likewise.
+       * dwarf_getpubnames.c (get_offsets): Likewise.
+       * dwarf_nextcu.c (dwarf_nextcu): Likewise.
+ 2009-04-23  Petr Machata  <pmachata@redhat.com>
+       * libdwP.h (__libdw_read_addr_inc, __libdw_read_off_inc,
+       __libdw_read_addr, __libdw_read_off): Add four new internal
+       functions.
  2009-05-07  Roland McGrath  <roland@redhat.com>
  
        * dwarf_getmacros.c (dwarf_getmacros): Use absolute section offset in
index a491fa32b98dd465201e142618e38aedb1e6f966,0000000000000000000000000000000000000000..331b934d83108021c3a4518b3d646e02c095f3d3
mode 100644,000000..100644
--- /dev/null
@@@ -1,100 -1,0 +1,101 @@@
-                                               ops, &nops);
 +/* Get CFA expression for frame.
 +   Copyright (C) 2006, 2007, 2009 Red Hat, Inc.
 +   This file is part of Red Hat elfutils.
 +
 +   Red Hat elfutils is free software; you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by the
 +   Free Software Foundation; version 2 of the License.
 +
 +   Red Hat elfutils is distributed in the hope that it will be useful, but
 +   WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +   General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License along
 +   with Red Hat elfutils; if not, write to the Free Software Foundation,
 +   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
 +
 +   In addition, as a special exception, Red Hat, Inc. gives You the
 +   additional right to link the code of Red Hat elfutils with code licensed
 +   under any Open Source Initiative certified open source license
 +   (http://www.opensource.org/licenses/index.php) which requires the
 +   distribution of source code with any binary distribution and to
 +   distribute linked combinations of the two.  Non-GPL Code permitted under
 +   this exception must only link to the code of Red Hat elfutils through
 +   those well defined interfaces identified in the file named EXCEPTION
 +   found in the source code files (the "Approved Interfaces").  The files
 +   of Non-GPL Code may instantiate templates or use macros or inline
 +   functions from the Approved Interfaces without causing the resulting
 +   work to be covered by the GNU General Public License.  Only Red Hat,
 +   Inc. may make changes or additions to the list of Approved Interfaces.
 +   Red Hat's grant of this exception is conditioned upon your not adding
 +   any new exceptions.  If you wish to add a new Approved Interface or
 +   exception, please contact Red Hat.  You must obey the GNU General Public
 +   License in all respects for all of the Red Hat elfutils code and other
 +   code used in conjunction with Red Hat elfutils except the Non-GPL Code
 +   covered by this exception.  If you modify this file, you may extend this
 +   exception to your version of the file, but you are not obligated to do
 +   so.  If you do not wish to provide this exception without modification,
 +   you must delete this exception statement from your version and license
 +   this file solely under the GPL without exception.
 +
 +   Red Hat elfutils is an included package of the Open Invention Network.
 +   An included package of the Open Invention Network is a package for which
 +   Open Invention Network licensees cross-license their patents.  No patent
 +   license is granted, either expressly or impliedly, by designation as an
 +   included package.  Should you wish to participate in the Open Invention
 +   Network licensing program, please visit www.openinventionnetwork.com
 +   <http://www.openinventionnetwork.com>.  */
 +
 +#ifdef HAVE_CONFIG_H
 +# include <config.h>
 +#endif
 +
 +#include "cfi.h"
 +#include <dwarf.h>
 +#include <stdlib.h>
 +
 +int
 +dwarf_frame_cfa (fs, ops)
 +     Dwarf_Frame *fs;
 +     Dwarf_Op **ops;
 +{
 +  /* Maybe there was a previous error.  */
 +  if (fs == NULL)
 +    return -1;
 +
 +  switch (fs->cfa_rule)
 +    {
 +    case cfa_undefined:
 +      *ops = NULL;
 +      return 0;
 +
 +    case cfa_offset:
 +      /* The Dwarf_Op was already fully initialized by execute_cfi.  */
 +      *ops = &fs->cfa_data.offset;
 +      return 1;
 +
 +    case cfa_expr:
 +      {
 +      unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32
 +                                   ? 4 : 8);
 +      size_t nops;
 +
 +      /* Parse the expression into internal form.  */
 +      int result = __libdw_intern_expression (NULL,
 +                                              fs->cache->other_byte_order,
 +                                              address_size,
 +                                              &fs->cache->expr_tree,
 +                                              &fs->cfa_data.expr,
++                                              ops, &nops,
++                                              IDX_debug_frame);
 +      return result ?: (int) nops;
 +      }
 +
 +    default:
 +      abort ();
 +    }
 +
 +  /*NOTREACHED*/
 +  return -1;
 +}
index dc414d0f8735801cce2657bfa7b81c4e59a74a73,0000000000000000000000000000000000000000..61e6ee2fa8637837595c6d438c6192d41ecd25a7
mode 100644,000000..100644
--- /dev/null
@@@ -1,143 -1,0 +1,144 @@@
-                                      &block, ops, nops) < 0)
 +/* Get register location expression for frame.
 +   Copyright (C) 2006, 2007, 2009 Red Hat, Inc.
 +   This file is part of Red Hat elfutils.
 +
 +   Red Hat elfutils is free software; you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by the
 +   Free Software Foundation; version 2 of the License.
 +
 +   Red Hat elfutils is distributed in the hope that it will be useful, but
 +   WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +   General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License along
 +   with Red Hat elfutils; if not, write to the Free Software Foundation,
 +   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
 +
 +   In addition, as a special exception, Red Hat, Inc. gives You the
 +   additional right to link the code of Red Hat elfutils with code licensed
 +   under any Open Source Initiative certified open source license
 +   (http://www.opensource.org/licenses/index.php) which requires the
 +   distribution of source code with any binary distribution and to
 +   distribute linked combinations of the two.  Non-GPL Code permitted under
 +   this exception must only link to the code of Red Hat elfutils through
 +   those well defined interfaces identified in the file named EXCEPTION
 +   found in the source code files (the "Approved Interfaces").  The files
 +   of Non-GPL Code may instantiate templates or use macros or inline
 +   functions from the Approved Interfaces without causing the resulting
 +   work to be covered by the GNU General Public License.  Only Red Hat,
 +   Inc. may make changes or additions to the list of Approved Interfaces.
 +   Red Hat's grant of this exception is conditioned upon your not adding
 +   any new exceptions.  If you wish to add a new Approved Interface or
 +   exception, please contact Red Hat.  You must obey the GNU General Public
 +   License in all respects for all of the Red Hat elfutils code and other
 +   code used in conjunction with Red Hat elfutils except the Non-GPL Code
 +   covered by this exception.  If you modify this file, you may extend this
 +   exception to your version of the file, but you are not obligated to do
 +   so.  If you do not wish to provide this exception without modification,
 +   you must delete this exception statement from your version and license
 +   this file solely under the GPL without exception.
 +
 +   Red Hat elfutils is an included package of the Open Invention Network.
 +   An included package of the Open Invention Network is a package for which
 +   Open Invention Network licensees cross-license their patents.  No patent
 +   license is granted, either expressly or impliedly, by designation as an
 +   included package.  Should you wish to participate in the Open Invention
 +   Network licensing program, please visit www.openinventionnetwork.com
 +   <http://www.openinventionnetwork.com>.  */
 +
 +#ifdef HAVE_CONFIG_H
 +# include <config.h>
 +#endif
 +
 +#include "cfi.h"
 +#include <dwarf.h>
 +
 +int
 +dwarf_frame_register (fs, regno, ops_mem, ops, nops)
 +     Dwarf_Frame *fs;
 +     int regno;
 +     Dwarf_Op ops_mem[2];
 +     Dwarf_Op **ops;
 +     size_t *nops;
 +{
 +  /* Maybe there was a previous error.  */
 +  if (fs == NULL)
 +    return -1;
 +
 +  if (unlikely (regno < 0))
 +    {
 +      __libdw_seterrno (DWARF_E_INVALID_ACCESS);
 +      return -1;
 +    }
 +
 +  int result = 0;             /* A location, not a value.  */
 +
 +  if (unlikely ((size_t) regno >= fs->nregs))
 +    goto default_rule;
 +
 +  const struct dwarf_frame_register *reg = &fs->regs[regno];
 +
 +  switch (reg->rule)
 +    {
 +    case reg_unspecified:
 +    default_rule:
 +      /* Use the default rule for registers not yet mentioned in CFI.  */
 +      if (fs->cache->default_same_value)
 +      goto same_value;
 +      /*FALLTHROUGH*/
 +    case reg_undefined:
 +      /* The value is known to be unavailable.  */
 +      result = 1;
 +      /*FALLTHROUGH*/
 +    case reg_same_value:
 +    same_value:
 +      /* The location is not known here, but the caller might know it.  */
 +      *ops = NULL;
 +      *nops = 0;
 +      break;
 +
 +    case reg_val_offset:
 +      result = 1;             /* A value, not a location.  */
 +      /*FALLTHROUGH*/
 +    case reg_offset:
 +      ops_mem[0] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa };
 +      ops_mem[1] = (Dwarf_Op) { .atom = DW_OP_plus_uconst,
 +                              .number = reg->value };
 +      *ops = ops_mem;
 +      *nops = reg->value == 0 ? 1 : 2;
 +      break;
 +
 +    case reg_register:
 +      ops_mem[0] = (Dwarf_Op) { .atom = DW_OP_regx, .number = reg->value };
 +      *ops = ops_mem;
 +      *nops = 1;
 +      break;
 +
 +    case reg_val_expression:
 +      result = 1;             /* A value, not a location.  */
 +      /*FALLTHROUGH*/
 +    case reg_expression:
 +      {
 +      unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32
 +                                   ? 4 : 8);
 +
 +      Dwarf_Block block;
 +      const uint8_t *p = fs->cache->data->d.d_buf + reg->value;
 +      get_uleb128 (block.length, p);
 +      block.data = (void *) p;
 +
 +      /* Parse the expression into internal form.  */
 +      if (__libdw_intern_expression (NULL,
 +                                     fs->cache->other_byte_order,
 +                                     address_size,
 +                                     &fs->cache->expr_tree,
++                                     &block, ops, nops,
++                                     IDX_debug_frame) < 0)
 +        result = -1;
 +      break;
 +      }
 +    }
 +
 +  return result;
 +}
index ae6c1baa30757428c0dc51d4533f166c7a1690e6,0000000000000000000000000000000000000000..dc711eda9d3db2407f77a0ae1dcd0a06f96cedd7
mode 100644,000000..100644
--- /dev/null
@@@ -1,331 -1,0 +1,331 @@@
-   if (elf_getshstrndx (elf, &shstrndx) != 0)
 +/* Get CFI from ELF file's exception-handling info.
 +   Copyright (C) 2006, 2009 Red Hat, Inc.
 +   This file is part of Red Hat elfutils.
 +
 +   Red Hat elfutils is free software; you can redistribute it and/or modify
 +   it under the terms of the GNU General Public License as published by the
 +   Free Software Foundation; version 2 of the License.
 +
 +   Red Hat elfutils is distributed in the hope that it will be useful, but
 +   WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +   General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License along
 +   with Red Hat elfutils; if not, write to the Free Software Foundation,
 +   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
 +
 +   In addition, as a special exception, Red Hat, Inc. gives You the
 +   additional right to link the code of Red Hat elfutils with code licensed
 +   under any Open Source Initiative certified open source license
 +   (http://www.opensource.org/licenses/index.php) which requires the
 +   distribution of source code with any binary distribution and to
 +   distribute linked combinations of the two.  Non-GPL Code permitted under
 +   this exception must only link to the code of Red Hat elfutils through
 +   those well defined interfaces identified in the file named EXCEPTION
 +   found in the source code files (the "Approved Interfaces").  The files
 +   of Non-GPL Code may instantiate templates or use macros or inline
 +   functions from the Approved Interfaces without causing the resulting
 +   work to be covered by the GNU General Public License.  Only Red Hat,
 +   Inc. may make changes or additions to the list of Approved Interfaces.
 +   Red Hat's grant of this exception is conditioned upon your not adding
 +   any new exceptions.  If you wish to add a new Approved Interface or
 +   exception, please contact Red Hat.  You must obey the GNU General Public
 +   License in all respects for all of the Red Hat elfutils code and other
 +   code used in conjunction with Red Hat elfutils except the Non-GPL Code
 +   covered by this exception.  If you modify this file, you may extend this
 +   exception to your version of the file, but you are not obligated to do
 +   so.  If you do not wish to provide this exception without modification,
 +   you must delete this exception statement from your version and license
 +   this file solely under the GPL without exception.
 +
 +   Red Hat elfutils is an included package of the Open Invention Network.
 +   An included package of the Open Invention Network is a package for which
 +   Open Invention Network licensees cross-license their patents.  No patent
 +   license is granted, either expressly or impliedly, by designation as an
 +   included package.  Should you wish to participate in the Open Invention
 +   Network licensing program, please visit www.openinventionnetwork.com
 +   <http://www.openinventionnetwork.com>.  */
 +
 +#ifdef HAVE_CONFIG_H
 +# include <config.h>
 +#endif
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <assert.h>
 +
 +#include "libdwP.h"
 +#include "cfi.h"
 +#include "encoded-value.h"
 +#include <dwarf.h>
 +
 +
 +static Dwarf_CFI *
 +allocate_cfi (Elf *elf, GElf_Addr vaddr)
 +{
 +  Dwarf_CFI *cfi = calloc (1, sizeof *cfi);
 +  if (cfi == NULL)
 +    {
 +      __libdw_seterrno (DWARF_E_NOMEM);
 +      return NULL;
 +    }
 +
 +  cfi->e_ident = (unsigned char *) elf_getident (elf, NULL);
 +  if (cfi->e_ident == NULL)
 +    {
 +      free (cfi);
 +      __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
 +      return NULL;
 +    }
 +
 +  cfi->eh_frame = true;
 +  if ((BYTE_ORDER == LITTLE_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2MSB)
 +      || (BYTE_ORDER == BIG_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2LSB))
 +    cfi->other_byte_order = true;
 +
 +  cfi->frame_vaddr = vaddr;
 +  cfi->textrel = 0;           /* XXX ? */
 +  cfi->datarel = 0;           /* XXX ? */
 +
 +  return cfi;
 +}
 +
 +static const uint8_t *
 +parse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr,
 +                  const GElf_Ehdr *ehdr, GElf_Addr *eh_frame_vaddr,
 +                  size_t *table_entries, uint8_t *table_encoding)
 +{
 +  const uint8_t *h = hdr;
 +
 +  if (*h++ != 1)              /* version */
 +    return (void *) -1l;
 +
 +  uint8_t eh_frame_ptr_encoding = *h++;
 +  uint8_t fde_count_encoding = *h++;
 +  uint8_t fde_table_encoding = *h++;
 +
 +  if (eh_frame_ptr_encoding == DW_EH_PE_omit)
 +    return (void *) -1l;
 +
 +  /* Dummy used by read_encoded_value.  */
 +  Elf_Data_Scn dummy_cfi_hdr_data =
 +    {
 +      .d = { .d_buf = (void *) hdr, .d_size = hdr_size }
 +    };
 +  Dwarf_CFI dummy_cfi =
 +    {
 +      .e_ident = ehdr->e_ident,
 +      .datarel = hdr_vaddr,
 +      .frame_vaddr = hdr_vaddr,
 +      .data = &dummy_cfi_hdr_data,
 +    };
 +
 +  *eh_frame_vaddr = read_encoded_value (&dummy_cfi, eh_frame_ptr_encoding, &h);
 +
 +  if (fde_count_encoding != DW_EH_PE_omit)
 +    {
 +      Dwarf_Word fde_count = read_encoded_value (&dummy_cfi,
 +                                               fde_count_encoding, &h);
 +      if (fde_count != 0 && (size_t) fde_count == fde_count
 +        && fde_table_encoding != DW_EH_PE_omit
 +        && (fde_table_encoding &~ DW_EH_PE_signed) != DW_EH_PE_uleb128)
 +      {
 +        *table_entries = fde_count;
 +        *table_encoding = fde_table_encoding;
 +        return h;
 +      }
 +    }
 +
 +  return NULL;
 +}
 +
 +static Dwarf_CFI *
 +getcfi_gnu_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, const GElf_Phdr *phdr)
 +{
 +  if (unlikely (phdr->p_filesz < 4))
 +    goto invalid;
 +
 +  Elf_Data *data = elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz,
 +                                       ELF_T_BYTE);
 +  if (data == NULL)
 +    {
 +    invalid_hdr:
 +    invalid:
 +      /* XXX might be read error or corrupt phdr */
 +      __libdw_seterrno (DWARF_E_INVALID_CFI);
 +      return NULL;
 +    }
 +
 +  Dwarf_Addr eh_frame_ptr;
 +  size_t search_table_entries;
 +  uint8_t search_table_encoding;
 +  const uint8_t *search_table = parse_eh_frame_hdr (data->d_buf, phdr->p_filesz,
 +                                                  phdr->p_vaddr, ehdr,
 +                                                  &eh_frame_ptr,
 +                                                  &search_table_entries,
 +                                                  &search_table_encoding);
 +  if (search_table == (void *) -1l)
 +    goto invalid_hdr;
 +
 +  Dwarf_Off eh_frame_offset = eh_frame_ptr - phdr->p_vaddr + phdr->p_offset;
 +  Dwarf_Word eh_frame_size = 0;
 +
 +  /* XXX we have no way without section headers to know the size
 +     of the .eh_frame data.  Calculate the largest it might possibly be.
 +     This won't be wasteful if the file is already mmap'd, but if it isn't
 +     it might be quite excessive.  */
 +  size_t filesize;
 +  if (elf_rawfile (elf, &filesize) != NULL)
 +    eh_frame_size = filesize - eh_frame_offset;
 +
 +  data = elf_getdata_rawchunk (elf, eh_frame_offset, eh_frame_size, ELF_T_BYTE);
 +  if (data == NULL)
 +    {
 +      __libdw_seterrno (DWARF_E_INVALID_ELF); /* XXX might be read error */
 +      return NULL;
 +    }
 +  Dwarf_CFI *cfi = allocate_cfi (elf, eh_frame_ptr);
 +  if (cfi != NULL)
 +    {
 +      cfi->data = (Elf_Data_Scn *) data;
 +
 +      if (search_table != NULL)
 +      {
 +        cfi->search_table = search_table;
 +        cfi->search_table_vaddr = phdr->p_vaddr;
 +        cfi->search_table_encoding = search_table_encoding;
 +        cfi->search_table_entries = search_table_entries;
 +      }
 +    }
 +  return cfi;
 +}
 +
 +/* Search the phdrs for PT_GNU_EH_FRAME.  */
 +static Dwarf_CFI *
 +getcfi_phdr (Elf *elf, const GElf_Ehdr *ehdr)
 +{
 +  const uint_fast16_t phnum = ehdr->e_phnum;
 +
 +  for (uint_fast16_t i = 0; i < phnum; ++i)
 +    {
 +      GElf_Phdr phdr_mem;
 +      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
 +      if (unlikely (phdr == NULL))
 +      return NULL;
 +      if (phdr->p_type == PT_GNU_EH_FRAME)
 +      return getcfi_gnu_eh_frame (elf, ehdr, phdr);
 +    }
 +
 +  __libdw_seterrno (DWARF_E_NO_DWARF);
 +  return NULL;
 +}
 +
 +static Dwarf_CFI *
 +getcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr,
 +                   Elf_Scn *scn, GElf_Shdr *shdr,
 +                   Elf_Scn *hdr_scn, GElf_Addr hdr_vaddr)
 +{
 +  Elf_Data *data = elf_rawdata (scn, NULL);
 +  if (data == NULL)
 +    {
 +      __libdw_seterrno (DWARF_E_INVALID_ELF);
 +      return NULL;
 +    }
 +  Dwarf_CFI *cfi = allocate_cfi (elf, shdr->sh_addr);
 +  if (cfi != NULL)
 +    {
 +      cfi->data = (Elf_Data_Scn *) data;
 +      if (hdr_scn != NULL)
 +      {
 +        Elf_Data *hdr_data = elf_rawdata (hdr_scn, NULL);
 +        if (hdr_data != NULL)
 +          {
 +            GElf_Addr eh_frame_vaddr;
 +            cfi->search_table_vaddr = hdr_vaddr;
 +            cfi->search_table
 +              = parse_eh_frame_hdr (hdr_data->d_buf, hdr_data->d_size,
 +                                    hdr_vaddr, ehdr, &eh_frame_vaddr,
 +                                    &cfi->search_table_entries,
 +                                    &cfi->search_table_encoding);
 +            if (cfi->search_table == (void *) -1l)
 +              {
 +                free (cfi);
 +                /* XXX might be read error or corrupt phdr */
 +                __libdw_seterrno (DWARF_E_INVALID_CFI);
 +                return NULL;
 +              }
 +
 +            /* Sanity check.  */
 +            if (unlikely (eh_frame_vaddr != shdr->sh_addr))
 +              cfi->search_table = NULL;
 +          }
 +      }
 +    }
 +  return cfi;
 +}
 +
 +/* Search for the sections named ".eh_frame" and ".eh_frame_hdr".  */
 +static Dwarf_CFI *
 +getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
 +{
 +  size_t shstrndx;
++  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
 +    {
 +      __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
 +      return NULL;
 +    }
 +
 +  if (shstrndx != 0)
 +    {
 +      Elf_Scn *hdr_scn = NULL;
 +      GElf_Addr hdr_vaddr = 0;
 +      Elf_Scn *scn = NULL;
 +      while ((scn = elf_nextscn (elf, scn)) != NULL)
 +      {
 +        GElf_Shdr shdr_mem;
 +        GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
 +        if (shdr == NULL)
 +          continue;
 +        const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
 +        if (name == NULL)
 +          continue;
 +        if (!strcmp (name, ".eh_frame_hdr"))
 +          {
 +            hdr_scn = scn;
 +            hdr_vaddr = shdr->sh_addr;
 +          }
 +        else if (!strcmp (name, ".eh_frame"))
 +          return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
 +                                      hdr_scn, hdr_vaddr);
 +      }
 +    }
 +
 +  return (void *) -1l;
 +}
 +
 +Dwarf_CFI *
 +dwarf_getcfi_elf (elf)
 +     Elf *elf;
 +{
 +  if (elf_kind (elf) != ELF_K_ELF)
 +    {
 +      __libdw_seterrno (DWARF_E_NOELF);
 +      return NULL;
 +    }
 +
 +  GElf_Ehdr ehdr_mem;
 +  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
 +  if (unlikely (ehdr == NULL))
 +    {
 +      __libdw_seterrno (DWARF_E_INVALID_ELF);
 +      return NULL;
 +    }
 +
 +  Dwarf_CFI *result = getcfi_shdr (elf, ehdr);
 +  if (result == (void *) -1l)
 +    result = getcfi_phdr (elf, ehdr);
 +
 +  return result;
 +}
 +INTDEF (dwarf_getcfi_elf)
index c3233e293c668837f48e1f47602ca084e29ddf1d,f829e72b114921567235a3550f2d803f8f45df85..be8a333084382ac54a0d21c4bb3c57ed6417c650
@@@ -1,5 -1,5 +1,5 @@@
  /* Return location expression list.
-    Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007 Red Hat, Inc.
 -   Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006 Red Hat, Inc.
++   Copyright (C) 2000-2009 Red Hat, Inc.
     This file is part of Red Hat elfutils.
     Written by Ulrich Drepper <drepper@redhat.com>, 2000.
  
@@@ -111,16 -111,15 +111,16 @@@ loc_compare (const void *p1, const voi
    return 0;
  }
  
 -static int
 -getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
 -           Dwarf_Op **llbuf, size_t *listlen, int sec_index)
 +int
 +internal_function
 +__libdw_intern_expression (Dwarf *dbg,
 +                         bool other_byte_order, unsigned int address_size,
 +                         void **cache, const Dwarf_Block *block,
-                          Dwarf_Op **llbuf, size_t *listlen)
++                         Dwarf_Op **llbuf, size_t *listlen, int sec_index)
  {
 -  Dwarf *dbg = cu->dbg;
 -
    /* Check whether we already looked at this list.  */
    struct loc_s fake = { .addr = block->data };
 -  struct loc_s **found = tfind (&fake, &cu->locs, loc_compare);
 +  struct loc_s **found = tfind (&fake, cache, loc_compare);
    if (found != NULL)
      {
        /* We already saw it.  */
        {
        case DW_OP_addr:
          /* Address, depends on address size of CU.  */
-         if (address_size == 4)
-           {
-             if (unlikely (data + 4 > end_data))
-               {
-               invalid:
-                 __libdw_seterrno (DWARF_E_INVALID_DWARF);
-                 return -1;
-               }
-             newloc->number = read_4ubyte_unaligned_inc (&bo, data);
-           }
-         else
-           {
-             if (unlikely (data + 8 > end_data))
-               goto invalid;
-             newloc->number = read_8ubyte_unaligned_inc (&bo, data);
-           }
+         if (__libdw_read_address_inc (dbg, sec_index, (unsigned char **)&data,
 -                                      cu->address_size, &newloc->number))
++                                      address_size, &newloc->number))
+           return -1;
          break;
  
        case DW_OP_deref:
    return 0;
  }
  
-            Dwarf_Op **llbuf, size_t *listlen)
 +static int
 +getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
-                                   block, llbuf, listlen);
++           Dwarf_Op **llbuf, size_t *listlen, int sec_index)
 +{
 +  return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
 +                                  cu->address_size, &cu->locs,
++                                  block, llbuf, listlen, sec_index);
 +}
 +
  int
  dwarf_getlocation (attr, llbuf, listlen)
       Dwarf_Attribute *attr;
diff --cc libdw/libdwP.h
index 4cccb56cfa3ca428b89537eb437e801fbc9b2b54,97a2e042f6837ca3fd04a54a16817d46819083ff..28c49e53a93e38a1c7b219df47ccc5db2220f4e1
@@@ -417,16 -414,6 +417,17 @@@ extern int __libdw_visit_scopes (unsign
                                 void *arg)
    __nonnull_attribute__ (2, 3) internal_function;
  
-                                     Dwarf_Op **llbuf, size_t *listlen)
 +/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
 +   and cache the result (via tsearch).  */
 +extern int __libdw_intern_expression (Dwarf *dbg,
 +                                    bool other_byte_order,
 +                                    unsigned int address_size,
 +                                    void **cache, const Dwarf_Block *block,
++                                    Dwarf_Op **llbuf, size_t *listlen,
++                                    int sec_index)
 +  __nonnull_attribute__ (4, 5, 6, 7) internal_function;
 +
 +
  /* Return error code of last failing function call.  This value is kept
     separately for each thread.  */
  extern int __dwarf_errno_internal (void);
Simple merge