]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 9 Oct 2011 19:43:41 +0000 (19:43 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 9 Oct 2011 19:43:41 +0000 (19:43 +0000)
Display @entry parameter values even for references.
* ada-valprint.c (ada_val_print_1) <TYPE_CODE_REF>: Try also
coerce_ref_if_computed.
* c-valprint.c (c_val_print) <TYPE_CODE_REF>: Likewise.
* dwarf2expr.c (dwarf_block_to_dwarf_reg_deref): New function.
(execute_stack_op) <DW_OP_GNU_entry_value>: Add -1 deref_size to the
existing push_dwarf_reg_entry_value call.  Add new detection calling
dwarf_block_to_dwarf_reg_deref.  Update the error message.
(ctx_no_push_dwarf_reg_entry_value): New parameter deref_size.
* dwarf2expr.h
(struct dwarf_expr_context_funcs) <push_dwarf_reg_entry_value>: Add new
parameter deref_size, describe it in the comment.
(ctx_no_push_dwarf_reg_entry_value): Add new parameter deref_size.
(dwarf_block_to_dwarf_reg_deref): New declaration.
* dwarf2loc.c (dwarf_entry_parameter_to_value): Add new parameter
deref_size, describe it in the function comment.  New variables
data_src and size, fetch the alternative block accoring to DEREF_SIZE.
(dwarf_expr_push_dwarf_reg_entry_value): Add new parameter deref_size,
describe it in the function comment.  Fetch the alternative block
accoring to DEREF_SIZE.
(entry_data_value_coerce_ref, entry_data_value_copy_closure)
(entry_data_value_free_closure, entry_data_value_funcs): New.
(value_of_dwarf_reg_entry): New variables checked_type, target_type,
outer_val, target_val, val and addr.  Try to fetch and create also
referenced value content.
(pieced_value_funcs): NULL value for coerce_ref.
(needs_dwarf_reg_entry_value): Add new parameter deref_size.
* f-valprint.c (f_val_print) <TYPE_CODE_REF>: Try also
coerce_ref_if_computed.
* opencl-lang.c (opencl_value_funcs): NULL value for coerce_ref.
* p-valprint.c (pascal_val_print) <TYPE_CODE_REF>: Likewise.
* stack.c (read_frame_arg): Compare also dereferenced values.
* value.c (value_computed_funcs): Make the parameter v const, use
value_lval_const for it.
(value_lval_const, coerce_ref_if_computed): New function.
(coerce_ref): New variable retval.  Call also coerce_ref_if_computed.
* value.h (struct lval_funcs): New field coerce_ref.
(value_computed_funcs): Make the parameter v const.
(value_lval_const, coerce_ref_if_computed): New declarations.

gdb/testsuite/
Display @entry parameter values even for references.
* gdb.arch/amd64-entry-value.cc (reference, datap, datap_input): New
functions.
(main): New variables regvar, nodatavarp, stackvar1, stackvar2.  Call
reference and datap_input.
* gdb.arch/amd64-entry-value.exp (reference, breakhere_reference): New
breakpoints.
(continue to breakpoint: entry_reference: reference)
(entry_reference: bt at entry)
(continue to breakpoint: entry_reference: breakhere_reference)
(entry_reference: bt, entry_reference: ptype regparam)
(entry_reference: p regparam, entry_reference: ptype regparam@entry)
(entry_reference: p regparam@entry, entry_reference: p &regparam@entry)
(entry_reference: p regcopy, entry_reference: p nodataparam)
(entry_reference: p nodataparam@entry): New tests.

15 files changed:
gdb/ChangeLog
gdb/ada-valprint.c
gdb/c-valprint.c
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/f-valprint.c
gdb/opencl-lang.c
gdb/p-valprint.c
gdb/stack.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/amd64-entry-value.cc
gdb/testsuite/gdb.arch/amd64-entry-value.exp
gdb/value.c
gdb/value.h

index 5d1339e3d807348083efbf032b17396870dfcdc9..e7cb9982a08693666b17d564d35028dea1f7156a 100644 (file)
@@ -1,3 +1,45 @@
+2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       Display @entry parameter values even for references.
+       * ada-valprint.c (ada_val_print_1) <TYPE_CODE_REF>: Try also
+       coerce_ref_if_computed.
+       * c-valprint.c (c_val_print) <TYPE_CODE_REF>: Likewise.
+       * dwarf2expr.c (dwarf_block_to_dwarf_reg_deref): New function.
+       (execute_stack_op) <DW_OP_GNU_entry_value>: Add -1 deref_size to the
+       existing push_dwarf_reg_entry_value call.  Add new detection calling
+       dwarf_block_to_dwarf_reg_deref.  Update the error message.
+       (ctx_no_push_dwarf_reg_entry_value): New parameter deref_size.
+       * dwarf2expr.h
+       (struct dwarf_expr_context_funcs) <push_dwarf_reg_entry_value>: Add new
+       parameter deref_size, describe it in the comment.
+       (ctx_no_push_dwarf_reg_entry_value): Add new parameter deref_size.
+       (dwarf_block_to_dwarf_reg_deref): New declaration.
+       * dwarf2loc.c (dwarf_entry_parameter_to_value): Add new parameter
+       deref_size, describe it in the function comment.  New variables
+       data_src and size, fetch the alternative block accoring to DEREF_SIZE.
+       (dwarf_expr_push_dwarf_reg_entry_value): Add new parameter deref_size,
+       describe it in the function comment.  Fetch the alternative block
+       accoring to DEREF_SIZE.
+       (entry_data_value_coerce_ref, entry_data_value_copy_closure)
+       (entry_data_value_free_closure, entry_data_value_funcs): New.
+       (value_of_dwarf_reg_entry): New variables checked_type, target_type,
+       outer_val, target_val, val and addr.  Try to fetch and create also
+       referenced value content.
+       (pieced_value_funcs): NULL value for coerce_ref.
+       (needs_dwarf_reg_entry_value): Add new parameter deref_size.
+       * f-valprint.c (f_val_print) <TYPE_CODE_REF>: Try also
+       coerce_ref_if_computed.
+       * opencl-lang.c (opencl_value_funcs): NULL value for coerce_ref.
+       * p-valprint.c (pascal_val_print) <TYPE_CODE_REF>: Likewise.
+       * stack.c (read_frame_arg): Compare also dereferenced values.
+       * value.c (value_computed_funcs): Make the parameter v const, use
+       value_lval_const for it.
+       (value_lval_const, coerce_ref_if_computed): New function.
+       (coerce_ref): New variable retval.  Call also coerce_ref_if_computed.
+       * value.h (struct lval_funcs): New field coerce_ref.
+       (value_computed_funcs): Make the parameter v const.
+       (value_lval_const, coerce_ref_if_computed): New declarations.
+
 2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        Support @entry in input expressions.
index 7b9e3ee870768231b5994e19216a5c0ad3bc8ef8..8a72b9e35c4b85f4f214b3f0afbf5876f1be4959 100644 (file)
@@ -898,9 +898,18 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr,
       
       if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
         {
-          CORE_ADDR deref_val_int
-           = unpack_pointer (type, valaddr + offset_aligned);
+          CORE_ADDR deref_val_int;
+         struct value *deref_val;
 
+         deref_val = coerce_ref_if_computed (original_value);
+         if (deref_val)
+           {
+             common_val_print (deref_val, stream, recurse + 1, options,
+                               current_language);
+             break;
+           }
+
+          deref_val_int = unpack_pointer (type, valaddr + offset_aligned);
           if (deref_val_int != 0)
             {
               struct value *deref_val =
index 76579d2116c1a016fdb14f516ed2d57503c53629..3461b08b921b4a90705e3eb588c9ef3df3e7d6fa 100644 (file)
@@ -380,10 +380,19 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
        {
          if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
            {
-             struct value *deref_val =
-               value_at
-               (TYPE_TARGET_TYPE (type),
-                unpack_pointer (type, valaddr + embedded_offset));
+             struct value *deref_val;
+
+             deref_val = coerce_ref_if_computed (original_value);
+             if (deref_val != NULL)
+               {
+                 /* More complicated computed references are not supported.  */
+                 gdb_assert (embedded_offset == 0);
+               }
+             else
+               deref_val = value_at (TYPE_TARGET_TYPE (type),
+                                     unpack_pointer (type,
+                                                     (valaddr
+                                                      + embedded_offset)));
 
              common_val_print (deref_val, stream, recurse, options,
                                current_language);
index 4fccc262ecdeba1a5a0453e1f3556341227bd44f..71aff6ad33dde79607051a3e57977ea894d30018 100644 (file)
@@ -518,6 +518,63 @@ dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end)
   return dwarf_reg;
 }
 
+/* If <BUF..BUF_END] contains DW_FORM_block* with just DW_OP_breg*(0) and
+   DW_OP_deref* return the DWARF register number.  Otherwise return -1.
+   DEREF_SIZE_RETURN contains -1 for DW_OP_deref; otherwise it contains the
+   size from DW_OP_deref_size.  */
+
+int
+dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, const gdb_byte *buf_end,
+                               CORE_ADDR *deref_size_return)
+{
+  ULONGEST dwarf_reg;
+  LONGEST offset;
+
+  if (buf_end <= buf)
+    return -1;
+  if (*buf >= DW_OP_breg0 && *buf <= DW_OP_breg31)
+    {
+      dwarf_reg = *buf - DW_OP_breg0;
+      buf++;
+    }
+  else if (*buf == DW_OP_bregx)
+    {
+      buf++;
+      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+      if ((int) dwarf_reg != dwarf_reg)
+       return -1;
+    }
+  else
+    return -1;
+
+  buf = read_sleb128 (buf, buf_end, &offset);
+  if (offset != 0)
+    return -1;
+
+  if (buf >= buf_end)
+    return -1;
+
+  if (*buf == DW_OP_deref)
+    {
+      buf++;
+      *deref_size_return = -1;
+    }
+  else if (*buf == DW_OP_deref_size)
+    {
+      buf++;
+      if (buf >= buf_end)
+       return -1;
+      *deref_size_return = *buf++;
+    }
+  else
+    return -1;
+
+  if (buf != buf_end)
+    return -1;
+
+  return dwarf_reg;
+}
+
 /* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_fbreg(X) fill
    in FB_OFFSET_RETURN with the X offset and return 1.  Otherwise return 0.  */
 
@@ -1304,12 +1361,27 @@ execute_stack_op (struct dwarf_expr_context *ctx,
              {
                op_ptr += len;
                ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg,
-                                                       0 /* unused */);
+                                                       0 /* unused */,
+                                                       -1 /* deref_size */);
+               goto no_push;
+             }
+
+           dwarf_reg = dwarf_block_to_dwarf_reg_deref (op_ptr, op_ptr + len,
+                                                       &deref_size);
+           if (dwarf_reg != -1)
+             {
+               if (deref_size == -1)
+                 deref_size = ctx->addr_size;
+               op_ptr += len;
+               ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg,
+                                                       0 /* unused */,
+                                                       deref_size);
                goto no_push;
              }
 
            error (_("DWARF-2 expression error: DW_OP_GNU_entry_value is "
-                    "supported only for single DW_OP_reg*"));
+                    "supported only for single DW_OP_reg* "
+                    "or for DW_OP_breg*(0)+DW_OP_deref*"));
          }
 
        case DW_OP_GNU_const_type:
