]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
unwind branch cleanup, closer to merge-ready.
authorRoland McGrath <roland@redhat.com>
Mon, 20 Apr 2009 02:11:17 +0000 (19:11 -0700)
committerRoland McGrath <roland@redhat.com>
Mon, 20 Apr 2009 02:11:17 +0000 (19:11 -0700)
23 files changed:
backends/ChangeLog
libdw/ChangeLog
libdw/Makefile.am
libdw/cfi.c
libdw/cfi.h
libdw/cie.c
libdw/dwarf_getcfi_elf.c
libdw/dwarf_next_cfi.c
libdw/encoded-value.h
libdw/libdw.h
libdw/libdw.map
libdw/unwind.h [deleted file]
libdwfl/ChangeLog
libdwfl/Makefile.am
libdwfl/dwfl_addrframe.c
libdwfl/dwfl_module_dwarf_cfi.c [moved from libdwfl/dwfl_module_getcfi.c with 79% similarity]
libdwfl/dwfl_module_eh_cfi.c [new file with mode: 0644]
libdwfl/libdwfl.h
libdwfl/libdwflP.h
libebl/ChangeLog
libebl/libebl.h
tests/ChangeLog
tests/addrcfi.c

index 62b5275e609943bd8774079e4f505d88e63d848b..30c0c4c1e20d9a0557b677b6d2686473cab37ab2 100644 (file)
@@ -1,4 +1,4 @@
-2007-01-18  Roland McGrath  <roland@redhat.com>
+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.
index 8e92fe7d64764488b00f33b7288e223fbffb8b4a..abc4ffb121e8980298300710c1dd71f0384e4099 100644 (file)
@@ -1,3 +1,52 @@
+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.
        * libdw.map (ELFUTILS_0.127): New version set, inherits from
        ELFUTILS_0.126.  Add dwfl_module_addrsym.
 
