This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix GCC PR83906 - [8 Regression] Random FAIL: libstdc++-prettyprinters/80276.cc whatis p4


On 2018-01-24 12:27 PM, Pedro Alves wrote:
> GCC PR83906 [1] is about a GCC/libstdc++ GDB/Python type printer
> testcase failing randomly, as shown by running (in libstdc++'s
> testsuite):
> 
>  make check RUNTESTFLAGS=prettyprinters.exp=80276.cc
> 
> in a loop.  Sometimes you get this:
> 
>  FAIL: libstdc++-prettyprinters/80276.cc whatis p4
> 
> I.e., this:
>  type = std::unique_ptr<std::vector<std::unique_ptr<std::list<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >>[]>>[99]>
> 
> instead of this:
>  type = std::unique_ptr<std::vector<std::unique_ptr<std::list<std::string>[]>>[99]>
> 
> Jonathan Wakely tracked it on the printer side to this bit in
> libstdc++'s type printer:
> 
>             if self.type_obj == type_obj:
>                 return strip_inline_namespaces(self.name)
> 
> This assumes the two types resolve to the same gdb.Type but some times
> the comparison unexpectedly fails.
> 
> Running the testcase manually under Valgrind finds the problem in GDB:
> 
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>  ==6118== Conditional jump or move depends on uninitialised value(s)
>  ==6118==    at 0x4C35CB0: bcmp (vg_replace_strmem.c:1100)
>  ==6118==    by 0x6F773A: check_types_equal(type*, type*, VEC_type_equality_entry_d**) (gdbtypes.c:3515)
>  ==6118==    by 0x6F7B00: check_types_worklist(VEC_type_equality_entry_d**, bcache*) (gdbtypes.c:3618)
>  ==6118==    by 0x6F7C03: types_deeply_equal(type*, type*) (gdbtypes.c:3655)
>  ==6118==    by 0x4D5B06: typy_richcompare(_object*, _object*, int) (py-type.c:1007)
>  ==6118==    by 0x63D7E6C: PyObject_RichCompare (object.c:961)
>  ==6118==    by 0x646EAEC: PyEval_EvalFrameEx (ceval.c:4960)
>  ==6118==    by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519)
>  ==6118==    by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519)
>  ==6118==    by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519)
>  ==6118==    by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519)
>  ==6118==    by 0x646DC08: PyEval_EvalFrameEx (ceval.c:4519)
>  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> That "bcmp" call is really a memcmp call in check_types_equal.  The
> problem is that gdb is memcmp'ing two objects that are equal in value:
> 
>  (top-gdb) p *TYPE_RANGE_DATA (type1)
>  $1 = {low = {kind = PROP_CONST, data = {const_val = 0, baton = 0x0}}, high = {kind = PROP_CONST, data = {const_val = 15, baton = 0xf}}, flag_upper_bound_is_count = 0,
>    flag_bound_evaluated = 0}
>  (top-gdb) p *TYPE_RANGE_DATA (type2)
>  $2 = {low = {kind = PROP_CONST, data = {const_val = 0, baton = 0x0}}, high = {kind = PROP_CONST, data = {const_val = 15, baton = 0xf}}, flag_upper_bound_is_count = 0,
>    flag_bound_evaluated = 0}
> 
> but differ in padding.  Notice the 4-byte hole:
> 
>   (top-gdb) ptype /o range_bounds
>   /* offset    |  size */  type = struct range_bounds {
>   /*    0      |    16 */    struct dynamic_prop {
>   /*    0      |     4 */        dynamic_prop_kind kind;
>   /* XXX  4-byte hole  */
>   /*    8      |     8 */        union dynamic_prop_data {
>   /*                 8 */            LONGEST const_val;
>   /*                 8 */            void *baton;
> 
> 				     /* total size (bytes):    8 */
> 				 } data;
> 
> which is filled with garbage:
> 
>   (top-gdb) x /40bx TYPE_RANGE_DATA (type1)
>   0x2fa7ea0:      0x01    0x00    0x00    0x00    0x43    0x01    0x00    0x00
> 						  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   0x2fa7ea8:      0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
>   0x2fa7eb0:      0x01    0x00    0x00    0x00    0xfe    0x7f    0x00    0x00
>   0x2fa7eb8:      0x0f    0x00    0x00    0x00    0x00    0x00    0x00    0x00
>   0x2fa7ec0:      0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
>   (top-gdb) x /40bx TYPE_RANGE_DATA (type2)
>   0x20379b0:      0x01    0x00    0x00    0x00    0xfe    0x7f    0x00    0x00
> 						  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   0x20379b8:      0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
>   0x20379c0:      0x01    0x00    0x00    0x00    0xfe    0x7f    0x00    0x00
>   0x20379c8:      0x0f    0x00    0x00    0x00    0x00    0x00    0x00    0x00
>   0x20379d0:      0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
> 
>   (top-gdb) p memcmp (TYPE_RANGE_DATA (type1), TYPE_RANGE_DATA (type2), sizeof (*TYPE_RANGE_DATA (type1)))
>   $3 = -187
> 
> In some cases objects of type range_bounds are memset when allocated,
> but then their dynamic_prop low/high fields are copied over from some
> template dynamic_prop object that wasn't memset.  E.g.,
> create_static_range_type's low/high locals are left with garbage in
> the padding, and then that padding is copied over to the range_bounds
> object's low/high fields.
> 
> At first, I considered making sure to always memset range_bounds
> objects, thinking that maybe type objects are being put in some bcache
> instance somewhere.  But then I hacked bcache/bcache_full to poison
> non-pod types, and made dynamic_prop a non-pod, and GDB still
> compiled.
> 
> So given that, it seems safest to not assume padding will always be
> memset, and instead treat them as regular value types, implementing
> (in)equality operators and using those instead of memcmp.
> 
> This fixes the random FAILs in GCC's testcase.
> 
> [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83906

LGTM.

Simon


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]