@@ -1460,7 +1532,8 @@ ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die)
 
 void
 ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-                                  int dwarf_reg, CORE_ADDR fb_offset)
+                                  int dwarf_reg, CORE_ADDR fb_offset,
+                                  int deref_size)
 {
   internal_error (__FILE__, __LINE__,
                  _("Support for DW_OP_GNU_entry_value is unimplemented"));
index c014ce20abd0b5e4ecc880f20d731628c11e6785..a319ca328122a2df505e304cf591c9921916e434 100644 (file)
@@ -67,9 +67,11 @@ struct dwarf_expr_context_funcs
      number DWARF_REG specifying the push_dwarf_reg_entry_value parameter is
      not -1 FB_OFFSET is ignored.  Otherwise FB_OFFSET specifies stack
      parameter offset against caller's stack pointer (which equals the callee's
-     frame base).  */
+     frame base).  If DEREF_SIZE is not -1 then use
+     DW_AT_GNU_call_site_data_value instead of DW_AT_GNU_call_site_value.  */
   void (*push_dwarf_reg_entry_value) (struct dwarf_expr_context *ctx,
-                                     int dwarf_reg, CORE_ADDR fb_offset);
+                                     int dwarf_reg, CORE_ADDR fb_offset,
+                                     int deref_size);
 
 #if 0
   /* Not yet implemented.  */