-2007-02-10  Roland McGrath  <roland@redhat.com>
-
-       * libdw.map (ELFUTILS_0.127): Add dwfl_addrframe, dwfl_module_getcfi.
-
-       * dwarf.h: Define DW_EH_PE_* constants.
-
-       * unwindP.h (struct Dwarf_CFI_s): Add `ebl' member.
-       * dwarf_cfi_setebl.c: New file.
-       * Makefile.am (libdw_a_SOURCES): Add it.
-       * unwind.h: Declare dwarf_cfi_setebl.
-       * unwindP.h: Add INTDECL.
-
-       * 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.127): 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.
-       * unwind.c: New file.
-       * unwindP.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.h (DW_CFA_low_user, DW_CFA_high_user): Renamed to
-       DW_CFA_lo_user, DW_CFA_hi_user, to match DWARF 3 spec.
-
-       * unwind.h: New file.
-       * dwarf_next_cfi.c: New file.
-       * Makefile.am (euinclude_HEADERS, libdw_a_SOURCES): Add them.
-       * libdw.map (ELFUTILS_0.127): New set inheriting from ELFUTILS_0.126.
-       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.
-
 2007-02-10  Roland McGrath  <roland@redhat.com>
 
        * dwarf.h (DW_OP_fbreg): Comment fix.
index 62eafb7edb39e5789f1f1dd0f3fdde35056edfa5..4d041cf736beeaf364f2011c55560ab04a700e58 100644 (file)
@@ -47,7 +47,7 @@ noinst_PROGRAMS = $(noinst_LIBRARIES:_pic.a=.so)
 endif
 
 include_HEADERS = dwarf.h
-pkginclude_HEADERS = libdw.h unwind.h
+pkginclude_HEADERS = libdw.h
 
 libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
                  dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \
index 0be13d4a5f4831726ef7e402ba10f91bb688e029..d9065ecdd9bd97dc4af8d74338fb047f3e37d897 100644 (file)
@@ -412,7 +412,7 @@ cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
      First we'll let the backend fill in the default initial
      state for this machine's ABI.  */
 
-  Dwarf_CIE abi_info = { CIE_ID, 1, 1, -1, "", NULL, 0, 0, NULL, NULL };
+  Dwarf_CIE abi_info = { DW_CIE_ID_64, NULL, NULL, 1, 1, -1, "", NULL, 0, 0 };
 
   /* Make sure we have a backend handle cached.  */
   if (unlikely (cache->ebl == NULL))
index 8390fd825e1e554e9121ceae3bad6b4ad1f29c10..2f8a1a18e97005ccbcafc8829c3f9acd2b92ca83 100644 (file)
 
 #include "libdwP.h"
 #include "libelfP.h"
-#include "unwind.h"            /* XXX */
 struct ebl;
 
+#define dwarf_cfi_cie_p(entry) ((entry)->cie.CIE_id == DW_CIE_ID_64)
+
 /* Cached CIE representation.  */
 struct dwarf_cie
 {
index e698a4b9db5f2e40ecce88874d754dd0211eede8..eed9aa89973f4cc63024fe78ddac60b49dbf220d 100644 (file)
@@ -167,7 +167,7 @@ __libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset)
   int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
                                       &cache->data->d, cache->eh_frame,
                                       offset, &next_offset, &entry);
-  if (result != 0 || entry.cie.CIE_id != CIE_ID)
+  if (result != 0 || entry.cie.CIE_id != DW_CIE_ID_64)
     {
       __libdw_seterrno (DWARF_E_INVALID_DWARF);
       return NULL;
index f68e6418b2e800e9d0a07c4a5d96c72ae8808957..ae6c1baa30757428c0dc51d4533f166c7a1690e6 100644 (file)
@@ -265,7 +265,7 @@ getcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr,
   return cfi;
 }
 
-/* Search for the section named ".eh_frame".  */
+/* Search for the sections named ".eh_frame" and ".eh_frame_hdr".  */
 static Dwarf_CFI *
 getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
 {
index 698e31c8d678598931378540eaca0478ac99356c..ae911b81558b621d8ffbb903cf1ebeafa5265817 100644 (file)
@@ -89,7 +89,7 @@ dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
 
   uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
   size_t offset_size = 4;
-  if (length == 0xffffffffu)
+  if (length == DWARF3_LENGTH_64_BIT)
     {
       /* This is the 64-bit DWARF format.  */
       offset_size = 8;
@@ -120,14 +120,14 @@ dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
     {
       entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
       /* Canonicalize the 32-bit CIE_ID value to 64 bits.  */
-      if (!eh_frame_p && entry->cie.CIE_id == 0xffffffffu)
-       entry->cie.CIE_id = CIE_ID;
+      if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
+       entry->cie.CIE_id = DW_CIE_ID_64;
     }
   if (eh_frame_p)
     {
       /* Canonicalize the .eh_frame CIE pointer to .debug_frame format.  */
       if (entry->cie.CIE_id == 0)
-       entry->cie.CIE_id = CIE_ID;
+       entry->cie.CIE_id = DW_CIE_ID_64;
       else
        {
          /* In .eh_frame format, a CIE pointer is the distance from where
@@ -140,7 +140,7 @@ dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
        }
     }
 
-  if (entry->cie.CIE_id == CIE_ID)
+  if (entry->cie.CIE_id == DW_CIE_ID_64)
     {
       /* Read the version stamp.  Always an 8-bit value.  */
       uint8_t version = *bytes++;
index b9985992578fd31b5ae6c1504b3d348fb04eb290..0bd09e495ea4d244b4d198461b03f2cd67770a6a 100644 (file)
@@ -52,7 +52,8 @@
 
 #include <dwarf.h>
 #include <stdlib.h>
-#include "unwind.h"            /* XXX */
+#include "libdwP.h"
+
 
 static size_t __attribute__ ((unused))
 encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
index 3f3e5a09d4be4041fa9e28d0e29ed91ce978ad92..81c2b73e624a671861780027ab02d21cea4ba61d 100644 (file)
@@ -1,5 +1,5 @@
 /* Interfaces for libdw.
-   Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
+   Copyright (C) 2002-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
@@ -190,6 +190,70 @@ typedef struct
 } Dwarf_Op;
 
 
+/* This describes one Common Information Entry read from a CFI section.
+   Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi.  */
+typedef struct
+{
+  Dwarf_Off CIE_id;     /* Always DW_CIE_ID_64 in Dwarf_CIE structures.  */
+
+  /* Instruction stream describing initial state used by FDEs.  If
+     we did not understand the whole augmentation string and it did
+     not use 'z', then there might be more augmentation data here
+     (and in FDEs) before the actual instructions.  */
+  const uint8_t *initial_instructions;
+  const uint8_t *initial_instructions_end;
+
+  Dwarf_Word code_alignment_factor;
+  Dwarf_Sword data_alignment_factor;
+  Dwarf_Word return_address_register;
+
+  const char *augmentation;    /* Augmentation string.  */
+
+  /* Augmentation data, might be NULL.  The size is correct only if
+     we understood the augmentation string sufficiently.  */
+  const uint8_t *augmentation_data;
+  size_t augmentation_data_size;
+  size_t fde_augmentation_data_size;
+} Dwarf_CIE;
+
+/* This describes one Frame Description Entry read from a CFI section.
+   Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi.  */
+typedef struct
+{
+  /* Section offset of CIE this FDE refers to.  This will never be
+     DW_CIE_ID_64 in an FDE.  If this value is DW_CIE_ID_64, this is
+     actually a Dwarf_CIE structure.  */
+  Dwarf_Off CIE_pointer;
+
+  /* We can't really decode anything further without looking up the CIE
+     and checking its augmentation string.  Here follows the encoded
+     initial_location and address_range, then any augmentation data,
+     then the instruction stream.  This FDE describes PC locations in
+     the byte range [initial_location, initial_location+address_range).
+     When the CIE augmentation string uses 'z', the augmentation data is
+     a DW_FORM_block (self-sized).  Otherwise, when we understand the
+     augmentation string completely, fde_augmentation_data_size gives
+     the number of bytes of augmentation data before the instructions.  */
+  const uint8_t *start;
+  const uint8_t *end;
+} Dwarf_FDE;
+
+/* Each entry in a CFI section is either a CIE described by Dwarf_CIE or
+   an FDE described by Dward_FDE.  Check CIE_id to see which you have.  */
+typedef union
+{
+  Dwarf_Off CIE_id;     /* Always DW_CIE_ID_64 in Dwarf_CIE structures.  */
+  Dwarf_CIE cie;
+  Dwarf_FDE fde;
+} Dwarf_CFI_Entry;
+
+/* Opaque type representing a frame state described by CFI.  */
+typedef struct Dwarf_Frame_s Dwarf_Frame;
+
+/* Opaque type representing a CFI section found in a DWARF or ELF file.  */
+typedef struct Dwarf_CFI_s Dwarf_CFI;
+
+
 /* Handle for debug sessions.  */
 typedef struct Dwarf Dwarf;
 
@@ -229,6 +293,47 @@ extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
      __nonnull_attribute__ (3);
 
 
+/* Decode one DWARF CFI entry (CIE or FDE) from the raw section data.
+   The E_IDENT from the originating ELF file indicates the address
+   size and byte order used in the CFI section contained in DATA;
+   EH_FRAME_P should be true for .eh_frame format and false for
+   .debug_frame format.  OFFSET is the byte position in the section
+   to start at; on return *NEXT_OFFSET is filled in with the byte
+   position immediately after this entry.
+
+   On success, returns 0 and fills in *ENTRY; use dwarf_cfi_cie_p to
+   see whether ENTRY->cie or ENTRY->fde is valid.
+
+   On errors, returns -1.  Some format errors will permit safely
+   skipping to the next CFI entry though the current one is unusable.
+   In that case, *NEXT_OFF will be updated before a -1 return.
+
+   If there are no more CFI entries left in the section,
+   returns 1 and sets *NEXT_OFFSET to (Dwarf_Off) -1.  */
+extern int dwarf_next_cfi (const unsigned char e_ident[],
+                          Elf_Data *data, bool eh_frame_p,
+                          Dwarf_Off offset, Dwarf_Off *next_offset,
+                          Dwarf_CFI_Entry *entry)
+  __nonnull_attribute__ (1, 2, 5, 6);
+
+/* Use the CFI in the DWARF .debug_frame section.
+   Returns NULL if there is no such section (not an error).
+   The pointer returned can be used until dwarf_end is called on DWARF,
+   and must not be passed to dwarf_cfi_end.
+   Calling this more than once returns the same pointer.  */
+extern Dwarf_CFI *dwarf_getcfi (Dwarf *dwarf);
+
+/* Use the CFI in the ELF file's exception-handling data.
+   Returns NULL if there is no such data.
+   The pointer returned can be used until elf_end is called on ELF,
+   and must be passed to dwarf_cfi_end before then.
+   Calling this more than once allocates independent data structures.  */
+extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf);
+
+/* Release resources allocated by dwarf_getcfi_elf.  */
+extern int dwarf_cfi_end (Dwarf_CFI *cache);
+
+
 /* Return DIE at given offset.  */
 extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset,
                                Dwarf_Die *result) __nonnull_attribute__ (3);
@@ -626,6 +731,57 @@ extern int dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp,
                               const char **strp);
 
 
+/* Compute what's known about a call frame when the PC is at ADDRESS.
+   Returns 0 for success or -1 for errors.
+   On success, *FRAME is a malloc'd pointer.  */
+extern int dwarf_cfi_addrframe (Dwarf_CFI *cache,
+                               Dwarf_Addr address, Dwarf_Frame **frame)
+  __nonnull_attribute__ (3);
+
+/* Return the DWARF register number used in FRAME to denote
+   the return address in FRAME's caller frame.  The remaining
+   arguments can be non-null to fill in more information.
+
+   Fill [*START, *END) with the PC range to which FRAME's information applies.
+   Fill in *SIGNALP to indicate whether this is a signal-handling frame.
+   If true, this is the implicit call frame that calls a signal handler.
+   This frame's "caller" is actually the interrupted state, not a call;
+   its return address is an exact PC, not a PC after a call instruction.  */
+extern int dwarf_frame_info (Dwarf_Frame *frame,
+                            Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp);
+
+/* Deliver a DWARF expression that yields the Canonical Frame Address at
+   this frame state.  Returns -1 for errors, or the number of operations
+   stored at *OPS.  That pointer can be used only as long as FRAME is alive
+   and unchanged.  Returns zero if the CFA cannot be determined here.  */
+extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops)
+  __nonnull_attribute__ (2);
+
+/* Deliver a DWARF expression that yields the location or value of
+   DWARF register number REGNO in the state described by FRAME.
+
+   Returns -1 for errors, 0 if REGNO has an accessible location,
+   or 1 if REGNO has only a computable value.  Stores at *NOPS
+   the number of operations in the array stored at *OPS.
+   With return value 0, this is a DWARF location expression.
+   With return value 1, this is a DWARF expression that computes the value.
+
+   Return value 1 with *NOPS zero means CFI says the caller's REGNO is
+   "undefined" here, i.e. it's call-clobbered and cannot be recovered.
+
+   Return value 0 with *NOPS zero means CFI says the caller's REGNO is
+   "same_value" here, i.e. this frame did not change it; ask the caller
+   frame where to find it.
+
+   For common simple expressions *OPS is OPS_MEM.  For arbitrary DWARF
+   expressions in the CFI, *OPS is an internal pointer that can be used as
+   long as the Dwarf_CFI used to create FRAME remains alive.  */
+extern int dwarf_frame_register (Dwarf_Frame *frame, int regno,
+                                Dwarf_Op ops_mem[2],
+                                Dwarf_Op **ops, size_t *nops)
+  __nonnull_attribute__ (3, 4, 5);
+
+
 /* Return error code of last failing function call.  This value is kept
    separately for each thread.  */
 extern int dwarf_errno (void);
index 598c9de726d448fe34f5519c0aa1a4a7c03d715e..8b37bfe214fc8274abddf159e35e40d5de32206f 100644 (file)
@@ -195,9 +195,8 @@ ELFUTILS_0.138 {
     *;
 } ELFUTILS_0.136;
 
-ELFUTILS_0.140_UNWIND {
+ELFUTILS_0.141_UNWIND {
   global:
-    # XXX new unwind stuff not decided yet
     dwarf_next_cfi;
     dwarf_getcfi;
     dwarf_getcfi_elf;
@@ -206,6 +205,8 @@ ELFUTILS_0.140_UNWIND {
     dwarf_frame_cfa;
     dwarf_frame_register;
     dwarf_frame_info;
+
     dwfl_addrframe;
-    dwfl_module_getcfi;
+    dwfl_module_dwarf_cfi;
+    dwfl_module_eh_cfi;
 } ELFUTILS_0.138;
diff --git a/libdw/unwind.h b/libdw/unwind.h
deleted file mode 100644 (file)
index d5169ba..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-#ifndef _libdw_unwind_h                /* XXX */
-#define _libdw_unwind_h 1
-
-#include "libdw.h"
-
-/* This describes one Common Information Entry read from a CFI section.
-   Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi.  */
-typedef struct
-{
-  Dwarf_Off CIE_id;    /* Always CIE_ID in Dwarf_CIE structures. */
-#define CIE_ID ((Dwarf_Off) -1l)
-
-  Dwarf_Word code_alignment_factor;
-  Dwarf_Sword data_alignment_factor;
-  Dwarf_Word return_address_register;
-
-  const char *augmentation;    /* Augmentation string.  */
-
-  /* Augmentation data, might be NULL.  The size is correct only if
-     we understood the augmentation string sufficiently.  */
-  const uint8_t *augmentation_data;
-  size_t augmentation_data_size;
-  size_t fde_augmentation_data_size;
-
-  /* Instruction stream describing initial state used by FDEs.  If
-     we did not understand the whole augmentation string and it did
-     not use 'z', then there might be more augmentation data here
-     (and in FDEs) before the actual instructions.  */
-  const uint8_t *initial_instructions;
-  const uint8_t *initial_instructions_end;
-} Dwarf_CIE;
-
-/* This describes one Frame Description Entry read from a CFI section.
-   Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi.  */
-typedef struct
-{
-  /* Section offset of CIE this FDE refers to.  This will never be
-     CIE_ID in an FDE.  If this value is CIE_ID, this is actually a
-     Dwarf_CIE structure.  */
-  Dwarf_Off CIE_pointer;
-
-  /* We can't really decode anything further without looking up the CIE
-     and checking its augmentation string.  Here follows the encoded
-     initial_location and address_range, then any augmentation data,
-     then the instruction stream.  This FDE describes PC locations in
-     the byte range [initial_location, initial_location+address_range).
-     When the CIE augmentation string uses 'z', the augmentation data is
-     a DW_FORM_block (self-sized).  Otherwise, when we understand the
-     augmentation string completely, fde_augmentation_data_size gives
-     the number of bytes of augmentation data before the instructions.  */
-  const uint8_t *start;
-  const uint8_t *end;
-} Dwarf_FDE;
-
-typedef union
-{
-  Dwarf_CIE cie;
-  Dwarf_FDE fde;
-} Dwarf_CFI_Entry;
-
-#define dwarf_cfi_cie_p(entry) ((entry)->cie.CIE_id == CIE_ID)
-
-/* Decode one DWARF CFI entry (CIE or FDE) from the raw section data.
-   The E_IDENT from the originating ELF file indicates the address
-   size and byte order used in the CFI section contained in DATA;
-   EH_FRAME_P should be true for .eh_frame format and false for
-   .debug_frame format.  OFFSET is the byte position in the section
-   to start at; on return *NEXT_OFFSET is filled in with the byte
-   position immediately after this entry.
-
-   On success, returns 0 and fills in *ENTRY; use dwarf_cfi_cie_p to
-   see whether ENTRY->cie or ENTRY->fde is valid.
-
-   On errors, returns -1.  Some format errors will permit safely
-   skipping to the next CFI entry though the current one is unusable.
-   In that case, *NEXT_OFF will be updated before a -1 return.
-
-   If there are no more CFI entries left in the section,
-   returns 1 and sets *NEXT_OFFSET to (Dwarf_Off) -1.  */
-extern int dwarf_next_cfi (const unsigned char e_ident[],
-                          Elf_Data *data, bool eh_frame_p,
-                          Dwarf_Off offset, Dwarf_Off *next_offset,
-                          Dwarf_CFI_Entry *entry)
-  __nonnull_attribute__ (1, 2, 5, 6);
-
-
-/* Opaque type representing a frame state described by CFI.  */
-typedef struct Dwarf_Frame_s Dwarf_Frame;
-
-/* Opaque type representing a CFI section found in a DWARF or ELF file.  */
-typedef struct Dwarf_CFI_s Dwarf_CFI;
-
-/* Use the CFI in the DWARF .debug_frame section.
-   Returns NULL if there is no such section (not an error).
-   The pointer returned can be used until dwarf_end is called on DWARF,
-   and must not be passed to dwarf_cfi_end.
-   Calling this more than once returns the same pointer.  */
-extern Dwarf_CFI *dwarf_getcfi (Dwarf *dwarf);
-
-/* Use the CFI in the ELF file's exception-handling data.
-   Returns NULL if there is no such data.
-   The pointer returned can be used until elf_end is called on ELF,
-   and must be passed to dwarf_cfi_end before then.
-   Calling this more than once allocates independent data structures.  */
-extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf);
-
-/* Release resources allocated by dwarf_getcfi_elf.  */
-extern int dwarf_cfi_end (Dwarf_CFI *cache);
-
-
-/* Compute what's known about a call frame when the PC is at ADDRESS.
-   Returns 0 for success or -1 for errors.
-   On success, *FRAME is a malloc'd pointer.  */
-extern int dwarf_cfi_addrframe (Dwarf_CFI *cache,
-                               Dwarf_Addr address, Dwarf_Frame **frame)
-  __nonnull_attribute__ (3);
-
-/* Return the DWARF register number used in FRAME to denote
-   the return address in FRAME's caller frame.  The remaining
-   arguments can be non-null to fill in more information.
-
-   Fill [*START, *END) with the PC range to which FRAME's information applies.
-   Fill in *SIGNALP to indicate whether this is a signal-handling frame.
-   If true, this is the implicit call frame that calls a signal handler.
-   This frame's "caller" is actually the interrupted state, not a call;
-   its return address is an exact PC, not a PC after a call instruction.  */
-extern int dwarf_frame_info (Dwarf_Frame *frame,
-                            Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp);
-
-/* Deliver a DWARF expression that yields the Canonical Frame Address at
-   this frame state.  Returns -1 for errors, or the number of operations
-   stored at *OPS.  That pointer can be used only as long as FRAME is alive
-   and unchanged.  Returns zero if the CFA cannot be determined here.  */
-extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops)
-  __nonnull_attribute__ (2);
-
-/* Deliver a DWARF expression that yields the location or value of
-   DWARF register number REGNO in the state described by FRAME.
-
-   Returns -1 for errors, 0 if REGNO has an accessible location,
-   or 1 if REGNO has only a computable value.  Stores at *NOPS
-   the number of operations in the array stored at *OPS.
-   With return value 0, this is a DWARF location expression.
-   With return value 1, this is a DWARF expression that computes the value.
-
-   Return value 1 with *NOPS zero means CFI says the caller's REGNO is
-   "undefined" here, i.e. it's call-clobbered and cannot be recovered.
-
-   Return value 0 with *NOPS zero means CFI says the caller's REGNO is
-   "same_value" here, i.e. this frame did not change it; ask the caller
-   frame where to find it.
-
-   For common simple expressions *OPS is OPS_MEM.  For arbitrary DWARF
-   expressions in the CFI, *OPS is an internal pointer that can be used as
-   long as the Dwarf_CFI used to create FRAME remains alive.  */
-extern int dwarf_frame_register (Dwarf_Frame *frame, int regno,
-                                Dwarf_Op ops_mem[2],
-                                Dwarf_Op **ops, size_t *nops)
-  __nonnull_attribute__ (3, 4, 5);
-
-
-// XXX libdwfl front-end
-#include "../libdwfl/libdwfl.h"
-
-
-/* Find the CFI for this module.  Returns NULL if there is no CFI.
-   On success, fills in *BIAS with the difference between addresses
-   within the loaded module and those in the CFI referring to it.
-   The pointer returned can be used until the module is cleaned up.
-   Calling this more than once returns the same pointer.  */
-extern Dwarf_CFI *dwfl_module_getcfi (Dwfl_Module *mod, Dwarf_Addr *bias);
-
-// XXX needs module bias? for DW_OP_addr in exprs?
-/* Compute what's known about a call frame when the PC is at ADDRESS.
-   Returns 0 for success or -1 for errors.
-   On success, *FRAME is a malloc'd pointer.  */
-extern int dwfl_addrframe (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Frame **frame)
-  __nonnull_attribute__ (3);
-
-#endif /* XXX */
index 4092e913ad85d5c399e0c5d7083bc32903af296d..9115b29917b43c7b7c98a020bc5e7aa641c588b1 100644 (file)
@@ -1,10 +1,11 @@
-2007-02-10  Roland McGrath  <roland@redhat.com>
+2009-04-19  Roland McGrath  <roland@redhat.com>
 
-       * libdwflP.h (struct Dwfl_Module): New members `cfi', `cfi_elf'.
-       Add INTDECL for dwfl_module_getcfi.
-       * dwfl_module_getcfi.c: New file.
+       * dwfl_module_dwarf_cfi.c: New file.
+       * dwfl_module_eh_cfi.c: New file.
        * dwfl_addrframe.c: New file.
        * Makefile.am (libdwfl_a_SOURCES): Add them.
