gdb
authorTom Tromey <tromey@redhat.com>
Fri, 11 Sep 2009 18:38:39 +0000 (18:38 +0000)
committerTom Tromey <tromey@redhat.com>
Fri, 11 Sep 2009 18:38:39 +0000 (18:38 +0000)
* dwarf2loc.c (struct piece_closure) <arch>: New field.
(dwarf2_evaluate_loc_desc): Update.
(dwarf2_loc_desc_needs_frame): Likewise.
(allocate_piece_closure): Initialize new field.
(read_pieced_value): Update.
(write_pieced_value): Update.
(copy_pieced_value_closure): Update.
* dwarf2expr.h (enum dwarf_value_location): New.
(struct dwarf_expr_context) <in_reg>: Remove.
<location, len, data>: New fields.
(struct dwarf_expr_piece) <in_reg, value>: Remove.
<location, v>: New fields.
* dwarf2expr.c (add_piece): Remove in_reg, value arguments.
Update.
(require_composition): New function.
(execute_stack_op): Update.
<DW_OP_implicit_value, DW_OP_stack_value>: New cases.
<DW_OP_reg0>: Set location, not in_reg.
<DW_OP_regx>: Likewise.  Use require_composition.
<DW_OP_fbreg>: Update.
<DW_OP_piece>: Likewise.
* dwarf2-frame.c (execute_stack_op): Update.
gdb/testsuite
* gdb.dwarf2/valop.S: New file.
* gdb.dwarf2/valop.exp: New file.

gdb/ChangeLog
gdb/dwarf2-frame.c
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/valop.S [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/valop.exp [new file with mode: 0644]

index a1f3d27121a43b10207be37fd68415400fbdbcae..bc93f25e8f3fb6906264d6dfab4d27868ab3910c 100644 (file)
@@ -1,3 +1,28 @@
+2009-09-11  Tom Tromey  <tromey@redhat.com>
+
+       * dwarf2loc.c (struct piece_closure) <arch>: New field.
+       (dwarf2_evaluate_loc_desc): Update.
+       (dwarf2_loc_desc_needs_frame): Likewise.
+       (allocate_piece_closure): Initialize new field.
+       (read_pieced_value): Update.
+       (write_pieced_value): Update.
+       (copy_pieced_value_closure): Update.
+       * dwarf2expr.h (enum dwarf_value_location): New.
+       (struct dwarf_expr_context) <in_reg>: Remove.
+       <location, len, data>: New fields.
+       (struct dwarf_expr_piece) <in_reg, value>: Remove.
+       <location, v>: New fields.
+       * dwarf2expr.c (add_piece): Remove in_reg, value arguments.
+       Update.
+       (require_composition): New function.
+       (execute_stack_op): Update.
+       <DW_OP_implicit_value, DW_OP_stack_value>: New cases.
+       <DW_OP_reg0>: Set location, not in_reg.
+       <DW_OP_regx>: Likewise.  Use require_composition.
+       <DW_OP_fbreg>: Update.
+       <DW_OP_piece>: Likewise.
+       * dwarf2-frame.c (execute_stack_op): Update.
+
 2009-09-10  Anthony Green  <green@moxielogic.com>
 
        * moxie-tdep.c (moxie_analyze_prologue): Recognize new prologue
index f9ca067dfe163e5acaf9c52437a48b6902fd230c..a923edffdcca6763c6a03c19753d6926c45b084c 100644 (file)
@@ -379,8 +379,15 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
   dwarf_expr_eval (ctx, exp, len);
   result = dwarf_expr_fetch (ctx, 0);
 
-  if (ctx->in_reg)
+  if (ctx->location == DWARF_VALUE_REGISTER)
     result = read_reg (this_frame, result);
+  else if (ctx->location != DWARF_VALUE_MEMORY)
+    {
+      /* This is actually invalid DWARF, but if we ever do run across
+        it somehow, we might as well support it.  So, instead, report
+        it as unimplemented.  */
+      error (_("Not implemented: computing unwound register using explicit value operator"));
+    }
 
   do_cleanups (old_chain);
 
index 6401e722c4220bbcd339b238b84feffc2ac50208..1ff7c3f0075f1d5306b9f055df95ad702eaeafdd 100644 (file)
@@ -125,8 +125,7 @@ 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)
+add_piece (struct dwarf_expr_context *ctx, ULONGEST size)
 {
   struct dwarf_expr_piece *p;
 
@@ -141,9 +140,15 @@ add_piece (struct dwarf_expr_context *ctx,
                            * sizeof (struct dwarf_expr_piece));
 
   p = &ctx->pieces[ctx->num_pieces - 1];
-  p->in_reg = in_reg;
-  p->value = value;
+  p->location = ctx->location;
   p->size = size;
+  if (p->location == DWARF_VALUE_LITERAL)
+    {
+      p->v.literal.data = ctx->data;
+      p->v.literal.length = ctx->len;
+    }
+  else
+    p->v.value = dwarf_expr_fetch (ctx, 0);
 }
 
 /* Evaluate the expression at ADDR (LEN bytes long) using the context
@@ -287,6 +292,23 @@ signed_address_type (struct gdbarch *gdbarch, int addr_size)
     }
 }
 \f
+
+/* Check that the current operator is either at the end of an
+   expression, or that it is followed by a composition operator.  */
+
+static void
+require_composition (gdb_byte *op_ptr, gdb_byte *op_end, const char *op_name)
+{
+  /* It seems like DW_OP_GNU_uninit should be handled here.  However,
+     it doesn't seem to make sense for DW_OP_*_value, and it was not
+     checked at the other place that this function is called.  */
+  if (op_ptr != op_end && *op_ptr != DW_OP_piece && *op_ptr != DW_OP_bit_piece)
+    error (_("DWARF-2 expression error: `%s' operations must be "
+            "used either alone or in conjuction with DW_OP_piece "
+            "or DW_OP_bit_piece."),
+          op_name);
+}
+
 /* The engine for the expression evaluator.  Using the context in CTX,
    evaluate the expression between OP_PTR and OP_END.  */
 