@@ -277,10 +279,15 @@ CORE_ADDR ctx_no_get_tls_address (void *baton, CORE_ADDR offset);
 void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset);
 struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die);
 void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-                                       int dwarf_reg, CORE_ADDR fb_offset);
+                                       int dwarf_reg, CORE_ADDR fb_offset,
+                                       int deref_size);
 
 int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
 
+int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf,
+                                   const gdb_byte *buf_end,
+                                   CORE_ADDR *deref_size_return);
+
 int dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
                              CORE_ADDR *fb_offset_return);
 
index a44d3d2788449cdb16904d61dd47cf47b5ec561f..0e1179c00f230ff37d818d2f68589dde8090533f 100644 (file)
@@ -910,7 +910,9 @@ dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
   return parameter;
 }
 
-/* Return value for PARAMETER for DW_AT_GNU_call_site_value.
+/* Return value for PARAMETER matching DEREF_SIZE.  If DEREF_SIZE is -1, return
+   the normal DW_AT_GNU_call_site_value block.  Otherwise return the
+   DW_AT_GNU_call_site_data_value (dereferenced) block.
 
    TYPE and CALLER_FRAME specify how to evaluate the DWARF block into returned
    struct value.
@@ -920,33 +922,44 @@ dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
 
 static struct value *
 dwarf_entry_parameter_to_value (struct call_site_parameter *parameter,
-                               struct type *type,
+                               CORE_ADDR deref_size, struct type *type,
                                struct frame_info *caller_frame,
                                struct dwarf2_per_cu_data *per_cu)
 {
+  const gdb_byte *data_src;
   gdb_byte *data;
+  size_t size;
+
+  data_src = deref_size == -1 ? parameter->value : parameter->data_value;
+  size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
+
+  /* DEREF_SIZE size is not verified here.  */
+  if (data_src == NULL)
+    throw_error (NO_ENTRY_VALUE_ERROR,
+                _("Cannot resolve DW_AT_GNU_call_site_data_value"));
 
   /* DW_AT_GNU_call_site_value is a DWARF expression, not a DWARF
      location.  Postprocessing of DWARF_VALUE_MEMORY would lose the type from
      DWARF block.  */
