]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
readelf: Fix CFI decoding for DW_EH_PE_absptr.
authorRoland McGrath <roland@redhat.com>
Tue, 2 Feb 2010 23:50:15 +0000 (15:50 -0800)
committerRoland McGrath <roland@redhat.com>
Tue, 2 Feb 2010 23:50:15 +0000 (15:50 -0800)
src/ChangeLog
src/readelf.c

index ee1b733f66921b1ac2b78c306c163aa92b656a94..562433149d9223d8d024f90addd34a0aeeed6d52 100644 (file)
@@ -1,3 +1,11 @@
+2010-02-02  Roland McGrath  <roland@redhat.com>
+
+       * readelf.c (print_encoding_base): Handle DW_EH_PE_absptr (zero).
+       (read_encoded): Likewise.
+       (print_debug_frame_section): Check for bogus augmentation length.
+       For P augmentation, use read_encoded, print the encoding description,
+       and use hex for unsigned values.
+
 2010-01-15  Roland McGrath  <roland@redhat.com>
 
        * ar.c: Include <sys/stat.h>.
index 6ba259cf16a2f913ab41daf005134704ca9f9059..7b687d75b381a1a01cb08a308e1eaf31447de6da 100644 (file)
@@ -4705,8 +4705,7 @@ print_encoding_base (const char *pfx, unsigned int fde_encoding)
     {
       unsigned int w = fde_encoding;
 
-      if (w & 0xf)
-       w = print_encoding (w);
+      w = print_encoding (w);
 
       if (w & 0x70)
        {
@@ -4728,6 +4727,10 @@ static const unsigned char *
 read_encoded (unsigned int encoding, const unsigned char *readp,
              const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
 {
+  if ((encoding & 0xf) == DW_EH_PE_absptr)
+    encoding = gelf_getclass (dbg->elf) == ELFCLASS32
+      ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
+
   switch (encoding & 0xf)
     {
     case DW_EH_PE_uleb128:
@@ -4915,6 +4918,9 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
              unsigned int augmentationlen;
              get_uleb128 (augmentationlen, readp);
 
+             if (augmentationlen > dataend - readp)
+               error (1, 0, gettext ("invalid augmentation length"));
+
              const char *hdr = "Augmentation data:";
              const char *cp = augmentation + 1;
              while (*cp != '\0')
@@ -4941,51 +4947,27 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                      const unsigned char *startp = readp;
                      unsigned int encoding = *readp++;
                      uint64_t val = 0;
-                     int64_t sval = 0;
-                     bool is_signed = false;
+                     readp = read_encoded (encoding, readp,
+                                           readp - 1 + augmentationlen,
+                                           &val, dbg);
+
+                     while (++startp < readp)
+                       printf ("%#x ", *startp);
 
+                     putchar ('(');
+                     print_encoding (encoding);
+                     putchar (' ');
                      switch (encoding & 0xf)
                        {
-                       case DW_EH_PE_uleb128:
-                         get_uleb128 (val, readp);
-                         break;
                        case DW_EH_PE_sleb128:
-                         get_sleb128 (sval, readp);
-                         is_signed = true;
-                         break;
-                       case DW_EH_PE_udata2:
-                         val = read_2ubyte_unaligned_inc (dbg, readp);
-                         break;
-                       case DW_EH_PE_udata4:
-                         val = read_4ubyte_unaligned_inc (dbg, readp);
-                         break;
-                       case DW_EH_PE_udata8:
-                         val = read_8ubyte_unaligned_inc (dbg, readp);
-                         break;
                        case DW_EH_PE_sdata2:
-                         val = read_2sbyte_unaligned_inc (dbg, readp);
-                         is_signed = true;
-                         break;
                        case DW_EH_PE_sdata4:
-                         val = read_4sbyte_unaligned_inc (dbg, readp);
-                         is_signed = true;
-                         break;
-                       case DW_EH_PE_sdata8:
-                         val = read_8sbyte_unaligned_inc (dbg, readp);
-                         is_signed = true;
+                         printf ("%" PRId64 ")\n", val);
                          break;
                        default:
-                         error (1, 0,
-                                gettext ("invalid augmentation encoding"));
+                         printf ("%#" PRIx64 ")\n", val);
+                         break;
                        }
-
-                     while (++startp < readp)
-                       printf ("%#x ", *startp);
-
-                     if (is_signed)
-                       printf ("(%" PRId64 ")\n", sval);
-                     else
-                       printf ("(%" PRIu64 ")\n", val);
                    }
                  else
                    printf ("(%x)\n", *readp++);