gas/ChangeLog:
[deliverable/binutils-gdb.git] / gdb / dwarf2expr.c
index 7456979b91f31450650b4f79e16792920eeb1eac..fdff8eaa851cbf1a48a021d75352c6446be5c7c5 100644 (file)
@@ -1,5 +1,7 @@
-/* Dwarf2 Expression Evaluator
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+/* DWARF 2 Expression Evaluator.
+
+   Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+
    Contributed by Daniel Berlin (dan@dberlin.org)
 
    This file is part of GDB.
@@ -16,8 +18,8 @@
 
    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., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -30,7 +32,7 @@
 /* Local prototypes.  */
 
 static void execute_stack_op (struct dwarf_expr_context *,
-                             unsigned char *, unsigned char *);
+                             gdb_byte *, gdb_byte *);
 
 /* Create a new context for the expression evaluator.  */
 
@@ -39,8 +41,11 @@ new_dwarf_expr_context (void)
 {
   struct dwarf_expr_context *retval;
   retval = xcalloc (1, sizeof (struct dwarf_expr_context));
-  retval->stack_len = 10;
-  retval->stack = xmalloc (10 * sizeof (CORE_ADDR));
+  retval->stack_len = 0;
+  retval->stack_allocated = 10;
+  retval->stack = xmalloc (retval->stack_allocated * sizeof (CORE_ADDR));
+  retval->num_pieces = 0;
+  retval->pieces = 0;
   return retval;
 }
 
@@ -50,6 +55,7 @@ void
 free_dwarf_expr_context (struct dwarf_expr_context *ctx)
 {
   xfree (ctx->stack);
+  xfree (ctx->pieces);
   xfree (ctx);
 }
 
@@ -61,12 +67,10 @@ dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need)
 {
   if (ctx->stack_len + need > ctx->stack_allocated)
     {
-      size_t templen = ctx->stack_len * 2;
-      while (templen < (ctx->stack_len + need))
-          templen *= 2;
+      size_t newlen = ctx->stack_len + need + 10;
       ctx->stack = xrealloc (ctx->stack,
-                            templen * sizeof (CORE_ADDR));
-      ctx->stack_allocated = templen;
+                            newlen * sizeof (CORE_ADDR));
+      ctx->stack_allocated = newlen;
     }
 }
 
@@ -85,7 +89,7 @@ void
 dwarf_expr_pop (struct dwarf_expr_context *ctx)
 {
   if (ctx->stack_len <= 0)
-    error ("dwarf expression stack underflow");
+    error (_("dwarf expression stack underflow"));
   ctx->stack_len--;
 }
 
@@ -94,19 +98,41 @@ dwarf_expr_pop (struct dwarf_expr_context *ctx)
 CORE_ADDR
 dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n)
 {
-  if (ctx->stack_len < n)
-     error ("Asked for position %d of stack, stack only has %d elements on it\n",
+  if (ctx->stack_len <= n)
+     error (_("Asked for position %d of stack, stack only has %d elements on it."),
            n, ctx->stack_len);
   return ctx->stack[ctx->stack_len - (1 + n)];
 
 }
 
+/* Add a new piece to CTX's piece list.  */
+static void
+add_piece (struct dwarf_expr_context *ctx,
+           int in_reg, CORE_ADDR value, ULONGEST size)
+{
+  struct dwarf_expr_piece *p;
+
+  ctx->num_pieces++;
+
+  if (ctx->pieces)
+    ctx->pieces = xrealloc (ctx->pieces,
+                            (ctx->num_pieces
+                             * sizeof (struct dwarf_expr_piece)));
+  else
+    ctx->pieces = xmalloc (ctx->num_pieces
+                           * sizeof (struct dwarf_expr_piece));
+
+  p = &ctx->pieces[ctx->num_pieces - 1];
+  p->in_reg = in_reg;
+  p->value = value;
+  p->size = size;
+}
+
 /* Evaluate the expression at ADDR (LEN bytes long) using the context
    CTX.  */
 
 void
-dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr,
-                size_t len)
+dwarf_expr_eval (struct dwarf_expr_context *ctx, gdb_byte *addr, size_t len)
 {
   execute_stack_op (ctx, addr, addr + len);
 }