-  data = alloca (parameter->value_size + 1);
-  memcpy (data, parameter->value, parameter->value_size);
-  data[parameter->value_size] = DW_OP_stack_value;
+  data = alloca (size + 1);
+  memcpy (data, data_src, size);
+  data[size] = DW_OP_stack_value;
 
-  return dwarf2_evaluate_loc_desc (type, caller_frame, data,
-                                  parameter->value_size + 1, per_cu);
+  return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
 }
 
-/* Execute call_site_parameter's DWARF block for caller of the CTX's frame.
-   CTX must be of dwarf_expr_ctx_funcs kind.  See DWARF_REG and FB_OFFSET
-   description at struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
+/* Execute call_site_parameter's DWARF block matching DEREF_SIZE for caller of
+   the CTX's frame.  CTX must be of dwarf_expr_ctx_funcs kind.  See DWARF_REG
+   and FB_OFFSET description at struct
+   dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
 
    The CTX caller can be from a different CU - per_cu_dwarf_call implementation
    can be more simple as it does not support cross-CU DWARF executions.  */
 
 static void
 dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-                                      int dwarf_reg, CORE_ADDR fb_offset)
+                                      int dwarf_reg, CORE_ADDR fb_offset,
+                                      int deref_size)
 {
   struct dwarf_expr_baton *debaton;
   struct frame_info *frame, *caller_frame;
@@ -964,8 +977,13 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
 
   parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
                                                 &caller_per_cu);
-  data_src = parameter->value;
-  size = parameter->value_size;
+  data_src = deref_size == -1 ? parameter->value : parameter->data_value;
+  size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
+
+  /* DEREF_SIZE size is not verified here.  */
+  if (data_src == NULL)
+    throw_error (NO_ENTRY_VALUE_ERROR,
+                _("Cannot resolve DW_AT_GNU_call_site_data_value"));
 
   baton_local.frame = caller_frame;
   baton_local.per_cu = caller_per_cu;
@@ -987,6 +1005,62 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
   ctx->baton = saved_ctx.baton;
 }
 
