address size can be different from DW_OP_deref size
[external/binutils.git] / gdb / dwarf2expr.c
index 1fe8b79..e1ddc96 100644 (file)
@@ -229,6 +229,28 @@ get_unsigned_type (struct gdbarch *gdbarch, struct type *type)
     }
 }
 
+/* Return the signed form of TYPE.  TYPE is necessarily an integral
+   type.  */
+
+static struct type *
+get_signed_type (struct gdbarch *gdbarch, struct type *type)
+{
+  switch (TYPE_LENGTH (type))
+    {
+    case 1:
+      return builtin_type (gdbarch)->builtin_int8;
+    case 2:
+      return builtin_type (gdbarch)->builtin_int16;
+    case 4:
+      return builtin_type (gdbarch)->builtin_int32;
+    case 8:
+      return builtin_type (gdbarch)->builtin_int64;
+    default:
+      error (_("no signed variant found for type, while evaluating "
+              "DWARF expression"));
+    }
+}
+
 /* Retrieve the N'th item on CTX's stack, converted to an address.  */
 
 CORE_ADDR
@@ -447,6 +469,8 @@ dwarf_get_base_type (struct dwarf_expr_context *ctx, ULONGEST die, int size)
   if (ctx->get_base_type)
     {
       result = ctx->get_base_type (ctx, die);
+      if (result == NULL)
+       error (_("Could not find type for DW_OP_GNU_const_type"));
       if (size != 0 && TYPE_LENGTH (result) != size)
        error (_("DW_OP_GNU_const_type has different sizes for type and data"));
     }
@@ -853,6 +877,19 @@ execute_stack_op (struct dwarf_expr_context *ctx,
              type = address_type;
 
            (ctx->read_mem) (ctx->baton, buf, addr, addr_size);
+
+           /* If the size of the object read from memory is different
+              from the type length, we need to zero-extend it.  */
+           if (TYPE_LENGTH (type) != addr_size)
+             {
+               ULONGEST result =
+                 extract_unsigned_integer (buf, addr_size, byte_order);
+
+               buf = alloca (TYPE_LENGTH (type));
+               store_unsigned_integer (buf, TYPE_LENGTH (type),
+                                       byte_order, result);
+             }
+
            result_val = value_from_contents_and_address (type, buf, addr);
            break;
          }
@@ -994,7 +1031,19 @@ execute_stack_op (struct dwarf_expr_context *ctx,
              case DW_OP_shra:
                dwarf_require_integral (value_type (first));
                dwarf_require_integral (value_type (second));
+               if (TYPE_UNSIGNED (value_type (first)))
+                 {
+                   struct type *stype
+                     = get_signed_type (ctx->gdbarch, value_type (first));
+
+                   first = value_cast (stype, first);
+                 }
+
                result_val = value_binop (first, second, BINOP_RSH);
+               /* Make sure we wind up with the same type we started
+                  with.  */
+               if (value_type (result_val) != value_type (second))
+                 result_val = value_cast (value_type (second), result_val);
                break;
              case DW_OP_xor:
                dwarf_require_integral (value_type (first));