]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Always canonicalize stored encodings. Prepare for CIEs with varying address_size.
authorRoland McGrath <roland@redhat.com>
Thu, 24 Jun 2010 23:47:17 +0000 (16:47 -0700)
committerRoland McGrath <roland@redhat.com>
Thu, 24 Jun 2010 23:47:17 +0000 (16:47 -0700)
libdw/ChangeLog
libdw/cfi.h
libdw/cie.c
libdw/dwarf_next_cfi.c
libdw/encoded-value.h
libdw/fde.c

index b671da8ff52c7189da349abb3091c0ade745809f..59fbb8aad05edf92f7500f8a9551dac3fa2c6c4e 100644 (file)
@@ -1,3 +1,16 @@
+2010-06-24  Roland McGrath  <roland@redhat.com>
+
+       * encoded-value.h (encoded_value_size): Replace E_IDENT parameter
+       with ADDRESS_SIZE.
+       (read_encoded_value): Update caller.
+       * fde.c (binary_search_fde): Likewise.
+       * dwarf_next_cfi.c: Likewise.
+       * cfi.h (struct dwarf_cie): New member address_size.
+       (CFI_ADDRSIZE): New macro.
+       * cie.c (intern_new_cie): Initialize and use CIE->address_size.
+       (canonicalize_encoding): New function.
+       (intern_new_cie): Call it, do both FDE and LSDA encodings.
+
 2010-06-23  Roland McGrath  <roland@redhat.com>
 
        * cfi.c (dwarf_cfi_validate_fde): Function removed.
index b300b73df08b12c09732c6c633675b8a6ceae82f..3dab7fb84573e5760fe4289135ec1bc9eb686acd 100644 (file)
@@ -71,7 +71,11 @@ struct dwarf_cie
 
   const Dwarf_Frame *initial_state;
 
-  uint8_t fde_encoding;                /* DW_EH_PE_* for addresses in FDEs.  */
+  uint8_t address_size;            /* Address size used here.  */
+
+  /* These encodings are canonicalized from DW_EH_PE_absptr
+     to a particular size DW_EH_PE_udata[48].  */
+  uint8_t fde_encoding;            /* DW_EH_PE_* for addresses in FDEs.  */
   uint8_t lsda_encoding;    /* DW_EH_PE_* for LSDA in FDE augmentation.  */
 
   bool sized_augmentation_data;        /* Saw 'z': FDEs have self-sized data.  */
@@ -142,6 +146,8 @@ struct Dwarf_CFI_s
   bool default_same_value;
 };
 
+#define CFI_ADDRSIZE(cache)    (cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8)
+
 
 enum dwarf_frame_rule
   {
index 7c93f5510978c2bad52539cf133c869e83198682..7e111f17e092c895766c8ee7e1755246f9d271cb 100644 (file)
@@ -70,6 +70,29 @@ compare_cie (const void *a, const void *b)
   return 0;
 }
 
+/* Canonicalize encoding to a specific size.  */
+static bool
+canonicalize_encoding (uint8_t *encoding, uint8_t address_size)
+{
+  if ((*encoding & 0x07) == DW_EH_PE_absptr)
+    {
+      assert (DW_EH_PE_absptr == 0);
+
+      switch (address_size)
+       {
+       case 8:
+         *encoding |= DW_EH_PE_udata8;
+         break;
+       case 4:
+         *encoding |= DW_EH_PE_udata4;
+         break;
+       default:
+         return true;
+       }
+    }
+  return false;
+}
+
 /* There is no CIE at OFFSET in the tree.  Add it.  */
 static struct dwarf_cie *
 intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
@@ -90,6 +113,9 @@ intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
   cie->sized_augmentation_data = false;
   cie->signal_frame = false;
 
+  /* XXX should get from dwarf_next_cfi with v4 header.  */
+  cie->address_size = CFI_ADDRSIZE (cache);
+
   cie->fde_encoding = DW_EH_PE_absptr;
   cie->lsda_encoding = DW_EH_PE_omit;
 
@@ -112,7 +138,7 @@ intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
          cie->lsda_encoding = *data++;
          if (!cie->sized_augmentation_data)
            cie->fde_augmentation_data_size
