]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Add new dwarf_cfi_validate_fde call.
authorRoland McGrath <roland@redhat.com>
Wed, 16 Jun 2010 10:40:56 +0000 (03:40 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 16 Jun 2010 18:16:45 +0000 (11:16 -0700)
NEWS
libdw/ChangeLog
libdw/cfi.c
libdw/cfi.h
libdw/fde.c
libdw/libdw.h
libdw/libdw.map

diff --git a/NEWS b/NEWS
index fe141380abf5c7f991c6b5cd8d4e483bfdf202c3..9fc203e8912250a84a4138c9ec3fda68cc7bdb65 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ Version 0.148:
 
 libdw: Accept DWARF 4 format.
 
+libdw: New function dwarf_cfi_validate_fde.
+
 libdwfl: Fixes in core-file handling, support cores from PIEs.
         When working from build IDs, don't open a named file that mismatches.
 
index f974e96d41802b42d3fd5f317dad2d2f4367f5e5..7a1078904582390b909bb5eeab46ad3f715819eb 100644 (file)
@@ -1,5 +1,14 @@
 2010-06-16  Roland McGrath  <roland@redhat.com>
 
+       * fde.c (fde_by_offset): Renamed to ...
+       (__libdw_fde_by_offset): ... this, made global and internal_function.
+       Don't take ADDRESS argument.
+       (__libdw_find_fde): Update caller.  Do address sanity check here.
+       * cfi.h: Declare __libdw_fde_by_offset.
+       * cfi.c (dwarf_cfi_validate_fde): New function.
+       * libdw.h: Declare it.
+       * libdw.map (ELFUTILS_0.148): Add it.
+
        * cie.c (intern_new_cie): Canonicalize DW_EH_PE_absptr FDE encoding to
        either DW_EH_PE_udata8 or DW_EH_PE_udata4.
 
index aeb48e697931763c5ebb9a14dccb1978f90885b6..e49335ddc54da2c73c01548f333a00dad8dfb876 100644 (file)
@@ -504,3 +504,42 @@ __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
     }
   return result;
 }
+
+int
+dwarf_cfi_validate_fde (cache, offset, start, end, signalp, encoding)
+     Dwarf_CFI *cache;
+     Dwarf_Off offset;
+     Dwarf_Addr *start;
+     Dwarf_Addr *end;
+     bool *signalp;
+     uint8_t *encoding;
+{
+  if (cache == NULL)
+    return -1;
+
+  struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset);
+  if (unlikely (fde == NULL))
+    return -1;
+
+  Dwarf_Frame *fs;
+  int result = __libdw_frame_at_address (cache, fde, fde->end, &fs);
+  if (unlikely (result != DWARF_E_NOERROR))
+    {
+      __libdw_seterrno (result);
+      return -1;
+    }
+
+  result = fs->nregs + 1;
+  free (fs);
+
+  if (start != NULL)
+    *start = fde->start;
+  if (end != NULL)
+    *end = fde->end;
+  if (signalp != NULL)
+    *signalp = fde->cie->signal_frame;
+  if (encoding != NULL)
+    *encoding = fde->cie->fde_encoding;
+
+  return result;
+}
index 6aaa9c8a70f27dd57db5adb49648bcc4eb30eab0..ef9cd7e1b37f9aaa090fa113f7ffaafaf54621b1 100644 (file)
@@ -227,6 +227,11 @@ extern struct dwarf_fde *__libdw_find_fde (Dwarf_CFI *cache,
                                           Dwarf_Addr address)
   __nonnull_attribute__ (1) internal_function;
 
+/* Look for an FDE by its offset in the section.  */
+extern struct dwarf_fde *__libdw_fde_by_offset (Dwarf_CFI *cache,
+                                               Dwarf_Off offset)
+  __nonnull_attribute__ (1) internal_function;
+
 /* Process the FDE that contains the given PC address,
    to yield the frame state when stopped there.
    The return value is a DWARF_E_* error code.  */
index c826114c277ad0e2c25d419845adbb302bcfff6b..5685252ba01bc056133f308afb5848206cb93e43 100644 (file)
@@ -1,5 +1,5 @@
 /* FDE reading.
-   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2009-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -139,8 +139,9 @@ intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
   return fde;
 }
 
-static struct dwarf_fde *
-fde_by_offset (Dwarf_CFI *cache, Dwarf_Addr address, Dwarf_Off offset)
+struct dwarf_fde *
+internal_function
+__libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset)
 {
   Dwarf_CFI_Entry entry;
   Dwarf_Off next_offset;
@@ -167,10 +168,6 @@ fde_by_offset (Dwarf_CFI *cache, Dwarf_Addr address, Dwarf_Off offset)
   if (cache->next_offset == offset)
     cache->next_offset = next_offset;
 
-  /* Sanity check the address range.  */
-  if (address < fde->start || address >= fde->end)
-    goto invalid;
-
   return fde;
 }
 
@@ -254,7 +251,15 @@ __libdw_find_fde (Dwarf_CFI *cache, Dwarf_Addr address)
       Dwarf_Off offset = binary_search_fde (cache, address);
       if (offset == (Dwarf_Off) -1l)
        goto no_match;
-      return fde_by_offset (cache, address, offset);
+      struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset);
+      if (unlikely (fde != NULL)
+         /* Sanity check the address range.  */
+         && unlikely (address < fde->start || address >= fde->end))
+       {
+         __libdw_seterrno (DWARF_E_INVALID_DWARF);
+         return NULL;
+       }
+      return fde;
     }
 
   /* It's not there.  Read more CFI entries until we find it.  */
index 252361fc0b88b7462ee82d0aa11c9aefb0cf3d46..75998e1a037992dd5c041d6a6cff9ae9b49b43b5 100644 (file)
@@ -799,6 +799,20 @@ extern int dwarf_frame_register (Dwarf_Frame *frame, int regno,
                                 Dwarf_Op **ops, size_t *nops)
   __nonnull_attribute__ (3, 4, 5);
 
+/* Look up the FDE described at OFFSET bytes into the CFI section,
+   and validate it by decoding the FDE fully.  Returns -1 for errors.
+   On success, returns the maximum DWARF register number that this
+   FDE describes and fills *START and *END with the PC address range
+   this FDE covers, *SIGNALP with whether this is a signal frame, and
+   *ENCODING with the pointer encoding used in this FDE.  This is not
+   necessarily the exact encoding byte given in the augmentation string;
+   it will describe the exact address size used (DW_EH_PE_udata4 or
+   DW_EH_PE_udata8) if a DW_EH_PE_absptr encoding is being used.  */
+extern int dwarf_cfi_validate_fde (Dwarf_CFI *cache,
+                                  Dwarf_Off offset,
+                                  Dwarf_Addr *start, Dwarf_Addr *end,
+                                  bool *signalp, uint8_t *encoding);
+
 
 /* Return error code of last failing function call.  This value is kept
    separately for each thread.  */
index 1a9afb135cf81fb5e00978df7dfae23e57a1d88d..89897acdc1ebc56c0880d85b31a3bdd0e2400f3f 100644 (file)
@@ -237,3 +237,8 @@ ELFUTILS_0.146 {
   global:
     dwfl_core_file_report;
 } ELFUTILS_0.144;
+
+ELFUTILS_0.148 {
+  global:
+    dwarf_cfi_validate_fde;
+} ELFUTILS_0.146;