+       * libdwflP.h (struct Dwfl_Module): New members `dwarf_cfi', `eh_cfi.
+       Add INTDECL for dwfl_module_eh_cfi, dwfl_module_dwarf_cfi.
 
 2009-04-19  Roland McGrath  <roland@redhat.com>
 
index 9470c3dc6552ec95947e2010bb00334b5db71926..d271c5750bcf69dc9b2cde8bf37e62384ba537a0 100644 (file)
@@ -68,7 +68,8 @@ libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
                    dwfl_module_getsrc_file.c \
                    libdwfl_crc32.c libdwfl_crc32_file.c \
                    elf-from-memory.c \
-                   dwfl_module_getcfi.c dwfl_addrframe.c \
+                   dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \
+                   dwfl_addrframe.c \
                    dwfl_module_getsym.c \
                    dwfl_module_addrname.c dwfl_module_addrsym.c \
                    dwfl_module_return_value_location.c \
index 21548e77f0301c9d4abb11665fbeaf4dd2ad2e51..cd0a9a5b0f1bffdc79017a1c91cf348976e554a3 100644 (file)
    <http://www.openinventionnetwork.com>.  */
 
 #include "libdwflP.h"
-#include "../libdw/cfi.h"      /* XXX */
+#include "../libdw/cfi.h"
+
+/* Return -1 for hard error, 0 for address match, 1 for no match.  */
+static int
+try_cfi (Dwarf_CFI *cfi, Dwarf_Addr *bias, bool hard,
+        Dwarf_Addr address, Dwarf_Frame **frame)
+{
+  int result = INTUSE(dwarf_cfi_addrframe) (cfi, address - *bias, frame);
+  if (result != 0)
+    {
+      if (hard)
+       __libdwfl_seterrno (DWFL_E_LIBDW);
+      else
+       {
+         int err = INTUSE(dwarf_errno) ();
+         if (err == DWARF_E_NO_MATCH)
+           return 1;
+         __libdwfl_seterrno (DWFL_E (LIBDW, err));
+       }
+    }
+  return result;
+}
 
 int
 dwfl_addrframe (dwfl, address, frame)
