2004-09-12 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / dwarf2expr.c
index 410cd54c6227f198cb5c8a771d0958461dd13553..a60e5a90e86f38e8695e4660eee329ea3bcd9f10 100644 (file)
@@ -42,6 +42,8 @@ new_dwarf_expr_context (void)
   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;
 }
 
@@ -51,6 +53,7 @@ void
 free_dwarf_expr_context (struct dwarf_expr_context *ctx)
 {
   xfree (ctx->stack);
+  xfree (ctx->pieces);
   xfree (ctx);
 }
 
@@ -100,6 +103,29 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int 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.  */
 
@@ -178,7 +204,9 @@ dwarf2_read_address (unsigned char *buf, unsigned char *buf_end, int *bytes_read
     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;
 }
 
@@ -439,18 +467,6 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
            result = dwarf_expr_fetch (ctx, 0);
            if (ctx->in_reg)
              result = (ctx->read_reg) (ctx->baton, result);
-           else
-             {
-               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);
-             }
            result = result + offset;
            ctx->stack_len = before_stack_len;
            ctx->in_reg = 0;
@@ -572,7 +588,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);
@@ -585,6 +601,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;
@@ -605,6 +622,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);
@@ -639,6 +657,14 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
          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);
@@ -661,8 +687,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.025704 seconds and 4 git commands to generate.