-             += encoded_value_size (&cache->data->d, cache->e_ident,
+             += encoded_value_size (&cache->data->d, cie->address_size,
                                     cie->lsda_encoding, NULL);
          continue;
 
@@ -122,7 +148,7 @@ intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
 
        case 'P':               /* Skip personality routine.  */
          encoding = *data++;
-         data += encoded_value_size (&cache->data->d, cache->e_ident,
+         data += encoded_value_size (&cache->data->d, cie->address_size,
                                      encoding, data);
          continue;
 
@@ -136,27 +162,12 @@ intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
       break;
     }
 
-  if ((cie->fde_encoding & 0x0f) == DW_EH_PE_absptr)
+  if (canonicalize_encoding (&cie->fde_encoding, cie->address_size)
+      || canonicalize_encoding (&cie->lsda_encoding, cie->address_size))
     {
-      /* Canonicalize encoding to a specific size.  */
-      assert (DW_EH_PE_absptr == 0);
-
-      /* XXX should get from dwarf_next_cfi with v4 header.  */
-      uint_fast8_t address_size
-       = cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
-      switch (address_size)
-       {
-       case 8:
-         cie->fde_encoding |= DW_EH_PE_udata8;
-         break;
-       case 4:
-         cie->fde_encoding |= DW_EH_PE_udata4;
-         break;
-       default:
-         free (cie);
-         __libdw_seterrno (DWARF_E_INVALID_DWARF);
-         return NULL;
-       }
+      free (cie);
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
     }
 
   /* Save the initial instructions to be played out into initial state.  */
index 0e90457d09e0592bca5e365e5b549773907b53f1..49791c981df4129f57010eb7e24b3d7f5d068e54 100644 (file)
@@ -224,11 +224,12 @@ dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
                case 'R':               /* Skip FDE address encoding byte.  */
                  encoding = *bytes++;
                  entry->cie.fde_augmentation_data_size
-                   += encoded_value_size (data, e_ident, encoding, NULL);
+                   += encoded_value_size (data, address_size, encoding, NULL);
                  continue;
                case 'P':   /* Skip encoded personality routine pointer. */
                  encoding = *bytes++;
-                 bytes += encoded_value_size (data, e_ident, encoding, bytes);
+                 bytes += encoded_value_size (data, address_size,
+                                              encoding, bytes);
                  continue;
                case 'S':               /* Skip signal-frame flag.  */
                  continue;
index e118a1c4d99c7123a422207a91f52b533d1d9572..ee8a6f31a10d403fb27d82404546324625ddd6ec 100644 (file)
@@ -56,7 +56,7 @@
 
 
 static size_t __attribute__ ((unused))
-encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
+encoded_value_size (const Elf_Data *data, uint8_t address_size,
                    uint8_t encoding, const uint8_t *p)
 {
   if (encoding == DW_EH_PE_omit)
@@ -72,7 +72,7 @@ encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
       return 8;
 
     case DW_EH_PE_absptr:
-      return e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+      return address_size;
 
     case DW_EH_PE_uleb128:
       if (p != NULL)
@@ -84,7 +84,6 @@ encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
        }
 
     default:
-      abort ();
       return 0;
     }
 }
@@ -136,7 +135,8 @@ read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding, const uint8_t **p,
       break;
     case DW_EH_PE_aligned:
       {
-       const size_t size = encoded_value_size (&cache->data->d, cache->e_ident,
+       const size_t size = encoded_value_size (&cache->data->d,
+                                               CFI_ADDRSIZE (cache),
                                                encoding, *p);
        size_t align = ((cache->frame_vaddr
                         + (*p - (const uint8_t *) cache->data->d.d_buf))
@@ -203,7 +203,7 @@ read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding, const uint8_t **p,
        return true;
       *result -= cache->frame_vaddr;
       if (unlikely (*result > (cache->data->d.d_size
-                              - encoded_value_size (NULL, cache->e_ident,
+                              - encoded_value_size (NULL, CFI_ADDRSIZE (cache),
                                                     DW_EH_PE_absptr, NULL))))
        return true;
       const uint8_t *ptr = cache->data->d.d_buf + *result;
index 14e9395daf0678e6cff181d747d89b628910e738..44a39ccd7e3282c2ca9004aac3c09424231ec56c 100644 (file)
@@ -199,7 +199,8 @@ __libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset, ptrdiff_t *nextoff)
 static Dwarf_Off
 binary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address)
 {
-  const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident,
+  const size_t size = 2 * encoded_value_size (&cache->data->d,
+                                             CFI_ADDRSIZE (cache),
                                              cache->search_table_encoding,
                                              NULL);