+/* VALUE must be of type lval_computed with entry_data_value_funcs.  Perform
+   the indirect method on it, that is use its stored target value, the sole
+   purpose of entry_data_value_funcs..  */
+
+static struct value *
+entry_data_value_coerce_ref (const struct value *value)
+{
+  struct type *checked_type = check_typedef (value_type (value));
+  struct value *target_val;
+
+  if (TYPE_CODE (checked_type) != TYPE_CODE_REF)
+    return NULL;
+
+  target_val = value_computed_closure (value);
+  value_incref (target_val);
+  return target_val;
+}
+
+/* Implement copy_closure.  */
+
+static void *
+entry_data_value_copy_closure (const struct value *v)
+{
+  struct value *target_val = value_computed_closure (v);
+
+  value_incref (target_val);
+  return target_val;
+}
+
+/* Implement free_closure.  */
+
+static void
+entry_data_value_free_closure (struct value *v)
+{
+  struct value *target_val = value_computed_closure (v);
+
+  value_free (target_val);
+}
+
+/* Vector for methods for an entry value reference where the referenced value
+   is stored in the caller.  On the first dereference use
+   DW_AT_GNU_call_site_data_value in the caller.  */
+
+static const struct lval_funcs entry_data_value_funcs =
+{
+  NULL,        /* read */
+  NULL,        /* write */
+  NULL,        /* check_validity */
+  NULL,        /* check_any_valid */
+  NULL,        /* indirect */
+  entry_data_value_coerce_ref,
+  NULL,        /* check_synthetic_pointer */
+  entry_data_value_copy_closure,
+  entry_data_value_free_closure
+};
+
 /* Read parameter of TYPE at (callee) FRAME's function entry.  DWARF_REG and
    FB_OFFSET are used to match DW_AT_location at the caller's
    DW_TAG_GNU_call_site_parameter.  See DWARF_REG and FB_OFFSET description at
@@ -999,15 +1073,53 @@ static struct value *
 value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
                          int dwarf_reg, CORE_ADDR fb_offset)
 {
+  struct type *checked_type = check_typedef (type);
+  struct type *target_type = TYPE_TARGET_TYPE (checked_type);
   struct frame_info *caller_frame = get_prev_frame (frame);
+  struct value *outer_val, *target_val, *val;
   struct call_site_parameter *parameter;
   struct dwarf2_per_cu_data *caller_per_cu;
+  CORE_ADDR addr;
 
   parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
                                                 &caller_per_cu);
 
-  return dwarf_entry_parameter_to_value (parameter, type, caller_frame,
-                                        caller_per_cu);
+  outer_val = dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */,
+                                             type, caller_frame,
+                                             caller_per_cu);
+
+  /* Check if DW_AT_GNU_call_site_data_value cannot be used.  If it should be
+     used and it is not available do not fall back to OUTER_VAL - dereferencing
+     TYPE_CODE_REF with non-entry data value would give current value - not the
+     entry value.  */
+
+  if (TYPE_CODE (checked_type) != TYPE_CODE_REF
+      || TYPE_TARGET_TYPE (checked_type) == NULL)
+    return outer_val;
+
+  target_val = dwarf_entry_parameter_to_value (parameter,
+                                              TYPE_LENGTH (target_type),
+                                              target_type, caller_frame,
+                                              caller_per_cu);
+
+  /* value_as_address dereferences TYPE_CODE_REF.  */
+  addr = extract_typed_address (value_contents (outer_val), checked_type);
+
+  /* The target entry value has artificial address of the entry value
+     reference.  */
+  VALUE_LVAL (target_val) = lval_memory;
+  set_value_address (target_val, addr);
+
+  release_value (target_val);
+  val = allocate_computed_value (type, &entry_data_value_funcs,
+                                target_val /* closure */);
+
+  /* Copy the referencing pointer to the new computed value.  */
+  memcpy (value_contents_raw (val), value_contents_raw (outer_val),
+         TYPE_LENGTH (checked_type));
+  set_value_lazy (val, 0);
+
+  return val;
 }
 
 /* Read parameter of TYPE at (callee) FRAME's function entry.  DATA and
@@ -1799,6 +1911,7 @@ static const struct lval_funcs pieced_value_funcs = {
   check_pieced_value_validity,
   check_pieced_value_invalid,
   indirect_pieced_value,
+  NULL,        /* coerce_ref */
   check_pieced_synthetic_pointer,
   copy_pieced_value_closure,
   free_pieced_value_closure
@@ -2118,7 +2231,7 @@ needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
 
 static void
 needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-                            int dwarf_reg, CORE_ADDR fb_offset)