@@ -56,14 +77,17 @@ dwfl_addrframe (dwfl, address, frame)
      Dwarf_Addr address;
      Dwarf_Frame **frame;
 {
-  Dwarf_Addr dwbias;
   Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, address);
-  Dwarf_CFI *cfi = INTUSE(dwfl_module_getcfi) (mod, &dwbias);
-  if (cfi == NULL)
+  if (mod == NULL)
     return -1;
 
-  int result = INTUSE(dwarf_cfi_addrframe) (cfi, address - dwbias, frame);
-  if (result != 0)
-    __libdwfl_seterrno (DWFL_E_LIBDW);
+  /* Try to get a .debug_frame match first, then a .eh_frame match.  */
+  Dwarf_Addr bias;
+  int result = try_cfi (INTUSE(dwfl_module_dwarf_cfi) (mod, &bias), &bias,
+                       false, address, frame);
+  if (result > 0)
+    result = try_cfi (INTUSE(dwfl_module_eh_cfi) (mod, &bias), &bias,
+                     true, address, frame);
+
   return result;
 }
similarity index 79%
rename from libdwfl/dwfl_module_getcfi.c
rename to libdwfl/dwfl_module_dwarf_cfi.c
index 21f259050c699b86709fde2a41d10627bc68e888..eeca31a669473f51b332b95eec39ad3a6414c6ff 100644 (file)
@@ -1,5 +1,5 @@
-/* Find CFI for a module in libdwfl.
-   Copyright (C) 2006, 2007, 2009 Red Hat, Inc.
+/* Find DWARF CFI for a module in libdwfl.
+   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
 #include "../libdw/cfi.h"
 
 Dwarf_CFI *
-dwfl_module_getcfi (mod, bias)
+internal_function
+__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot, Dwarf_CFI *cfi)
+{
+  if (cfi != NULL && cfi->ebl == NULL)
+    {
+      Dwfl_Error error = __libdwfl_module_getebl (mod);
+      if (error == DWFL_E_NOERROR)
+       cfi->ebl = mod->ebl;
+      else
+       {
+         if (slot == &mod->eh_cfi)
+           INTUSE(dwarf_cfi_end) (cfi);
+         __libdwfl_seterrno (error);
+         return NULL;
+       }
+    }
+
+  return *slot = cfi;
+}
+
+Dwarf_CFI *
+dwfl_module_dwarf_cfi (mod, bias)
      Dwfl_Module *mod;
      Dwarf_Addr *bias;
 {
   if (mod == NULL)
     return NULL;
 
-  if (mod->cfi == NULL)
-    {
-      mod->cfi = INTUSE(dwarf_getcfi) (INTUSE(dwfl_module_getdwarf) (mod,
-                                                                    bias));
-      if (mod->cfi == NULL && mod->main.elf != NULL)
-       {
-         mod->cfi_elf = true;
-         *bias = mod->main.bias;
-         mod->cfi = INTUSE(dwarf_getcfi_elf) (mod->main.elf);
-       }
-
-      if (mod->cfi != NULL && mod->cfi->ebl == NULL)
-       {
-         Dwfl_Error error = __libdwfl_module_getebl (mod);
-         if (error == DWFL_E_NOERROR)
-           mod->cfi->ebl = mod->ebl;
-         else
-           {
-             if (mod->cfi_elf)
-               INTUSE(dwarf_cfi_end) (mod->cfi);
-             mod->cfi = NULL;
-             __libdwfl_seterrno (error);
-           }
-       }
-    }
+  if (mod->dwarf_cfi != NULL)
+    return mod->dwarf_cfi;
 
-  return mod->cfi;
+  return __libdwfl_set_cfi (mod, &mod->dwarf_cfi,
+                           INTUSE(dwarf_getcfi)
+                           (INTUSE(dwfl_module_getdwarf) (mod, bias)));
 }
-INTDEF (dwfl_module_getcfi)
+INTDEF (dwfl_module_dwarf_cfi)
diff --git a/libdwfl/dwfl_module_eh_cfi.c b/libdwfl/dwfl_module_eh_cfi.c
new file mode 100644 (file)
index 0000000..a3cf624
--- /dev/null
@@ -0,0 +1,75 @@
+/* Find EH CFI for a module in libdwfl.
+   Copyright (C) 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>.  */
+
+#include "libdwflP.h"
+#include "../libdw/cfi.h"
+
+Dwarf_CFI *
+dwfl_module_eh_cfi (mod, bias)
+     Dwfl_Module *mod;
+     Dwarf_Addr *bias;
+{
+  if (mod == NULL)
+    return NULL;
+
+  if (mod->eh_cfi != NULL)
+    return mod->eh_cfi;
+
+  __libdwfl_getelf (mod);
+  if (mod->elferr != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (mod->elferr);
+      return NULL;
+    }
+
+  *bias = mod->main.bias;
+  return __libdwfl_set_cfi (mod, &mod->eh_cfi,
+                           INTUSE(dwarf_getcfi_elf) (mod->main.elf));
+}
+INTDEF (dwfl_module_eh_cfi)
index 91d43802499dca3dbb46058639e1e59d53cefffc..4af6a65de37733baba1e0076b9b6c089dfe50e71 100644 (file)
@@ -552,6 +552,28 @@ extern int dwfl_module_register_names (Dwfl_Module *mod,
                                       void *arg);
 
 
