* breakpoint.c (do_enable_breakpoint): Use update_watchpoint for
[binutils-gdb.git] / gdb / dwarf2expr.c
index a099878f5e5697484b4985f0591ab3f12587639e..75a4ec73aadb8d6cdf56cb8c684d0e8a8fe07d08 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 Expression Evaluator.
 
-   Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008
+   Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
    Contributed by Daniel Berlin (dan@dberlin.org)
@@ -27,6 +27,7 @@
 #include "gdbcore.h"
 #include "elf/dwarf2.h"
 #include "dwarf2expr.h"
+#include "gdb_assert.h"
 
 /* Local prototypes.  */
 
@@ -46,6 +47,7 @@ new_dwarf_expr_context (void)
   retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
   retval->num_pieces = 0;
   retval->pieces = 0;
+  retval->max_recursion_depth = 0x100;
   return retval;
 }
 
@@ -134,7 +136,13 @@ add_piece (struct dwarf_expr_context *ctx,
 void
 dwarf_expr_eval (struct dwarf_expr_context *ctx, gdb_byte *addr, size_t len)
 {
+  int old_recursion_depth = ctx->recursion_depth;
+
   execute_stack_op (ctx, addr, addr + len);
+
+  /* CTX RECURSION_DEPTH becomes invalid if an exception was thrown here.  */
+
+  gdb_assert (ctx->recursion_depth == old_recursion_depth);
 }
 
 /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
@@ -196,7 +204,8 @@ read_sleb128 (gdb_byte *buf, gdb_byte *buf_end, LONGEST * r)
    doesn't extend past BUF_END.  */
 
 CORE_ADDR
-dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int addr_size)
+dwarf2_read_address (struct gdbarch *gdbarch, gdb_byte *buf,
+                    gdb_byte *buf_end, int addr_size)
 {
   CORE_ADDR result;
 
@@ -207,28 +216,18 @@ dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int addr_size)
      is sufficient for extracting an address.  However, some
      architectures (e.g. MIPS) use signed addresses and using
      extract_unsigned_integer() will not produce a correct
-     result.  Turning the unsigned integer into a value and then
-     decomposing that value as an address will cause
-     gdbarch_integer_to_address() to be invoked for those
-     architectures which require it.  Thus, using value_as_address()
-     will produce the correct result for both types of architectures.
-
-     One concern regarding the use of values for this purpose is
-     efficiency.  Obviously, these extra calls will take more time to
-     execute and creating a value takes more space, space which will
-     have to be garbage collected at a later time.  If constructing
-     and then decomposing a value for this purpose proves to be too
-     inefficient, then gdbarch_integer_to_address() can be called
-     directly.
+     result.  Make sure we invoke gdbarch_integer_to_address()
+     for those architectures which require it.
 
      The use of `unsigned_address_type' in the code below refers to
      the type of buf and has no bearing on the signedness of the
      address being returned.  */
 
-  result = value_as_address (value_from_longest 
-                             (unsigned_address_type (addr_size),
-                              extract_unsigned_integer (buf, addr_size)));
-  return result;
+  if (gdbarch_integer_to_address_p (gdbarch))
+    return gdbarch_integer_to_address
+            (gdbarch, unsigned_address_type (addr_size), buf);
+
+  return extract_unsigned_integer (buf, addr_size);
 }
 
 /* Return the type of an address of size ADDR_SIZE,
@@ -281,6 +280,11 @@ execute_stack_op (struct dwarf_expr_context *ctx,
   ctx->in_reg = 0;
   ctx->initialized = 1;  /* Default is initialized.  */
 
+  if (ctx->recursion_depth > ctx->max_recursion_depth)
+    error (_("DWARF-2 expression error: Loop detected (%d)."),
+          ctx->recursion_depth);
+  ctx->recursion_depth++;
+
   while (op_ptr < op_end)
     {
       enum dwarf_location_atom op = *op_ptr++;
@@ -326,7 +330,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          break;
 
        case DW_OP_addr:
-         result = dwarf2_read_address (op_ptr, op_end, ctx->addr_size);
+         result = dwarf2_read_address (ctx->gdbarch,
+                                       op_ptr, op_end, ctx->addr_size);
          op_ptr += ctx->addr_size;
          break;
 
@@ -509,6 +514,20 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          offset = *op_ptr++;
          result = dwarf_expr_fetch (ctx, offset);
          break;
+         
+       case DW_OP_swap:
+         {
+           CORE_ADDR t1, t2;
+
+           if (ctx->stack_len < 2)
+              error (_("Not enough elements for DW_OP_swap. Need 2, have %d."),
+                     ctx->stack_len);
+           t1 = ctx->stack[ctx->stack_len - 1];
+           t2 = ctx->stack[ctx->stack_len - 2];
+           ctx->stack[ctx->stack_len - 1] = t2;
+           ctx->stack[ctx->stack_len - 2] = t1;
+           goto no_push;
+         }
 
        case DW_OP_over:
          result = dwarf_expr_fetch (ctx, 1);
@@ -546,7 +565,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
              {
                gdb_byte *buf = alloca (ctx->addr_size);
                (ctx->read_mem) (ctx->baton, buf, result, ctx->addr_size);
-               result = dwarf2_read_address (buf, buf + ctx->addr_size,
+               result = dwarf2_read_address (ctx->gdbarch,
+                                             buf, buf + ctx->addr_size,
                                              ctx->addr_size);
              }
              break;
@@ -556,7 +576,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
                int addr_size = *op_ptr++;
                gdb_byte *buf = alloca (addr_size);
                (ctx->read_mem) (ctx->baton, buf, result, addr_size);
-               result = dwarf2_read_address (buf, buf + addr_size,
+               result = dwarf2_read_address (ctx->gdbarch,
+                                             buf, buf + addr_size,
                                              addr_size);
              }
              break;
@@ -739,4 +760,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
       dwarf_expr_push (ctx, result);
     no_push:;
     }
+
+  ctx->recursion_depth--;
+  gdb_assert (ctx->recursion_depth >= 0);
 }