+                            int dwarf_reg, CORE_ADDR fb_offset, int deref_size)
 {
   struct needs_frame_baton *nf_baton = ctx->baton;
 
index 66b425d78c956b851b1ae9de106a5ce2d862169b..b800d89d4ba275fd622a7f3370928643c58e9d3f 100644 (file)
@@ -346,10 +346,19 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
        {
          if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
            {
-             struct value *deref_val =
-               value_at
-               (TYPE_TARGET_TYPE (type),
-                unpack_pointer (type, valaddr + embedded_offset));
+             struct value *deref_val;
+
+             deref_val = coerce_ref_if_computed (original_value);
+             if (deref_val != NULL)
+               {
+                 /* More complicated computed references are not supported.  */
+                 gdb_assert (embedded_offset == 0);
+               }
+             else
+               deref_val = value_at (TYPE_TARGET_TYPE (type),
+                                     unpack_pointer (type,
+                                                     (valaddr
+                                                      + embedded_offset)));
 
              common_val_print (deref_val, stream, recurse,
                                options, current_language);
index 79ad5f6590a46cc99ae9cc592307bc8dbc0313ae..05955b413604790110cb8eca758f95bc36fda316 100644 (file)
@@ -360,7 +360,8 @@ static const struct lval_funcs opencl_value_funcs =
     lval_func_write,
     lval_func_check_validity,
     lval_func_check_any_valid,
-    NULL,
+    NULL,      /* indirect */
+    NULL,      /* coerce_ref */
     lval_func_check_synthetic_pointer,
     lval_func_copy_closure,
     lval_func_free_closure
index d2efa5b3d20fd1c5d0c1e383b62cb2ae7aef77a6..e55b12269a9725b6180c2aef192fa5884f80f67f 100644 (file)
@@ -272,10 +272,19 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
        {
          if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
            {
-             struct value *deref_val =
-               value_at
-               (TYPE_TARGET_TYPE (type),
-                unpack_pointer (type, valaddr + embedded_offset));
+             struct value *deref_val;
+
+             deref_val = coerce_ref_if_computed (original_value);
+             if (deref_val != NULL)
+               {
+                 /* More complicated computed references are not supported.  */
+                 gdb_assert (embedded_offset == 0);
+               }
+             else
+               deref_val = value_at (TYPE_TARGET_TYPE (type),
+                                     unpack_pointer (type,
+                                                     (valaddr
+                                                      + embedded_offset)));
 
              common_val_print (deref_val, stream, recurse + 1, options,
                                current_language);
index 397b345dd25803f5e25f1c13fe07e84ece8f632d..b01dc1c9fa603a2c148681e16337d2451305c2b4 100644 (file)
@@ -350,8 +350,50 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
              if (!value_optimized_out (val)
                  && value_available_contents_eq (val, 0, entryval, 0, len))
                {
-                 entryval = NULL;
-                 val_equal = 1;
+                 struct value *val_deref, *entryval_deref;
+
+                 /* DW_AT_GNU_call_site_value does match with the current
+                    value.  If it is a reference still try to verify if
+                    dereferenced DW_AT_GNU_call_site_data_value does not
+                    differ.  */
+
+                 TRY_CATCH (except, RETURN_MASK_ERROR)
+                   {
+                     unsigned len_deref;
+
+                     val_deref = coerce_ref (val);
+                     if (value_lazy (val_deref))
+                       value_fetch_lazy (val_deref);
+                     len_deref = TYPE_LENGTH (value_type (val_deref));
+
+                     entryval_deref = coerce_ref (entryval);
+                     if (value_lazy (entryval_deref))
+                       value_fetch_lazy (entryval_deref);
+
+                     /* If the reference addresses match but dereferenced
+                        content does not match print them.  */
+                     if (val != val_deref
+                         && value_available_contents_eq (val_deref, 0,
+                                                         entryval_deref, 0,
+                                                         len_deref))
+                       val_equal = 1;
+                   }
+
+                 /* Value was not a reference; and its content matches.  */
+                 if (val == val_deref)
+                   val_equal = 1;
+                 /* If the dereferenced content could not be fetched do not
+                    display anything.  */
+                 else if (except.error == NO_ENTRY_VALUE_ERROR)
+                   val_equal = 1;
+                 else if (except.message)
+                   {
+                     entryval_error = alloca (strlen (except.message) + 1);
+                     strcpy (entryval_error, except.message);
+                   }
+
+                 if (val_equal)
+                   entryval = NULL;
                }
            }
 
index e3df529a845e3bef28ea906cb1e696aa3f505ec3..1a7b5da892b4043a28a5fa1a8c8e1728d9ab8fcb 100644 (file)
@@ -1,3 +1,21 @@
+2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       Display @entry parameter values even for references.
+       * gdb.arch/amd64-entry-value.cc (reference, datap, datap_input): New
+       functions.
+       (main): New variables regvar, nodatavarp, stackvar1, stackvar2.  Call
+       reference and datap_input.
+       * gdb.arch/amd64-entry-value.exp (reference, breakhere_reference): New
+       breakpoints.
+       (continue to breakpoint: entry_reference: reference)
+       (entry_reference: bt at entry)
+       (continue to breakpoint: entry_reference: breakhere_reference)
+       (entry_reference: bt, entry_reference: ptype regparam)
+       (entry_reference: p regparam, entry_reference: ptype regparam@entry)
+       (entry_reference: p regparam@entry, entry_reference: p &regparam@entry)
+       (entry_reference: p regcopy, entry_reference: p nodataparam)
+       (entry_reference: p nodataparam@entry): New tests.
+
 2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        Support @entry in input expressions.
index 7b7d050e00f5ba13aa475acf7c59845cf24aafe5..2202e28b25435acd400a08ca7030901d7b95bf07 100644 (file)
@@ -135,6 +135,40 @@ asm ("breakhere_stacktest:");
   e (v, v);
 }
 
+/* nodataparam has DW_AT_GNU_call_site_value but it does not have
+   DW_AT_GNU_call_site_data_value.  GDB should not display dereferenced @entry
+   value for it.  */
+
+static void __attribute__((noinline, noclone))
+reference (int &regparam, int &nodataparam, int r3, int r4, int r5, int r6,
+          int &stackparam1, int &stackparam2)
+{
+  int regcopy = regparam, nodatacopy = nodataparam;
+  int stackcopy1 = stackparam1, stackcopy2 = stackparam2;
+
+  regparam = 21;
+  nodataparam = 22;
+  stackparam1 = 31;
+  stackparam2 = 32;
+  e (v, v);
+asm ("breakhere_reference:");
+  e (v, v);
+}
+
+static int *__attribute__((noinline, noclone))
+datap ()
+{
+  static int two = 2;
+
+  return &two;
+}
+
+static void __attribute__((noinline, noclone))
+datap_input (int *datap)
+{
+  (*datap)++;
+}
+
 static int __attribute__((noinline, noclone))
 data (void)
 {
@@ -183,6 +217,12 @@ main ()
   validity (5, data ());
   invalid (data2 ());
 
+  {
+    int regvar = 1, *nodatavarp = datap (), stackvar1 = 11, stackvar2 = 12;
+    reference (regvar, *nodatavarp, 3, 4, 5, 6, stackvar1, stackvar2);
+    datap_input (nodatavarp);
+  }
+
   if (v)
     a (1, 1.25);
   else
index 10a82ab682081162adc3835d5e050aca01122f74..185249c4489380934409c9a6d280cdafce13c956 100644 (file)
@@ -42,6 +42,8 @@ gdb_breakpoint "different"
 gdb_breakpoint "breakhere_different"
 gdb_breakpoint "breakhere_validity"
 gdb_breakpoint "breakhere_invalid"
+gdb_breakpoint "reference"
+gdb_breakpoint "breakhere_reference"
 
 
 # Test @entry values for register passed parameters.
@@ -158,6 +160,38 @@ gdb_test_no_output "set print entry-values default" "entry_invalid: set print en
 gdb_test "frame" {\(inv=<optimized out>\).*} "entry_invalid: frame: default"
 
 
+# Test @entry values for DW_AT_GNU_call_site_data_value parameters.
+
+gdb_continue_to_breakpoint "entry_reference: reference"
+
+# GCC PR debug/49980: Missing stackparam1@entry and stackparam2@entry.
+gdb_test "bt" "#0 +reference \\(regparam=regparam@entry=@0x\[0-9a-f\]+: 1, nodataparam=@0x\[0-9a-f\]+: 2, \[^\r\n\]+, stackparam1=@0x\[0-9a-f\]+: 11, stackparam2=@0x\[0-9a-f\]+: 12\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*" \
+        "entry_reference: bt at entry"
+
+gdb_continue_to_breakpoint "entry_reference: breakhere_reference"
+
+# GCC PR debug/49980: Missing stackparam1@entry and stackparam2@entry.
+gdb_test "bt" "#0 +reference \\(regparam=@0x\[0-9a-f\]+: 21, regparam@entry=@0x\[0-9a-f\]+: 1, nodataparam=@0x\[0-9a-f\]+: 22, \[^\r\n\]+, stackparam1=@0x\[0-9a-f\]+: 31, stackparam2=@0x\[0-9a-f\]+: 32\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*" \
+        "entry_reference: bt"
+gdb_test "ptype regparam" " = int &" "entry_reference: ptype regparam"
+
+set test "entry_reference: p regparam"
+set addr ""
+gdb_test_multiple "p regparam" $test {
+    -re " = \\(int &\\) @(0x\[0-9a-f\]+): 21\r\n$gdb_prompt $" {
+       set addr $expect_out(1,string)
+       pass $test
+    }
+}
+
+gdb_test "ptype regparam@entry" " = int &" "entry_reference: ptype regparam@entry"
+gdb_test "p regparam@entry" " = \\(int &\\) @$addr: 1" "entry_reference: p regparam@entry"
+gdb_test "p &regparam@entry" " = \\(int \\*\\) $addr" "entry_reference: p &regparam@entry"
+gdb_test "p regcopy" " = 1" "entry_reference: p regcopy"
+gdb_test "p nodataparam" " = \\(int &\\) @0x\[0-9a-f\]+: 22" "entry_reference: p nodataparam"
+gdb_test "p nodataparam@entry" "Cannot resolve DW_AT_GNU_call_site_data_value" "entry_reference: p nodataparam@entry"
+
+
 # Test virtual tail call frames.
 
 gdb_continue_to_breakpoint "tailcall: breakhere"
index 087cdfd5c25ce81b7efed97918470a0f30d0d2e8..e72670b6a29f40cb6e3682863d489bd8e89b18ba 100644 (file)
@@ -1063,9 +1063,9 @@ set_value_pointed_to_offset (struct value *value, int val)
 }
 
 const struct lval_funcs *
-value_computed_funcs (struct value *v)
+value_computed_funcs (const struct value *v)
 {
-  gdb_assert (VALUE_LVAL (v) == lval_computed);
+  gdb_assert (value_lval_const (v) == lval_computed);
 
   return v->location.computed.funcs;
 }
@@ -1084,6 +1084,12 @@ deprecated_value_lval_hack (struct value *value)
   return &value->lval;
 }
 
+enum lval_type
+value_lval_const (const struct value *value)
+{
+  return value->lval;
+}
+
 CORE_ADDR
 value_address (const struct value *value)
 {
@@ -3082,16 +3088,40 @@ value_from_history_ref (char *h, char **endp)
   return access_value_history (index);
 }
 
+struct value *
+coerce_ref_if_computed (const struct value *arg)
+{
+  const struct lval_funcs *funcs;
+
+  if (TYPE_CODE (check_typedef (value_type (arg))) != TYPE_CODE_REF)
+    return NULL;
+
+  if (value_lval_const (arg) != lval_computed)
+    return NULL;
+
+  funcs = value_computed_funcs (arg);
+  if (funcs->coerce_ref == NULL)
+    return NULL;
+
+  return funcs->coerce_ref (arg);
+}
+
 struct value *
 coerce_ref (struct value *arg)
 {
   struct type *value_type_arg_tmp = check_typedef (value_type (arg));
+  struct value *retval;
 
-  if (TYPE_CODE (value_type_arg_tmp) == TYPE_CODE_REF)
-    arg = value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp),
-                        unpack_pointer (value_type (arg),              
-                                        value_contents (arg)));
-  return arg;
+  retval = coerce_ref_if_computed (arg);
+  if (retval)
+    return retval;
+
+  if (TYPE_CODE (value_type_arg_tmp) != TYPE_CODE_REF)
+    return arg;
+
+  return value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp),
+                       unpack_pointer (value_type (arg),
+                                       value_contents (arg)));
 }
 
 struct value *