@@ -295,8 +317,7 @@ execute_stack_op (struct dwarf_expr_context *ctx,
                  gdb_byte *op_ptr, gdb_byte *op_end)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch);
-
-  ctx->in_reg = 0;
+  ctx->location = DWARF_VALUE_MEMORY;
   ctx->initialized = 1;  /* Default is initialized.  */
 
   if (ctx->recursion_depth > ctx->max_recursion_depth)
@@ -436,20 +457,36 @@ execute_stack_op (struct dwarf_expr_context *ctx,
                   "used either alone or in conjuction with DW_OP_piece."));
 
          result = op - DW_OP_reg0;
-         ctx->in_reg = 1;
-
+         ctx->location = DWARF_VALUE_REGISTER;
          break;
 
        case DW_OP_regx:
          op_ptr = read_uleb128 (op_ptr, op_end, &reg);
-         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."));
+         require_composition (op_ptr, op_end, "DW_OP_regx");
 
          result = reg;
-         ctx->in_reg = 1;
+         ctx->location = DWARF_VALUE_REGISTER;
          break;
 
+       case DW_OP_implicit_value:
+         {
+           ULONGEST len;
+           op_ptr = read_uleb128 (op_ptr, op_end, &len);
+           if (op_ptr + len > op_end)
+             error (_("DW_OP_implicit_value: too few bytes available."));
+           ctx->len = len;
+           ctx->data = op_ptr;
+           ctx->location = DWARF_VALUE_LITERAL;
+           op_ptr += len;
+           require_composition (op_ptr, op_end, "DW_OP_implicit_value");
+         }
+         goto no_push;
+
+       case DW_OP_stack_value:
+         ctx->location = DWARF_VALUE_STACK;
+         require_composition (op_ptr, op_end, "DW_OP_stack_value");
+         goto no_push;
+
        case DW_OP_breg0:
        case DW_OP_breg1:
        case DW_OP_breg2:
@@ -513,12 +550,15 @@ execute_stack_op (struct dwarf_expr_context *ctx,
                specific this_base method.  */
            (ctx->get_frame_base) (ctx->baton, &datastart, &datalen);
            dwarf_expr_eval (ctx, datastart, datalen);
+           if (ctx->location == DWARF_VALUE_LITERAL
+               || ctx->location == DWARF_VALUE_STACK)
+             error (_("Not implemented: computing frame base using explicit value operator"));
            result = dwarf_expr_fetch (ctx, 0);
-           if (ctx->in_reg)
+           if (ctx->location == DWARF_VALUE_REGISTER)
              result = (ctx->read_reg) (ctx->baton, result);
            result = result + offset;
            ctx->stack_len = before_stack_len;
-           ctx->in_reg = 0;
+           ctx->location = DWARF_VALUE_MEMORY;
          }
          break;
        case DW_OP_dup:
@@ -758,12 +798,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 
             /* 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);
+           add_piece (ctx, size);
 
-            /* Pop off the address/regnum, and clear the in_reg flag.  */
-            dwarf_expr_pop (ctx);
-            ctx->in_reg = 0;
+            /* Pop off the address/regnum, and reset the location
+              type.  */
+           if (ctx->location != DWARF_VALUE_LITERAL)
+             dwarf_expr_pop (ctx);
+            ctx->location = DWARF_VALUE_MEMORY;
           }
           goto no_push;
 
index 6b3a068e69e13803fda375d40514c6e1f737670e..9d9b127add12683d873363eb6f0619099328af32 100644 (file)
 #if !defined (DWARF2EXPR_H)
 #define DWARF2EXPR_H
 
+/* The location of a value.  */
+enum dwarf_value_location
+{
+  /* The piece is in memory.  */
+  DWARF_VALUE_MEMORY,
+  /* The piece is in a register.  */
+  DWARF_VALUE_REGISTER,
+  /* The piece is on the stack.  */
+  DWARF_VALUE_STACK,
+  /* The piece is a literal.  */
+  DWARF_VALUE_LITERAL
+};
+
 /* The expression evaluator works with a dwarf_expr_context, describing
    its current state and its callbacks.  */
 struct dwarf_expr_context
@@ -80,9 +93,13 @@ struct dwarf_expr_context
      depth we'll tolerate before raising an error.  */
   int recursion_depth, max_recursion_depth;
 
-  /* Non-zero if the result is in a register.  The register number
-     will be on the expression stack.  */
-  int in_reg;
+  /* Location of the value.  */
+  enum dwarf_value_location location;
+
+  /* For VALUE_LITERAL, a the current literal value's length and
+     data.  */
+  ULONGEST len;
+  gdb_byte *data;
 
   /* Initialization status of variable: Non-zero if variable has been
      initialized; zero otherwise.  */
@@ -93,9 +110,9 @@ struct dwarf_expr_context
 
      Each time DW_OP_piece is executed, we add a new element to the
      end of this array, recording the current top of the stack, the
-     current in_reg flag, and the size given as the operand to
-     DW_OP_piece.  We then pop the top value from the stack, clear the
-     in_reg flag, and resume evaluation.
+     current location, and the size given as the operand to
+     DW_OP_piece.  We then pop the top value from the stack, rest the
+     location, and resume evaluation.
 
      The Dwarf spec doesn't say whether DW_OP_piece pops the top value
      from the stack.  We do, ensuring that clients of this interface
@@ -106,12 +123,11 @@ struct dwarf_expr_context
 
      If an expression never uses DW_OP_piece, num_pieces will be zero.
      (It would be nice to present these cases as expressions yielding
-     a single piece, with in_reg clear, so that callers need not
-     distinguish between the no-DW_OP_piece and one-DW_OP_piece cases.
-     But expressions with no DW_OP_piece operations have no value to
-     place in a piece's 'size' field; the size comes from the
-     surrounding data.  So the two cases need to be handled
-     separately.)  */
+     a single piece, so that callers need not distinguish between the
+     no-DW_OP_piece and one-DW_OP_piece cases.  But expressions with
+     no DW_OP_piece operations have no value to place in a piece's
+     'size' field; the size comes from the surrounding data.  So the
+     two cases need to be handled separately.)  */
   int num_pieces;
   struct dwarf_expr_piece *pieces;
 };
@@ -120,13 +136,22 @@ struct dwarf_expr_context
 /* A piece of an object, as recorded by DW_OP_piece.  */
 struct dwarf_expr_piece
 {
-  /* If IN_REG is zero, then the piece is in memory, and VALUE is its address.
-     If IN_REG is non-zero, then the piece is in a register, and VALUE
-     is the register number.  */
-  int in_reg;
-
-  /* This piece's address or register number.  */
-  CORE_ADDR value;
+  enum dwarf_value_location location;
+
+  union
+  {
+    /* This piece's address or register number.  */
+    CORE_ADDR value;
+
+    struct
+    {
+      /* A pointer to the data making up this piece, for literal
+        pieces.  */
+      gdb_byte *data;
+      /* The length of the available data.  */
+      ULONGEST length;
+    } literal;
+  } v;
 
   /* The length of the piece, in bytes.  */
   ULONGEST size;
index c3f6d40580182acc8c5785c29eccae7350aa5ab4..c314a78a3b3a6f9480b4d062c32fe01c840e2473 100644 (file)
@@ -220,6 +220,9 @@ struct piece_closure
   /* The number of pieces used to describe this variable.  */
   int n_pieces;
 
+  /* The architecture, used only for DWARF_VALUE_STACK.  */
+  struct gdbarch *arch;
+
   /* The pieces themselves.  */
   struct dwarf_expr_piece *pieces;
 };