@@ -115,17 +141,17 @@ dwarf_expr_eval (struct dwarf_expr_context *ctx, unsigned char *addr,
    by R, and return the new value of BUF.  Verify that it doesn't extend
    past BUF_END.  */
 
-unsigned char *
-read_uleb128 (unsigned char *buf, unsigned char *buf_end, ULONGEST * r)
+gdb_byte *
+read_uleb128 (gdb_byte *buf, gdb_byte *buf_end, ULONGEST * r)
 {
   unsigned shift = 0;
   ULONGEST result = 0;
-  unsigned char byte;
+  gdb_byte byte;
 
   while (1)
     {
       if (buf >= buf_end)
-       error ("read_uleb128: Corrupted DWARF expression.");
+       error (_("read_uleb128: Corrupted DWARF expression."));
 
       byte = *buf++;
       result |= (byte & 0x7f) << shift;
@@ -141,17 +167,17 @@ read_uleb128 (unsigned char *buf, unsigned char *buf_end, ULONGEST * r)
    by R, and return the new value of BUF.  Verify that it doesn't extend
    past BUF_END.  */
 
-unsigned char *
-read_sleb128 (unsigned char *buf, unsigned char *buf_end, LONGEST * r)
+gdb_byte *
+read_sleb128 (gdb_byte *buf, gdb_byte *buf_end, LONGEST * r)
 {
   unsigned shift = 0;
   LONGEST result = 0;
-  unsigned char byte;
+  gdb_byte byte;
 
   while (1)
     {
       if (buf >= buf_end)
-       error ("read_sleb128: Corrupted DWARF expression.");
+       error (_("read_sleb128: Corrupted DWARF expression."));
 
       byte = *buf++;
       result |= (byte & 0x7f) << shift;
@@ -170,16 +196,18 @@ read_sleb128 (unsigned char *buf, unsigned char *buf_end, LONGEST * r)
    BUF_END.  The address is returned, and *BYTES_READ is set to the
    number of bytes read from BUF.  */
 
-static CORE_ADDR
-read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read)
+CORE_ADDR
+dwarf2_read_address (gdb_byte *buf, gdb_byte *buf_end, int *bytes_read)
 {
   CORE_ADDR result;
 
   if (buf_end - buf < TARGET_ADDR_BIT / TARGET_CHAR_BIT)
-    error ("read_address: Corrupted DWARF expression.");
+    error (_("dwarf2_read_address: Corrupted DWARF expression."));
 
   *bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
-  result = extract_address (buf, 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;
 }
 
@@ -198,7 +226,7 @@ unsigned_address_type (void)
       return builtin_type_uint64;
     default:
       internal_error (__FILE__, __LINE__,
-                     "Unsupported address size.\n");
+                     _("Unsupported address size.\n"));
     }
 }
 
@@ -217,7 +245,7 @@ signed_address_type (void)
       return builtin_type_int64;
     default:
       internal_error (__FILE__, __LINE__,
-                     "Unsupported address size.\n");
+                     _("Unsupported address size.\n"));
     }
 }
 \f
@@ -225,19 +253,18 @@ signed_address_type (void)
    evaluate the expression between OP_PTR and OP_END.  */
 
 static void
-execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
-                 unsigned char *op_end)
+execute_stack_op (struct dwarf_expr_context *ctx,
+                 gdb_byte *op_ptr, gdb_byte *op_end)
 {
+  ctx->in_reg = 0;
+
   while (op_ptr < op_end)
     {
       enum dwarf_location_atom op = *op_ptr++;
-      CORE_ADDR result, memaddr;
+      CORE_ADDR result;
       ULONGEST uoffset, reg;
       LONGEST offset;
       int bytes_read;
-      enum lval_type expr_lval;
-
-      ctx->in_reg = 0;
 
       switch (op)
        {
@@ -277,7 +304,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
          break;
 
        case DW_OP_addr:
-         result = read_address (op_ptr, op_end, &bytes_read);
+         result = dwarf2_read_address (op_ptr, op_end, &bytes_read);
          op_ptr += bytes_read;
          break;
 
@@ -356,43 +383,23 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
        case DW_OP_reg29:
        case DW_OP_reg30:
        case DW_OP_reg31:
-         /* NOTE: in the presence of DW_OP_piece this check is incorrect.  */
-         if (op_ptr != op_end)
-           error ("DWARF-2 expression error: DW_OP_reg operations must be "
-                  "used alone.");
-
-         /* FIXME drow/2003-02-21: This call to read_reg could be pushed
-            into the evaluator's caller by changing the semantics for in_reg.
-            Then we wouldn't need to return an lval_type and a memaddr.  */
-         result = (ctx->read_reg) (ctx->baton, op - DW_OP_reg0, &expr_lval,
-                                   &memaddr);
-
-         if (expr_lval == lval_register)
-           {
-             ctx->regnum = op - DW_OP_reg0;
-             ctx->in_reg = 1;
-           }
-         else
-           result = memaddr;
+         if (op_ptr != op_end && *op_ptr != DW_OP_piece)
+           error (_("DWARF-2 expression error: DW_OP_reg operations must be "
+                  "used either alone or in conjuction with DW_OP_piece."));
+
+         result = op - DW_OP_reg0;
+         ctx->in_reg = 1;
 
          break;
 
        case DW_OP_regx:
          op_ptr = read_uleb128 (op_ptr, op_end, &reg);
-         if (op_ptr != op_end)
-           error ("DWARF-2 expression error: DW_OP_reg operations must be "
-                  "used alone.");
-
-         result = (ctx->read_reg) (ctx->baton, reg, &expr_lval, &memaddr);
-
-         if (expr_lval == lval_register)
-           {
-             ctx->regnum = reg;
-             ctx->in_reg = 1;
-           }
-         else
-           result = memaddr;
+         if (op_ptr != op_end && *op_ptr != DW_OP_piece)
+           error (_("DWARF-2 expression error: DW_OP_reg operations must be "
+                  "used either alone or in conjuction with DW_OP_piece."));
 
+         result = reg;
+         ctx->in_reg = 1;
          break;
 
        case DW_OP_breg0:
@@ -429,8 +436,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
        case DW_OP_breg31:
          {
            op_ptr = read_sleb128 (op_ptr, op_end, &offset);
-           result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0,
-                                     &expr_lval, &memaddr);
+           result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0);
            result += offset;
          }
          break;
@@ -438,13 +444,13 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
          {
            op_ptr = read_uleb128 (op_ptr, op_end, &reg);
            op_ptr = read_sleb128 (op_ptr, op_end, &offset);
-           result = (ctx->read_reg) (ctx->baton, reg, &expr_lval, &memaddr);
+           result = (ctx->read_reg) (ctx->baton, reg);
            result += offset;
          }
          break;
        case DW_OP_fbreg:
          {
-           unsigned char *datastart;
+           gdb_byte *datastart;
            size_t datalen;
            unsigned int before_stack_len;
 
@@ -454,20 +460,14 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
               afterwards, effectively erasing whatever the recursive
               call put there.  */
            before_stack_len = ctx->stack_len;
+           /* FIXME: cagney/2003-03-26: This code should be using
+               get_frame_base_address(), and then implement a dwarf2
+               specific this_base method.  */
            (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
            dwarf_expr_eval (ctx, datastart, datalen);
            result = dwarf_expr_fetch (ctx, 0);
-           if (! ctx->in_reg)
-             {
-               char *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 = read_address (buf,
-                                      buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT,
-                                      &bytes_read);
-             }
+           if (ctx->in_reg)
+             result = (ctx->read_reg) (ctx->baton, result);
            result = result + offset;
            ctx->stack_len = before_stack_len;
            ctx->in_reg = 0;
@@ -495,7 +495,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
            CORE_ADDR t1, t2, t3;
 
            if (ctx->stack_len < 3)
-              error ("Not enough elements for DW_OP_rot. Need 3, have %d\n",
+              error (_("Not enough elements for DW_OP_rot. Need 3, have %d."),
                      ctx->stack_len);
            t1 = ctx->stack[ctx->stack_len - 1];
            t2 = ctx->stack[ctx->stack_len - 2];
@@ -520,26 +520,28 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
            {
            case DW_OP_deref:
              {
-               char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+               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 = read_address (buf,
-                                      buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT,
-                                      &bytes_read);
+               result = dwarf2_read_address (buf,
+                                             buf + (TARGET_ADDR_BIT
+                                                    / TARGET_CHAR_BIT),
+                                             &bytes_read);
              }
              break;
 
            case DW_OP_deref_size:
              {
-               char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+               gdb_byte *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
                int bytes_read;
 
                (ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
-               result = read_address (buf,
-                                      buf + TARGET_ADDR_BIT / TARGET_CHAR_BIT,
-                                      &bytes_read);
+               result = dwarf2_read_address (buf,
+                                             buf + (TARGET_ADDR_BIT
+                                                    / TARGET_CHAR_BIT),
+                                             &bytes_read);
              }
              break;
 
@@ -587,7 +589,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
            second = dwarf_expr_fetch (ctx, 0);
            dwarf_expr_pop (ctx);
 
-           first = dwarf_expr_fetch (ctx, 1);
+           first = dwarf_expr_fetch (ctx, 0);
            dwarf_expr_pop (ctx);
 
            val1 = value_from_longest (unsigned_address_type (), first);
@@ -600,6 +602,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
                break;
              case DW_OP_div:
                binop = BINOP_DIV;
+                break;
              case DW_OP_minus:
                binop = BINOP_SUB;
                break;
@@ -620,6 +623,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
                break;
              case DW_OP_shr:
                binop = BINOP_RSH;
+                break;
              case DW_OP_shra:
                binop = BINOP_RSH;
                val1 = value_from_longest (signed_address_type (), first);
@@ -647,13 +651,21 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
                break;
              default:
                internal_error (__FILE__, __LINE__,
-                               "Can't be reached.");
+                               _("Can't be reached."));
              }
            result = value_as_long (value_binop (val1, val2, binop));
          }
          break;
 
        case DW_OP_GNU_push_tls_address:
+         /* Variable is at a constant offset in the thread-local
+         storage block into the objfile for the current thread and
+         the dynamic linker module containing this expression. Here
+         we return returns the offset from that base.  The top of the
+         stack has the offset from the beginning of the thread
+         control block at which the variable is located.  Nothing
+         should follow this operator, so the top of stack would be
+         returned.  */
          result = dwarf_expr_fetch (ctx, 0);
          dwarf_expr_pop (ctx);
          result = (ctx->get_tls_address) (ctx->baton, result);
@@ -676,8 +688,24 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
        case DW_OP_nop:
          goto no_push;
 
+        case DW_OP_piece:
+          {
+            ULONGEST size;
+            CORE_ADDR addr_or_regnum;
+
+            /* Record the piece.  */
+            op_ptr = read_uleb128 (op_ptr, op_end, &size);
+            addr_or_regnum = dwarf_expr_fetch (ctx, 0);
+            add_piece (ctx, ctx->in_reg, addr_or_regnum, size);
+
+            /* Pop off the address/regnum, and clear the in_reg flag.  */
+            dwarf_expr_pop (ctx);
+            ctx->in_reg = 0;
+          }
+          goto no_push;
+
        default:
-         error ("Unhandled dwarf expression opcode");
+         error (_("Unhandled dwarf expression opcode 0x%x"), op);
        }
 
       /* Most things push a result value.  */
This page took 0.043245 seconds and 4 git commands to generate.