+/* Find the CFI for this module.  Returns NULL if there is no CFI.
+   On success, fills in *BIAS with the difference between addresses
+   within the loaded module and those in the CFI referring to it.
+   The pointer returned can be used until the module is cleaned up.
+   Calling these more than once returns the same pointers.
+
+   dwfl_module_dwarf_cfi gets the '.debug_frame' information found with the
+   rest of the DWARF information.  dwfl_module_eh_cfi gets the '.eh_frame'
+   information found linked into the text.  A module might have either or
+   both.  */
+extern Dwarf_CFI *dwfl_module_dwarf_cfi (Dwfl_Module *mod, Dwarf_Addr *bias);
+extern Dwarf_CFI *dwfl_module_eh_cfi (Dwfl_Module *mod, Dwarf_Addr *bias);
+
+// XXX needs module bias? for DW_OP_addr in exprs?
+/* Compute what's known about a call frame when the PC is at ADDRESS.
+   This integrates both DWARF proper and EH information as available.
+   Returns 0 for success or -1 for errors.
+   On success, *FRAME is a malloc'd pointer.  */
+extern int dwfl_addrframe (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Frame **frame)
+  __nonnull_attribute__ (3);
+
+
 #ifdef __cplusplus
 }
 #endif
index c91ff8f07df3f2d76f79eded37d9b52145813633..b5bcd9bd86f0b305830332d4ca052b14019d4df2 100644 (file)
@@ -62,7 +62,6 @@
 #include <string.h>
 
 #include "../libdw/libdwP.h"   /* We need its INTDECLs.  */
