Fix readelf for large SLEB128 values.
authorRoland McGrath <roland@redhat.com>
Tue, 22 Jun 2010 06:00:35 +0000 (23:00 -0700)
committerRoland McGrath <roland@redhat.com>
Tue, 22 Jun 2010 06:00:35 +0000 (23:00 -0700)
libdw/ChangeLog
libdw/memory-access.h
src/ChangeLog
src/readelf.c

index 34c7ba3..dff21fa 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-21  Roland McGrath  <roland@redhat.com>
+
+       * memory-access.h (get_sleb128_rest_return): Fix sign extension for
+       10-byte case.
+
 2010-06-20  Roland McGrath  <roland@redhat.com>
 
        * libdw_findcu.c (__libdw_findcu): Take new flag argument,
index 13f79ec..b7799e9 100644 (file)
@@ -1,5 +1,5 @@
 /* Unaligned memory access functionality.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2009 Red Hat, Inc.
+   Copyright (C) 2000-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -90,7 +90,7 @@
     _v |= (uint64_t) (__b & 0x7f) << (nth * 7);                                      \
     if (likely ((__b & 0x80) == 0))                                          \
       {                                                                              \
-       var = (_v << (64 - (nth * 7) - 7) >> (64 - (nth * 7) - 7));           \
+       var = (_v << (64 - (nth * 7) - 7)) >> (64 - (nth * 7) - 7);           \
         break;                                                               \
       }                                                                              \
     else do {} while (0)
       {                                                                              \
        get_sleb128_step (var, *addrp, i, return var);                        \
       }                                                                              \
-    /* Other implementations set VALUE to INT_MAX in this                    \
-       case.  So we better do this as well.  */                                      \
-    return INT64_MAX;                                                        \
+    __b = *(*addrp)++;                                                       \
+    if (likely ((__b & 0x80) == 0))                                          \
+      return var | ((uint64_t) __b << 63);                                   \
+    else                                                                     \
+      /* Other implementations set VALUE to INT_MAX in this                  \
+        case.  So we better do this as well.  */                             \
+      return INT64_MAX;                                                              \
   } while (0)
 
 #ifdef IS_LIBDW
@@ -122,14 +126,14 @@ extern int64_t __libdw_get_sleb128 (int64_t acc, unsigned int i,
                                    const unsigned char **addrp)
      internal_function attribute_hidden;
 #else
-static uint64_t
+static inline uint64_t
 __attribute__ ((unused))
 __libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
 {
   unsigned char __b;
   get_uleb128_rest_return (acc, i, addrp);
 }
-static int64_t
+static inline int64_t
 __attribute__ ((unused))
 __libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
 {
index 59e8b8b..bcb9729 100644 (file)
@@ -1,3 +1,10 @@
+2010-06-21  Roland McGrath  <roland@redhat.com>
+
+       * readelf.c (dwarf_tag_string): Handle new v4 tags.
+
+       * readelf.c (print_ops): Use 64-bit types for LEB128 operands.
+       (print_cfa_program): Likewise.
+
 2010-06-20  Roland McGrath  <roland@redhat.com>
 
        * readelf.c (print_debug_units): New function, broken out of ...
index f5be7f1..76b4fe4 100644 (file)
@@ -3227,6 +3227,9 @@ dwarf_tag_string (unsigned int tag)
       [DW_TAG_mutable_type] = "mutable_type",
       [DW_TAG_condition] = "condition",
       [DW_TAG_shared_type] = "shared_type",
+      [DW_TAG_type_unit] = "type_unit",
+      [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
+      [DW_TAG_template_alias] = "template_alias",
     };
   const unsigned int nknown_tags = (sizeof (known_tags)
                                    / sizeof (known_tags[0]));
@@ -4092,9 +4095,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
        case DW_OP_plus_uconst:
        case DW_OP_constu:;
          const unsigned char *start = data;
-         unsigned int uleb;
+         uint64_t uleb;
          get_uleb128 (uleb, data); /* XXX check overrun */
-         printf ("%*s[%4" PRIuMAX "] %s %u\n",
+         printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
                  indent, "", (uintmax_t) offset, known[op], uleb);
          len -= data - start;
          offset += 1 + (data - start);
@@ -4102,10 +4105,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 
        case DW_OP_bit_piece:
          start = data;
-         unsigned int uleb2;
+         uint64_t uleb2;
          get_uleb128 (uleb, data); /* XXX check overrun */
          get_uleb128 (uleb2, data); /* XXX check overrun */
-         printf ("%*s[%4" PRIuMAX "] %s %u, %u\n",
+         printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
                  indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
          len -= data - start;
          offset += 1 + (data - start);
@@ -4115,9 +4118,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
        case DW_OP_breg0 ... DW_OP_breg31:
        case DW_OP_consts:
          start = data;
-         unsigned int sleb;
+         int64_t sleb;
          get_sleb128 (sleb, data); /* XXX check overrun */
-         printf ("%*s[%4" PRIuMAX "] %s %d\n",
+         printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
                  indent, "", (uintmax_t) offset, known[op], sleb);
          len -= data - start;
          offset += 1 + (data - start);
@@ -4127,7 +4130,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
          start = data;
          get_uleb128 (uleb, data); /* XXX check overrun */
          get_sleb128 (sleb, data); /* XXX check overrun */
-         printf ("%*s[%4" PRIuMAX "] %s %u %d\n",
+         printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
                  indent, "", (uintmax_t) offset, known[op], uleb, sleb);
          len -= data - start;
          offset += 1 + (data - start);
@@ -4615,10 +4618,10 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
                opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
       else if (opcode < DW_CFA_restore)
        {
-         unsigned int offset;
+         uint64_t offset;
          // XXX overflow check
          get_uleb128 (offset, readp);
-         printf ("     offset r%u (%s) at cfa%+d\n",
+         printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
                  opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
        }
       else
@@ -5430,7 +5433,7 @@ print_debug_units (Dwfl_Module *dwflmod,
                     " Version: %" PRIu16 ", Abbreviation section offset: %"
                     PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8
                     "\n Type signature: %#" PRIx64
-                    ", Type offset: %" PRIu64 "\n"),
+                    ", Type offset: %#" PRIx64 "\n"),
            (uint64_t) offset, version, abbroffset, addrsize, offsize,
            typesig, (uint64_t) typeoff);
   else