@@ -228,11 +231,13 @@ struct piece_closure
    PIECES.  */
 
 static struct piece_closure *
-allocate_piece_closure (int n_pieces, struct dwarf_expr_piece *pieces)
+allocate_piece_closure (int n_pieces, struct dwarf_expr_piece *pieces,
+                       struct gdbarch *arch)
 {
   struct piece_closure *c = XZALLOC (struct piece_closure);
 
   c->n_pieces = n_pieces;
+  c->arch = arch;
   c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece);
 
   memcpy (c->pieces, pieces, n_pieces * sizeof (struct dwarf_expr_piece));
@@ -253,24 +258,49 @@ read_pieced_value (struct value *v)
   for (i = 0; i < c->n_pieces; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
-
-      if (frame == NULL)
+      switch (p->location)
        {
-         memset (contents + offset, 0, p->size);
-         set_value_optimized_out (v, 1);
-       }
-      else if (p->in_reg)
-       {
-         struct gdbarch *arch = get_frame_arch (frame);
-         gdb_byte regval[MAX_REGISTER_SIZE];
-         int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->value);
-
-         get_frame_register (frame, gdb_regnum, regval);
-         memcpy (contents + offset, regval, p->size);
-       }
-      else
-       {
-         read_memory (p->value, contents + offset, p->size);
+       case DWARF_VALUE_REGISTER:
+         {
+           struct gdbarch *arch = get_frame_arch (frame);
+           bfd_byte regval[MAX_REGISTER_SIZE];
+           int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch,
+                                                          p->v.value);
+           get_frame_register (frame, gdb_regnum, regval);
+           memcpy (contents + offset, regval, p->size);
+         }
+         break;
+
+       case DWARF_VALUE_MEMORY:
+         read_memory (p->v.value, contents + offset, p->size);
+         break;
+
+       case DWARF_VALUE_STACK:
+         {
+           gdb_byte bytes[sizeof (ULONGEST)];
+           size_t n;
+           int addr_size = gdbarch_addr_bit (c->arch) / 8;
+           store_unsigned_integer (bytes, addr_size,
+                                   gdbarch_byte_order (c->arch),
+                                   p->v.value);
+           n = p->size;
+           if (n > addr_size)
+             n = addr_size;
+           memcpy (contents + offset, bytes, n);
+         }
+         break;
+
+       case DWARF_VALUE_LITERAL:
+         {
+           size_t n = p->size;
+           if (n > p->v.literal.length)
+             n = p->v.literal.length;
+           memcpy (contents + offset, p->v.literal.data, n);
+         }
+         break;
+
+       default:
+         internal_error (__FILE__, __LINE__, _("invalid location type"));
        }
       offset += p->size;
     }
@@ -295,15 +325,21 @@ write_pieced_value (struct value *to, struct value *from)
   for (i = 0; i < c->n_pieces; i++)
     {
       struct dwarf_expr_piece *p = &c->pieces[i];
-      if (p->in_reg)
+      switch (p->location)
        {
-         struct gdbarch *arch = get_frame_arch (frame);
-         int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->value);
-         put_frame_register (frame, gdb_regnum, contents + offset);
-       }
-      else
-       {
-         write_memory (p->value, contents + offset, p->size);
+       case DWARF_VALUE_REGISTER:
+         {
+           struct gdbarch *arch = get_frame_arch (frame);
+           int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value);
+           put_frame_register (frame, gdb_regnum, contents + offset);
+         }
+         break;
+       case DWARF_VALUE_MEMORY:
+         write_memory (p->v.value, contents + offset, p->size);
+         break;
+       default:
+         set_value_optimized_out (to, 1);
+         return;
        }
       offset += p->size;
     }
@@ -314,7 +350,7 @@ copy_pieced_value_closure (struct value *v)
 {
   struct piece_closure *c = (struct piece_closure *) value_computed_closure (v);
   
-  return allocate_piece_closure (c->n_pieces, c->pieces);
+  return allocate_piece_closure (c->n_pieces, c->pieces, c->arch);
 }
 
 static void
@@ -376,28 +412,71 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
       struct piece_closure *c;
       struct frame_id frame_id = get_frame_id (frame);
 
