* configure.ac (AC_CHECK_FUNCS): Add check for setsid.
[deliverable/binutils-gdb.git] / gdb / dwarf2expr.c
index a87dfc6fb85162497839f3b7fd02c83da663f096..1102cf07b6ef99bca057856664296ef2f0b4aae6 100644 (file)
@@ -1,12 +1,15 @@
-/* Dwarf2 Expression Evaluator
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+/* DWARF 2 Expression Evaluator.
+
+   Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008
+   Free Software Foundation, Inc.
+
    Contributed by Daniel Berlin (dan@dberlin.org)
 
    This file is part of GDB.
 
    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,
@@ -15,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., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "symtab.h"
@@ -30,7 +31,8 @@
 /* Local prototypes.  */
 
 static void execute_stack_op (struct dwarf_expr_context *,
-                             unsigned char *, unsigned char *);
+                             gdb_byte *, gdb_byte *);
+static struct type *unsigned_address_type (void);
 
 /* 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;
@@ -171,15 +197,44 @@ read_sleb128 (unsigned char *buf, unsigned char *buf_end, LONGEST * r)
    number of bytes read from BUF.  */
 
 CORE_ADDR
-dwarf2_read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read)
+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 ("dwarf2_read_address: Corrupted DWARF expression.");
+  if (buf_end - buf < gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT)
+    error (_("dwarf2_read_address: Corrupted DWARF expression."));
+
+  *bytes_read = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT;
+
+  /* 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.  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.
+
+     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 (),
+                              extract_unsigned_integer 
+                                (buf,
+                                 gdbarch_addr_bit (current_gdbarch)
+                                   / TARGET_CHAR_BIT)));
 
-  *bytes_read = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
-  result = extract_address (buf, TARGET_ADDR_BIT / TARGET_CHAR_BIT);
   return result;
 }
 
@@ -188,7 +243,7 @@ dwarf2_read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read
 static struct type *
 unsigned_address_type (void)
 {
-  switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
+  switch (gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT)
     {
     case 2:
       return builtin_type_uint16;
@@ -198,7 +253,7 @@ unsigned_address_type (void)
       return builtin_type_uint64;
     default:
       internal_error (__FILE__, __LINE__,
-                     "Unsupported address size.\n");
+                     _("Unsupported address size.\n"));
     }
 }
 
@@ -207,7 +262,7 @@ unsigned_address_type (void)
 static struct type *
 signed_address_type (void)
 {
-  switch (TARGET_ADDR_BIT / TARGET_CHAR_BIT)
+  switch (gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT)
     {
     case 2:
       return builtin_type_int16;
@@ -217,7 +272,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 +280,19 @@ 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;
+  ctx->initialized = 1;  /* Default is initialized.  */
+
   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)
        {
@@ -356,43 +411,25 @@ 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 (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."));
 
-         if (expr_lval == lval_register)
-           {
-             ctx->regnum = op - DW_OP_reg0;
-             ctx->in_reg = 1;
-           }
-         else
-           result = memaddr;
+         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 +466,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 +474,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;
 
@@ -460,18 +496,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
            (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 = dwarf2_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;
@@ -499,7 +525,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];
@@ -524,13 +550,16 @@ 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 (gdbarch_addr_bit (current_gdbarch)
+                                         / TARGET_CHAR_BIT);
                int bytes_read;
 
                (ctx->read_mem) (ctx->baton, buf, result,
-                                TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+                                gdbarch_addr_bit (current_gdbarch)
+                                  / TARGET_CHAR_BIT);
                result = dwarf2_read_address (buf,
-                                             buf + (TARGET_ADDR_BIT
+                                             buf + (gdbarch_addr_bit
+                                                      (current_gdbarch)
                                                     / TARGET_CHAR_BIT),
                                              &bytes_read);
              }
@@ -538,12 +567,15 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
 
            case DW_OP_deref_size:
              {
-               char *buf = alloca (TARGET_ADDR_BIT / TARGET_CHAR_BIT);
+               gdb_byte *buf
+                  = alloca (gdbarch_addr_bit (current_gdbarch)
+                             / TARGET_CHAR_BIT);
                int bytes_read;
 
                (ctx->read_mem) (ctx->baton, buf, result, *op_ptr++);
                result = dwarf2_read_address (buf,
-                                             buf + (TARGET_ADDR_BIT
+                                             buf + (gdbarch_addr_bit
+                                                     (current_gdbarch)
                                                     / TARGET_CHAR_BIT),
                                              &bytes_read);
              }
@@ -593,7 +625,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);
@@ -606,6 +638,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;
@@ -626,6 +659,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);
@@ -653,13 +687,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);
@@ -682,8 +724,32 @@ 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;
+
+       case DW_OP_GNU_uninit:
+         if (op_ptr != op_end)
+           error (_("DWARF-2 expression error: DW_OP_GNU_unint must always "
+                  "be the very last op."));
+
+         ctx->initialized = 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.04167 seconds and 4 git commands to generate.