public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Rohr, Stephan" <stephan.rohr@intel.com>
To: Simon Marchi <simark@simark.ca>,
	"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Cc: "tom@tromey.com" <tom@tromey.com>
Subject: RE: [PATCH 1/1] gdb/dwarf2: Fix 'rw_pieced_value' for values casted to different type.
Date: Tue, 11 Oct 2022 08:03:45 +0000	[thread overview]
Message-ID: <DM6PR11MB4564275FFC6CE96E79C5E62D93239@DM6PR11MB4564.namprd11.prod.outlook.com> (raw)
In-Reply-To: <0895de32-0b1b-4053-7a90-21d12fe81b6a@simark.ca>

Hi Simon,

thanks for the feedback and sorry for the late reply.  Please see my answers below.

> -----Original Message-----
> From: Simon Marchi <simark@simark.ca>
> Sent: Friday, August 19, 2022 6:40 PM
> To: Rohr, Stephan <stephan.rohr@intel.com>; gdb-patches@sourceware.org
> Cc: tom@tromey.com
> Subject: Re: [PATCH 1/1] gdb/dwarf2: Fix 'rw_pieced_value' for values casted
> to different type.
> 
> On 4/22/22 10:44, Stephan Rohr via Gdb-patches wrote:
> > From: "Rohr, Stephan" <stephan.rohr@intel.com>
> >
> > The 'rw_pieced_value' function is executed when fetching a (lazy)
> > variable described by 'DW_OP_piece' or 'DW_OP_bit_piece'.  The
> > function checks the 'type' and 'enclosing_type' fields of the value
> > for identity.
> >
> >   * The 'type' field describes the type of a value.
> >   * In most cases, the 'enclosing_type' field is identical to the
> >     'type' field.
> >   * Scenarios where the 'type' and 'enclosing_type' of an object
> >     differ are described in 'gdb/value.c'.  Possible cases are:
> >     * If a value represents a C++ object, then the 'type' field
> >       gives the object's compile-time type.  If the object actually
> >       belongs to some class derived from `type', perhaps with other
> >       base classes and additional members, then `type' is just a
> >       subobject of the real thing, and the full object is probably
> >       larger than `type' would suggest.
> >     * If 'type' is a dynamic class (i.e. one with a vtable), then GDB
> >       can actually determine the object's run-time type by looking at
> >       the run-time type information in the vtable.  GDB may then elect
> >       to read the entire object.
> >     * If the user casts a variable to a different type
> >       (e.g. 'print (<type> []) <variable>'), the value's type is
> >       updated before reading the value.
> 
> Out of curiosity, where do you see these scenarios described?  I could not
> find where value.c talks about the case where the user casts the variable.
> 
This scenario is not described in value.c.  The issue came up in our test suite
where the assertion caused GDB to crash when casting a pieced value, e.g.,

(gdb) info address a
Symbol "a" is multi-location:
  Range 0xfffd5990-0xfffd5e50: a variable in $r68 [256-bit piece, offset 0 bits],
and a variable in $r69 [256-bit piece, offset 0 bits], ...
(gdb) pt a
type = double [16][4]
(gdb) p (double[])a
.../gdb/dwarf2/loc.c:1771: internal-error: Should not be able to create a lazy value with an enclosing type
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n)

> >
> > If a lazy value is fetched, GDB allocates space based on the enclosing
> > type's length and typically reads the 'full' object.
> > This is not implemented for pieced values and causes an internal error
> > if 'type' and 'enclosing_type' of a value are not identical.
> >
> > However, GDB can read the value based on its type.  Thus, it should be
> > sufficient to check if the type's length (potentially shifted by
> > 'embedded_offset') does not exceed the enclosing type's length which
> > was used for memory allocation.
> 
> I'm trying to understand a bit better what happens here.  The current
> assertion states that it's incorrect to have a lazy value where the type does
> not match the enclosing_type (I don't really know why), but it clearly
> happens here.  So I'd like to determine who's right, the assertion or the code
> that produces such a value.  For reference, the assertion was added here:
> 
>   https://pi.simark.ca/gdb-patches/m3hbmbviko.fsf@fleche.redhat.com/#t
> 

I contacted Tom when I first encountered this issue.  Based on his feedback,
it seems fine to remove the assertion if the results work correctly.  With your
feedback and the test cases I added, I would agree that we can remove the
original assertion, though I also don't know why it was originally added.

> I was wondering at which point exactly we end up with such a value.
> It's here that we assign a new type (the array type) to the value, while the
> value is lazy, when handling the value cast:
> 
>     #0  deprecated_set_value_type (value=0x61100020a700,
> type=0x621000506890) at /home/smarchi/src/binutils-gdb/gdb/value.c:1105
>     #1  0x0000564249d99092 in value_cast (type=0x621000506730,
> arg2=0x61100020a700) at /home/smarchi/src/binutils-gdb/gdb/valops.c:496
>     #2  0x000056424838294c in expr::var_value_operation::evaluate_for_cast
> (this=0x6030002a6220, to_type=0x621000506730, exp=0x60300011cbc0,
> noside=EVAL_NORMAL) at /home/smarchi/src/binutils-gdb/gdb/eval.c:2885
>     #3  0x0000564247412e1e in expr::unop_cast_type_operation::evaluate
> (this=0x6030002a6250, expect_type=0x0, exp=0x60300011cbc0,
> noside=EVAL_NORMAL) at /home/smarchi/src/binutils-
> gdb/gdb/expop.h:2036
>     #4  0x000056424836092c in expression::evaluate (this=0x60300011cbc0,
> expect_type=0x0, noside=EVAL_NORMAL) at /home/smarchi/src/binutils-
> gdb/gdb/eval.c:101
>     #5  0x0000564248360a9d in evaluate_expression (exp=0x60300011cbc0,
> expect_type=0x0) at /home/smarchi/src/binutils-gdb/gdb/eval.c:115
>     #6  0x0000564248e56c95 in process_print_command_args
> (args=0x60200006fb52 "(int []) s1", print_opts=0x7ffe0fb62200,
> voidprint=true) at /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1307
>     #7  0x0000564248e56e79 in print_command_1 (args=0x60200006fb52 "(int
> []) s1", voidprint=1) at /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1320
>     #8  0x0000564248e57d15 in print_command (exp=0x60200006fb52 "(int [])
> s1", from_tty=1) at /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1453
> 
> Meanwhile, the enclosing_type remains the original struct type.
> 
> So my question is: when doing the value cast, do we also want to overwrite
> the value's enclosing type, in addition to the value's type?
> Is it useful to retain the original enclosing type?  In other words, we could do
> this change to also set the enclosing type when casting:
> 
> 
> diff --git a/gdb/valops.c b/gdb/valops.c index 27e84d9f6b3..cb3fb49e50d
> 100644
> --- a/gdb/valops.c
> +++ b/gdb/valops.c
> @@ -493,10 +493,10 @@ value_cast (struct type *type, struct value *arg2)
>                                                  TYPE_TARGET_TYPE (range_type),
>                                                  low_bound,
>                                                  new_length + low_bound - 1);
> -         deprecated_set_value_type (arg2,
> -                                    create_array_type (NULL,
> -                                                       element_type,
> -                                                       range_type));
> +         struct type *new_type
> +           = create_array_type (NULL, element_type, range_type);
> +         deprecated_set_value_type (arg2, new_type);
> +         set_value_enclosing_type (arg2, new_type);
>           return arg2;
>         }
>      }
> 
> I don't know if that change causes other things to fail, and I really don't know
> what the answer is.

This would surely fix the original issue I encountered.  However, I also see the risk
of unexpected side effects.

> One case I wonder about is when the size of the original object is not a
> multiple of the array's element size.  For instance, imagine s1 is 9 bytes long
> and you do:
> 
>   (gdb) print (int []) s1
> 
> where an int is 4 bytes.  The pieces of s1 will still describe 9 bytes, but the
> type and enclosing type will be 8 bytes long.  That might be a problem down
> the road, and a reason we want to keep the original enclosing type whose
> length matches the described content length.  Some additional tests for that
> would be nice.
> 

I extended the shortpiece.exp testcase by adding another variable s3 that is 10
bytes long.  GDB emits a warning and prints the maximum number of integers:

p (int []) s3
warning: array element type size does not divide object size in cast
$5 = {0, 1}

This is expected and correct behavior from my point of view.

> > ---
> >  gdb/dwarf2/expr.c                       |  6 ++----
> >  gdb/testsuite/gdb.dwarf2/shortpiece.exp | 12 ++++++++++++
> >  2 files changed, 14 insertions(+), 4 deletions(-)
> >
> > diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c index
> > 99862583336..6330a5787fc 100644
> > --- a/gdb/dwarf2/expr.c
> > +++ b/gdb/dwarf2/expr.c
> > @@ -174,10 +174,8 @@ rw_pieced_value (value *v, value *from, bool
> check_optimized)
> >      }
> >    else
> >      {
> > -      if (value_type (v) != value_enclosing_type (v))
> > -	internal_error (__FILE__, __LINE__,
> > -			_("Should not be able to create a lazy value with "
> > -			  "an enclosing type"));
> > +      gdb_assert ((TYPE_LENGTH (value_type (v)) +
> value_embedded_offset (v))
> > +		  <= TYPE_LENGTH (value_enclosing_type (v)));
> 
> This looks like an assertion that should hold for all values, all the time.  When
> a value has an enclosing type different than its type, the type should be
> strictly a subset of the enclosing type.  So, it seems a bit odd to check this
> here specifically.  It would maybe make more sense to check it when
> modifying the type or enclosing_type of a value.  In any case, that's separate
> from the current patch.  If we find out that it is correct to remove the existing
> internal_error call, then I would just simply remove it (replace it with
> nothing).

I agree here.  I will submit a new version of the patch with the extended testcase
and the removed assertion if we conclude that it's safe to remove.

> Simon

Thanks
Stephan
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


  reply	other threads:[~2022-10-11  8:03 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-22 14:44 [PATCH 0/1] " Stephan Rohr
2022-04-22 14:44 ` [PATCH 1/1] gdb/dwarf2: " Stephan Rohr
2022-06-06 16:51   ` Bruno Larsen
2022-07-14  7:50   ` Rohr, Stephan
2022-07-21 12:21   ` Rohr, Stephan
2022-08-02  6:30   ` Rohr, Stephan
2022-08-11  7:09   ` Rohr, Stephan
2022-08-19  7:41   ` Rohr, Stephan
2022-08-19 16:39   ` Simon Marchi
2022-10-11  8:03     ` Rohr, Stephan [this message]
2022-10-21 17:06       ` Tom Tromey
2022-10-14 18:28     ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR11MB4564275FFC6CE96E79C5E62D93239@DM6PR11MB4564.namprd11.prod.outlook.com \
    --to=stephan.rohr@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=simark@simark.ca \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).