-#include "../libdw/unwind.h"   /* XXX */
 
 /* gettext helper macros.  */
 #define _(Str) dgettext ("elfutils", Str)
@@ -183,8 +182,8 @@ struct Dwfl_Module
   struct dwfl_arange *aranges; /* Mapping of addresses in module to CUs.  */
   unsigned int naranges;
 
-  Dwarf_CFI *cfi;              /* Cached CFI for this module.  */
-  bool cfi_elf;                        /* cfi is from dwarf_getcfi_elf.  */
+  Dwarf_CFI *dwarf_cfi;                /* Cached DWARF CFI for this module.  */
+  Dwarf_CFI *eh_cfi;           /* Cached EH CFI for this module.  */
 
   int segment;                 /* Index of first segment table entry.  */
   bool gc;                     /* Mark/sweep flag.  */
@@ -278,6 +277,11 @@ extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
 /* Ensure that MOD->ebl is set up.  */
 extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
 
+/* Install a new Dwarf_CFI in *SLOT (MOD->eh_cfi or MOD->dwarf_cfi).  */
+extern Dwarf_CFI *__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot,
+                                    Dwarf_CFI *cfi)
+  internal_function;
+
 /* Iterate through all the CU's in the module.  Start by passing a null
    LASTCU, and then pass the last *CU returned.  Success return with null
    *CU no more CUs.  */