-      c = allocate_piece_closure (ctx->num_pieces, ctx->pieces);
+      c = allocate_piece_closure (ctx->num_pieces, ctx->pieces, ctx->gdbarch);
       retval = allocate_computed_value (SYMBOL_TYPE (var),
                                        &pieced_value_funcs,
                                        c);
       VALUE_FRAME_ID (retval) = frame_id;
     }
-  else if (ctx->in_reg)
-    {
-      struct gdbarch *arch = get_frame_arch (frame);
-      CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
-      int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
-      retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
-    }
   else
     {
-      CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
-
-      retval = allocate_value (SYMBOL_TYPE (var));
-      VALUE_LVAL (retval) = lval_memory;
-      set_value_lazy (retval, 1);
-      set_value_stack (retval, 1);
-      set_value_address (retval, address);
+      switch (ctx->location)
+       {
+       case DWARF_VALUE_REGISTER:
+         {
+           struct gdbarch *arch = get_frame_arch (frame);
+           CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
+           int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
+           retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
+         }
+         break;
+
+       case DWARF_VALUE_MEMORY:
+         {
+           CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
+
+           retval = allocate_value (SYMBOL_TYPE (var));
+           VALUE_LVAL (retval) = lval_memory;
+           set_value_lazy (retval, 1);
+           set_value_stack (retval, 1);
+           set_value_address (retval, address);
+         }
+         break;
+
+       case DWARF_VALUE_STACK:
+         {
+           gdb_byte bytes[sizeof (ULONGEST)];
+           ULONGEST value = (ULONGEST) dwarf_expr_fetch (ctx, 0);
+           bfd_byte *contents;
+           size_t n = ctx->addr_size;
+
+           store_unsigned_integer (bytes, ctx->addr_size,
+                                   gdbarch_byte_order (ctx->gdbarch),
+                                   value);
+           retval = allocate_value (SYMBOL_TYPE (var));
+           contents = value_contents_raw (retval);
+           if (n > TYPE_LENGTH (SYMBOL_TYPE (var)))
+             n = TYPE_LENGTH (SYMBOL_TYPE (var));
+           memcpy (contents, bytes, n);
+         }
+         break;
+
+       case DWARF_VALUE_LITERAL:
+         {
+           bfd_byte *contents;
+           size_t n = ctx->len;
+
+           retval = allocate_value (SYMBOL_TYPE (var));
+           contents = value_contents_raw (retval);
+           if (n > TYPE_LENGTH (SYMBOL_TYPE (var)))
+             n = TYPE_LENGTH (SYMBOL_TYPE (var));
+           memcpy (contents, ctx->data, n);
+         }
+         break;
+
+       default:
+         internal_error (__FILE__, __LINE__, _("invalid location type"));
+       }
     }
 
   set_value_initialized (retval, ctx->initialized);
@@ -494,7 +573,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
 
   dwarf_expr_eval (ctx, data, size);
 
-  in_reg = ctx->in_reg;
+  in_reg = ctx->location == DWARF_VALUE_REGISTER;
 
   if (ctx->num_pieces > 0)
     {
@@ -503,7 +582,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
       /* If the location has several pieces, and any of them are in
          registers, then we will need a frame to fetch them from.  */
       for (i = 0; i < ctx->num_pieces; i++)
-        if (ctx->pieces[i].in_reg)
+        if (ctx->pieces[i].location == DWARF_VALUE_REGISTER)
           in_reg = 1;
     }
 
index 1aa557fd4888dc4818dc5cbbbead44c59eec4d62..1ce646b9e02afbef1e46058da9f98f2422e17492 100644 (file)
@@ -1,3 +1,8 @@
+2009-09-11  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.dwarf2/valop.S: New file.
+       * gdb.dwarf2/valop.exp: New file.
+
 2009-09-11  Mark Kettenis  <kettenis@gnu.org>
 
        * gdb.threads/current-lwp-dead.exp: Only run this on Linux.