index 83c94fcab771b3590ebe667ad11ee9e7b604582f..dc2ac13ab1db0a48399b07c323aacd8e93ddb191 100644 (file)
@@ -180,6 +180,11 @@ struct lval_funcs
      will fall back to ordinary indirection.  */
   struct value *(*indirect) (struct value *value);
 
+  /* If non-NULL, this is used to implement reference resolving for
+     this value.  This method may return NULL, in which case coerce_ref
+     will fall back to ordinary references resolving.  */
+  struct value *(*coerce_ref) (const struct value *value);
+
   /* If non-NULL, this is used to determine whether the indicated bits
      of VALUE are a synthetic pointer.  */
   int (*check_synthetic_pointer) (const struct value *value,
@@ -213,7 +218,7 @@ extern struct value *allocate_optimized_out_value (struct type *type);
 
 /* If VALUE is lval_computed, return its lval_funcs structure.  */
 
-extern const struct lval_funcs *value_computed_funcs (struct value *value);
+extern const struct lval_funcs *value_computed_funcs (const struct value *);
 
 /* If VALUE is lval_computed, return its closure.  The meaning of the
    returned value depends on the functions VALUE uses.  */
@@ -314,6 +319,9 @@ extern void set_value_component_location (struct value *component,
 extern enum lval_type *deprecated_value_lval_hack (struct value *);
 #define VALUE_LVAL(val) (*deprecated_value_lval_hack (val))
 
+/* Like VALUE_LVAL, except the parameter can be const.  */
+extern enum lval_type value_lval_const (const struct value *value);
+
 /* If lval == lval_memory, return the address in the inferior.  If
    lval == lval_register, return the byte offset into the registers
    structure.  Otherwise, return 0.  The returned address
@@ -340,6 +348,11 @@ extern struct frame_id *deprecated_value_frame_id_hack (struct value *);
 extern short *deprecated_value_regnum_hack (struct value *);
 #define VALUE_REGNUM(val) (*deprecated_value_regnum_hack (val))
 
+/* Return value after lval_funcs->coerce_ref (after check_typedef).  Return
+   NULL if lval_funcs->coerce_ref is not applicable for whatever reason.  */
+
+extern struct value *coerce_ref_if_computed (const struct value *arg);
+
 /* Convert a REF to the object referenced.  */
 
 extern struct value *coerce_ref (struct value *value);