@@ -429,7 +433,8 @@ INTDECL (dwfl_linux_kernel_report_modules)
 INTDECL (dwfl_linux_kernel_report_offline)
 INTDECL (dwfl_offline_section_address)
 INTDECL (dwfl_module_relocate_address)
-INTDECL (dwfl_module_getcfi)
+INTDECL (dwfl_module_dwarf_cfi)
+INTDECL (dwfl_module_eh_cfi)
 
 /* Leading arguments standard to callbacks passed a Dwfl_Module.  */
 #define MODCB_ARGS(mod)        (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr
index 2d501a365bd5c0fc402eac2fb7d00a6e3bb1604c..52b46cd32fcc2d7791b0020806e6e5522a676afe 100644 (file)
@@ -1,4 +1,4 @@
-2007-01-18  Roland McGrath  <roland@redhat.com>
+2009-04-19  Roland McGrath  <roland@redhat.com>
 
        * ebl-hooks.h: Add abi_cfi hook.
        * eblopenbackend.c (default_abi_cfi): New function.
index 11de24aa158be62c7e60582b9836b9333fafba3f..1a56b9663d85db4715e8d59ef9e5ec9776226b2d 100644 (file)
@@ -1,5 +1,5 @@
 /* Interface for libebl.
-   Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
+   Copyright (C) 2000, 2001-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
@@ -52,7 +52,6 @@
 
 #include <gelf.h>
 #include "libdw.h"
-#include "unwind.h"            /* XXX */
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
index bc22309c69645f5f7ad759527bc9d1b424293e13..151dcabf3a44dc6f5dbdfa243ba14c44274aeaef 100644 (file)
@@ -1,4 +1,4 @@
-2007-02-10  Roland McGrath  <roland@redhat.com>
+2009-04-19  Roland McGrath  <roland@redhat.com>
 
        * addrcfi.c: New file.
        * Makefile.am (noinst_PROGRAMS): Add it.
index e2367f2b49a0b55a34755be823a7dcfe509e5c8c..101c5c0b014cc76aa9e58de258ac43c46127ed37 100644 (file)
@@ -36,7 +36,6 @@
 #include <error.h>
 #include <string.h>
 
-#include "../libdw/unwind.h"   /* XXX */
 
 static void
 print_detail (int result, const Dwarf_Op *ops, size_t nops)