diff --git a/gdb/testsuite/gdb.dwarf2/valop.S b/gdb/testsuite/gdb.dwarf2/valop.S
new file mode 100644 (file)
index 0000000..313a00b
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+   Copyright 2009 Free Software Foundation, Inc.
+
+   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 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This was compiled from a trivial program just to test the
+   DW_OP_stack_value and DW_OP_implicit_value operators:
+
+    unsigned int func (unsigned int arg) __attribute__ ((__noinline__));
+
+    unsigned int func (unsigned int arg)
+    {
+      unsigned int uses_stack_op = 23;
+      unsigned int uses_lit_op = 0x7fffffff;
+      unsigned int result = arg;
+
+      if (arg % 2)
+       result += uses_lit_op + uses_stack_op;
+      else
+       {
+         ++uses_stack_op;
+         ++uses_lit_op;
+
+         result -= uses_stack_op + uses_lit_op;
+       }
+
+      return result * uses_stack_op;  // line 19, see the .exp file
+    }
+
+    int main (int argc, char *argv[])
+    {
+      return func (1024);
+    }
+
+  Then it was compiled with:
+       
+       gcc -fvar-tracking{,-assignments} -gdwarf-3
+       -fno-inline{,-functions,-small-functions,-functions-called-once}
+       -O2
+
+*/
+
+       .file   "valop.c"
+       .section        .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+       .section        .debug_info,"",@progbits
+.Ldebug_info0:
+       .section        .debug_line,"",@progbits
+.Ldebug_line0:
+       .text
+.Ltext0:
+       .p2align 4,,15
+.globl func
+       .type   func, @function
+func:
+.LFB0:
+       .file 1 "valop.c"
+       .loc 1 4 0
+       .cfi_startproc
+.LVL0:
+       pushl   %ebp
+       .cfi_def_cfa_offset 8
+       movl    %esp, %ebp
+       .cfi_offset 5, -8
+       .cfi_def_cfa_register 5
+       .loc 1 4 0
+       movl    8(%ebp), %eax
+.LVL1:
+       .loc 1 9 0
+       testb   $1, %al
+       jne     .L5
+.LVL2:
+       .loc 1 16 0
+       addl    $2147483624, %eax
+.LVL3:
+       .loc 1 13 0
+       movl    $24, %edx
+.LVL4:
+       .loc 1 16 0
+       imull   %edx, %eax
+.LVL5:
+       .loc 1 20 0
+       popl    %ebp
+       .cfi_remember_state
+       .cfi_restore 5
+       .cfi_def_cfa 4, 4
+       ret
+.LVL6:
+       .p2align 4,,7
+       .p2align 3
+.L5:
+       .cfi_restore_state
+       .loc 1 10 0
+       subl    $2147483626, %eax
+.LVL7:
+       .loc 1 5 0
+       movl    $23, %edx
+.LVL8:
+       .loc 1 16 0
+       imull   %edx, %eax
+.LVL9:
+       .loc 1 20 0
+       popl    %ebp
+       .cfi_def_cfa 4, 4
+       .cfi_restore 5
+       ret
+       .cfi_endproc
+.LFE0:
+       .size   func, .-func
+       .p2align 4,,15
+.globl _start
+       .type   _start, @function
+_start:
+.LFB1:
+       .loc 1 23 0
+       .cfi_startproc
+.LVL10:
+       pushl   %ebp
+       .cfi_def_cfa_offset 8
+       movl    %esp, %ebp
+       .cfi_offset 5, -8
+       .cfi_def_cfa_register 5
+       subl    $4, %esp
+       .loc 1 24 0
+       movl    $1024, (%esp)
+       call    func
+.LVL11:
+       .loc 1 25 0
+       leave
+       .cfi_restore 5
+       .cfi_def_cfa 4, 4
+       ret
+       .cfi_endproc
+.LFE1:
+       .size   _start, .-_start
+.Letext0:
+       .section        .debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+       .long   .LVL0-.Ltext0
+       .long   .LVL2-.Ltext0
+       .value  0x4
+       .byte   0x47
+       .byte   0x9f
+       .byte   0x93
+       .uleb128 0x4
+       .long   .LVL2-.Ltext0
+       .long   .LVL4-.Ltext0
+       .value  0x4
+       .byte   0x48
+       .byte   0x9f
+       .byte   0x93
+       .uleb128 0x4
+       .long   .LVL4-.Ltext0
+       .long   .LVL6-.Ltext0
+       .value  0x1
+       .byte   0x52
+       .long   .LVL6-.Ltext0
+       .long   .LVL8-.Ltext0
+       .value  0x4
+       .byte   0x47
+       .byte   0x9f
+       .byte   0x93
+       .uleb128 0x4
+       .long   .LVL8-.Ltext0
+       .long   .LFE0-.Ltext0
+       .value  0x1
+       .byte   0x52
+       .long   0x0
+       .long   0x0
+.LLST1:
+       .long   .LVL0-.Ltext0
+       .long   .LVL2-.Ltext0
+       .value  0x6
+       .byte   0x9e
+       .uleb128 0x4
+       .long   0x7fffffff
+       .long   .LVL2-.Ltext0
+       .long   .LVL6-.Ltext0
+       .value  0x6
+       .byte   0x9e
+       .uleb128 0x4
+       .long   0x80000000
+       .long   .LVL6-.Ltext0
+       .long   .LFE0-.Ltext0
+       .value  0x6
+       .byte   0x9e
+       .uleb128 0x4
+       .long   0x7fffffff
+       .long   0x0
+       .long   0x0
+.LLST2:
+       .long   .LVL1-.Ltext0
+       .long   .LVL3-.Ltext0
+       .value  0x1
+       .byte   0x50
+       .long   .LVL3-.Ltext0
+       .long   .LVL5-.Ltext0
+       .value  0x1
+       .byte   0x50
+       .long   .LVL6-.Ltext0
+       .long   .LVL7-.Ltext0
+       .value  0x1
+       .byte   0x50
+       .long   .LVL7-.Ltext0
+       .long   .LVL9-.Ltext0
+       .value  0x1
+       .byte   0x50
+       .long   0x0
+       .long   0x0
+.LLST3:
+       .long   .LVL10-.Ltext0
+       .long   .LVL11-1-.Ltext0
+       .value  0x2
+       .byte   0x91
+       .sleb128 0
+       .long   0x0
+       .long   0x0
+.LLST4:
+       .long   .LVL10-.Ltext0
+       .long   .LVL11-1-.Ltext0
+       .value  0x2
+       .byte   0x91
+       .sleb128 4
+       .long   0x0
+       .long   0x0
+       .section        .debug_info
+       .long   0xd4
+       .value  0x3
+       .long   .Ldebug_abbrev0
+       .byte   0x4
+       .uleb128 0x1
+       .long   .LASF9
+       .byte   0x1
+       .long   .LASF10
+       .long   .LASF11
+       .long   .Ltext0
+       .long   .Letext0
+       .long   .Ldebug_line0
+       .uleb128 0x2
+       .byte   0x1
+       .long   .LASF3
+       .byte   0x1
+       .byte   0x3
+       .byte   0x1
+       .long   0x7c
+       .long   .LFB0
+       .long   .LFE0
+       .byte   0x1
+       .byte   0x9c
+       .long   0x7c
+       .uleb128 0x3
+       .string "arg"
+       .byte   0x1
+       .byte   0x3
+       .long   0x7c
+       .byte   0x2
+       .byte   0x91
+       .sleb128 0
+       .uleb128 0x4
+       .long   .LASF0
+       .byte   0x1
+       .byte   0x5
+       .long   0x7c
+       .long   .LLST0
+       .uleb128 0x4
+       .long   .LASF1
+       .byte   0x1
+       .byte   0x6
+       .long   0x7c
+       .long   .LLST1
+       .uleb128 0x4
+       .long   .LASF2
+       .byte   0x1
+       .byte   0x7
+       .long   0x7c
+       .long   .LLST2
+       .byte   0x0
+       .uleb128 0x5
+       .byte   0x4
+       .byte   0x7
+       .long   .LASF7
+       .uleb128 0x2
+       .byte   0x1
+       .long   .LASF4
+       .byte   0x1
+       .byte   0x16
+       .byte   0x1
+       .long   0xbd
+       .long   .LFB1
+       .long   .LFE1
+       .byte   0x1
+       .byte   0x9c
+       .long   0xbd
+       .uleb128 0x6
+       .long   .LASF5
+       .byte   0x1
+       .byte   0x16
+       .long   0xbd
+       .long   .LLST3
+       .uleb128 0x6
+       .long   .LASF6
+       .byte   0x1
+       .byte   0x16
+       .long   0xc4
+       .long   .LLST4
+       .byte   0x0
+       .uleb128 0x7
+       .byte   0x4
+       .byte   0x5
+       .string "int"
+       .uleb128 0x8
+       .byte   0x4
+       .long   0xca
+       .uleb128 0x8
+       .byte   0x4
+       .long   0xd0
+       .uleb128 0x5
+       .byte   0x1
+       .byte   0x6
+       .long   .LASF8
+       .byte   0x0
+       .section        .debug_abbrev
+       .uleb128 0x1
+       .uleb128 0x11
+       .byte   0x1
+       .uleb128 0x25
+       .uleb128 0xe
+       .uleb128 0x13
+       .uleb128 0xb
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x1b
+       .uleb128 0xe
+       .uleb128 0x11
+       .uleb128 0x1
+       .uleb128 0x12
+       .uleb128 0x1
+       .uleb128 0x10
+       .uleb128 0x6
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x2
+       .uleb128 0x2e
+       .byte   0x1
+       .uleb128 0x3f
+       .uleb128 0xc
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x27
+       .uleb128 0xc
+       .uleb128 0x49
+       .uleb128 0x13
+       .uleb128 0x11
+       .uleb128 0x1
+       .uleb128 0x12
+       .uleb128 0x1
+       .uleb128 0x40
+       .uleb128 0xa
+       .uleb128 0x1
+       .uleb128 0x13
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x3
+       .uleb128 0x5
+       .byte   0x0
+       .uleb128 0x3
+       .uleb128 0x8
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x49
+       .uleb128 0x13
+       .uleb128 0x2
+       .uleb128 0xa
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x4
+       .uleb128 0x34
+       .byte   0x0
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x49
+       .uleb128 0x13
+       .uleb128 0x2
+       .uleb128 0x6
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x5
+       .uleb128 0x24
+       .byte   0x0
+       .uleb128 0xb
+       .uleb128 0xb
+       .uleb128 0x3e
+       .uleb128 0xb
+       .uleb128 0x3
+       .uleb128 0xe
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x6
+       .uleb128 0x5
+       .byte   0x0
+       .uleb128 0x3
+       .uleb128 0xe
+       .uleb128 0x3a
+       .uleb128 0xb
+       .uleb128 0x3b
+       .uleb128 0xb
+       .uleb128 0x49
+       .uleb128 0x13
+       .uleb128 0x2
+       .uleb128 0x6
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x7
+       .uleb128 0x24
+       .byte   0x0
+       .uleb128 0xb
+       .uleb128 0xb
+       .uleb128 0x3e
+       .uleb128 0xb
+       .uleb128 0x3
+       .uleb128 0x8
+       .byte   0x0
+       .byte   0x0
+       .uleb128 0x8
+       .uleb128 0xf
+       .byte   0x0
+       .uleb128 0xb
+       .uleb128 0xb
+       .uleb128 0x49
+       .uleb128 0x13
+       .byte   0x0
+       .byte   0x0
+       .byte   0x0
+       .section        .debug_pubnames,"",@progbits
+       .long   0x20
+       .value  0x2
+       .long   .Ldebug_info0
+       .long   0xd8
+       .long   0x25
+       .string "func"
+       .long   0x83
+       .string "main"
+       .long   0x0
+       .section        .debug_aranges,"",@progbits
+       .long   0x1c
+       .value  0x2
+       .long   .Ldebug_info0
+       .byte   0x4
+       .byte   0x0
+       .value  0x0
+       .value  0x0
+       .long   .Ltext0
+       .long   .Letext0-.Ltext0
+       .long   0x0
+       .long   0x0
+       .section        .debug_str,"MS",@progbits,1
+.LASF7:
+       .string "unsigned int"
+.LASF3:
+       .string "func"
+.LASF0:
+       .string "uses_stack_op"
+.LASF5:
+       .string "argc"
+.LASF10:
+       .string "valop.c"
+.LASF2:
+       .string "result"
+.LASF8:
+       .string "char"
+.LASF9:
+       .string "GNU C 4.5.0 20090818 (experimental) [var-tracking-assignments-branch revision 150964]"
+.LASF4:
+       .string "main"
+.LASF11:
+       .string "/tmp"
+.LASF1:
+       .string "uses_lit_op"
+.LASF6:
+       .string "argv"
+       .ident  "GCC: (GNU) 4.5.0 20090818 (experimental) [var-tracking-assignments-branch revision 150964]"
+       .section        .note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.dwarf2/valop.exp b/gdb/testsuite/gdb.dwarf2/valop.exp
new file mode 100644 (file)
index 0000000..ee5ebda
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# 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, see <http://www.gnu.org/licenses/>.
+
+# Test DW_OP_stack_value and DW_OP_implicit_value.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+# This test can only be run on x86 targets.
+if {![istarget i?86-*]} {
+    return 0  
+}
+
+set testfile "valop"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
+       [list {additional_flags=-nostdlib}]] != "" } {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_test "break valop.c:19" "Breakpoint 2.*" "set breakpoint for valop"
+gdb_continue_to_breakpoint "continue to breakpoint for valop"
+
+gdb_test "print uses_stack_op" " = 24" "print uses_stack_op"
+gdb_test "print uses_lit_op" " = 2147483648" "print uses_lit_op"