gdb
[deliverable/binutils-gdb.git] / gdb / dwarf2expr.c
index fdff8eaa851cbf1a48a021d75352c6446be5c7c5..e2e106ba849020c1a6f9705fddb346f4366074c7 100644 (file)
@@ -1,6 +1,7 @@
 /* DWARF 2 Expression Evaluator.
 
-   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    Contributed by Daniel Berlin (dan@dberlin.org)
 
@@ -8,7 +9,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,9 +18,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "symtab.h"
 #include "gdbcore.h"
 #include "elf/dwarf2.h"
 #include "dwarf2expr.h"
+#include "gdb_assert.h"
 
 /* Local prototypes.  */
 
 static void execute_stack_op (struct dwarf_expr_context *,
                              gdb_byte *, gdb_byte *);
+static struct type *unsigned_address_type (int);
 
 /* Create a new context for the expression evaluator.  */
 
@@ -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
@@ -192,31 +200,43 @@ read_sleb128 (gdb_byte *buf, gdb_byte *buf_end, LONGEST * r)
   return buf;
 }
 
-/* Read an address from BUF, and verify that it doesn't extend past
-   BUF_END.  The address is returned, and *BYTES_READ is set to the
-   number of bytes read from BUF.  */
+/* Read an address of size ADDR_SIZE from BUF, and verify that it
+   doesn't extend past BUF_END.  */
 
 CORE_ADDR
-dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int *bytes_read)
+dwarf2_read_address (struct gdbarch *gdbarch, gdb_byte *buf,
+                    gdb_byte *buf_end, int addr_size)
 {
   CORE_ADDR result;
 
-  if (buf_end - buf < TARGET_ADDR_BIT / TARGET_CHAR_BIT)
+  if (buf_end - buf < addr_size)
     error (_("dwarf2_read_address: Corrupted DWARF expression."));
 
-  *bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
-  /* NOTE: cagney/2003-05-22: This extract is assuming that a DWARF 2
-     address is always unsigned.  That may or may not be true.  */
-  result = extract_unsigned_integer (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
-  return result;
+  /* For most architectures, calling extract_unsigned_integer() alone
+     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.  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.  */
+
+  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, for unsigned arithmetic.  */
+/* Return the type of an address of size ADDR_SIZE,
+   for unsigned arithmetic.  */
 
 static struct type *
-unsigned_address_type (void)
+unsigned_address_type (int addr_size)
 {
-  switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
+  switch (addr_size)
     {
     case 2:
       return builtin_type_uint16;
@@ -230,12 +250,13 @@ unsigned_address_type (void)
     }
 }
 
-/* Return the type of an address, for signed arithmetic.  */
+/* Return the type of an address of size ADDR_SIZE,
+   for signed arithmetic.  */
 
 static struct type *
-signed_address_type (void)
+signed_address_type (int addr_size)
 {
-  switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
+  switch (addr_size)
     {
     case 2:
       return builtin_type_int16;
@@ -257,6 +278,12 @@ execute_stack_op (struct dwarf_expr_context *ctx,
                  gdb_byte *op_ptr, gdb_byte *op_end)
 {
   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)
     {
@@ -264,7 +291,6 @@ execute_stack_op (struct dwarf_expr_context *ctx,
       CORE_ADDR result;
       ULONGEST uoffset, reg;
       LONGEST offset;
-      int bytes_read;
 
       switch (op)
        {
@@ -304,8 +330,9 @@ execute_stack_op (struct dwarf_expr_context *ctx,
          break;
 
        case DW_OP_addr:
-         result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
-         op_ptr += bytes_read;
+         result = dwarf2_read_address (ctx->gdbarch,
+                                       op_ptr, op_end, ctx->addr_size);
+         op_ptr += ctx->addr_size;
          break;
 
        case DW_OP_const1u:
@@ -383,7 +410,9 @@ execute_stack_op (struct dwarf_expr_context *ctx,
        case DW_OP_reg29:
        case DW_OP_reg30:
        case DW_OP_reg31:
-         if (op_ptr != op_end && *op_ptr != DW_OP_piece)
+         if (op_ptr != op_end 
+             && *op_ptr != DW_OP_piece
+             && *op_ptr != DW_OP_GNU_uninit)
            error (_("DWARF-2 expression error: DW_OP_reg operations must be "
                   "used either alone or in conjuction with DW_OP_piece."));
 
@@ -485,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);
@@ -520,28 +563,22 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            {
            case DW_OP_deref:
              {
-               gdb_byte *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
-               int bytes_read;
-
-               (ctx->read_mem) (ctx->baton, buf, result,
-                                TARGET_ADDR_BIT / TARGET_CHAR_BIT);
-               result = dwarf2_read_address (buf,
-                                             buf + (TARGET_ADDR_BIT
-                                                    / TARGET_CHAR_BIT),
-                                             &bytes_read);
+               gdb_byte *buf = alloca (ctx->addr_size);
+               (ctx->read_mem) (ctx->baton, buf, result, ctx->addr_size);
+               result = dwarf2_read_address (ctx->gdbarch,
+                                             buf, buf + ctx->addr_size,
+                                             ctx->addr_size);
              }
              break;
 
            case DW_OP_deref_size:
              {
-               gdb_byte *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
-               int bytes_read;
-
-               (ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
-               result = dwarf2_read_address (buf,
-                                             buf + (TARGET_ADDR_BIT
-                                                    / TARGET_CHAR_BIT),
-                                             &bytes_read);
+               int addr_size = *op_ptr++;
+               gdb_byte *buf = alloca (addr_size);
+               (ctx->read_mem) (ctx->baton, buf, result, addr_size);
+               result = dwarf2_read_address (ctx->gdbarch,
+                                             buf, buf + addr_size,
+                                             addr_size);
              }
              break;
 
@@ -592,8 +629,10 @@ execute_stack_op (struct dwarf_expr_context *ctx,
            first = dwarf_expr_fetch (ctx, 0);
            dwarf_expr_pop (ctx);
 
-           val1 = value_from_longest (unsigned_address_type (), first);
-           val2 = value_from_longest (unsigned_address_type (), second);
+           val1 = value_from_longest
+                    (unsigned_address_type (ctx->addr_size), first);
+           val2 = value_from_longest
+                    (unsigned_address_type (ctx->addr_size), second);
 
            switch (op)
              {
@@ -626,7 +665,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
                 break;
              case DW_OP_shra:
                binop = BINOP_RSH;
-               val1 = value_from_longest (signed_address_type (), first);
+               val1 = value_from_longest
+                        (signed_address_type (ctx->addr_size), first);
                break;
              case DW_OP_xor:
                binop = BINOP_BITWISE_XOR;
@@ -704,6 +744,14 @@ execute_stack_op (struct dwarf_expr_context *ctx,
           }
           goto no_push;
 
+       case DW_OP_GNU_uninit:
+         if (op_ptr != op_end)
+           error (_("DWARF-2 expression error: DW_OP_GNU_uninit must always "
+                  "be the very last op."));
+
+         ctx->initialized = 0;
+         goto no_push;
+
        default:
          error (_("Unhandled dwarf expression opcode 0x%x"), op);
        }
@@ -712,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);
 }
This page took 0.079571 seconds and 4 git commands to generate.