diff options
author | Tom de Vries <tdevries@suse.de> | 2019-10-16 17:11:56 +0200 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2019-10-16 17:11:56 +0200 |
commit | 745ff14e6e1b88f04eb447d4883fab81650f745f (patch) | |
tree | 7b8728ac46412b1349f6eaf7b273f16b1798db24 /gdb/gdbsupport/cleanups.h | |
parent | 03e1ab9424bd1d37da5818549067ef7a7b7ec641 (diff) | |
download | gdb-745ff14e6e1b88f04eb447d4883fab81650f745f.zip gdb-745ff14e6e1b88f04eb447d4883fab81650f745f.tar.gz gdb-745ff14e6e1b88f04eb447d4883fab81650f745f.tar.bz2 |
[gdb/tdep] Fix 'Unexpected register class' assert in amd64_push_arguments
Atm, when executing gdb.base/infcall-nested-structs.exp on x86_64-linux, we get:
...
FAIL: gdb.base/infcall-nested-structs.exp: l=c++: types-tc-tf: \
p/d check_arg_struct_02_01 (ref_val_struct_02_01)
FAIL: gdb.base/infcall-nested-structs.exp: l=c++: types-ts-tf: \
p/d check_arg_struct_02_01 (ref_val_struct_02_01)
FAIL: gdb.base/infcall-nested-structs.exp: l=c++: types-ti-tf: \
p/d check_arg_struct_02_01 (ref_val_struct_02_01)
=== gdb Summary ===
nr of expected passes 9255
nr of unexpected failures 3
nr of expected failures 142
...
The 3 FAILs are reported as PR tdep/25096.
The 142 XFAILs are for a gdb assertion failure, reported in PR tdep/24104,
which should have been KFAILs since there's a problem in gdb rather than in
the environment.
A minimal version of the assertion failure looks like this. Consider test.c:
...
struct s { struct { } es1; long f; };
struct s ref = { {}, 'f' };
int __attribute__((noinline,noclone)) check (struct s arg)
{ return arg.f == 'f'; }
int main (void)
{ return check (ref); }
...
When calling 'check (ref)' from main, we have '1' as expected:
...
$ g++ test3.c -g && ( ./a.out; echo $? )
1
...
But when calling 'check (ref)' from the gdb prompt, we get:
...
$ gdb a.out -batch -ex start -ex "p check (ref)"
Temporary breakpoint 1 at 0x4004f7: file test.c, line 8.
Temporary breakpoint 1, main () at test.c:8
8 { return check (ref); }
src/gdb/amd64-tdep.c:982: internal-error: \
CORE_ADDR amd64_push_arguments(regcache*, int, value**, CORE_ADDR, \
function_call_return_method): \
Assertion `!"Unexpected register class."' failed.
...
The assert happens in this loop in amd64_push_arguments:
...
for (j = 0; len > 0; j++, len -= 8)
{
int regnum = -1;
int offset = 0;
switch (theclass[j])
{
case AMD64_INTEGER:
regnum = integer_regnum[integer_reg++];
break;
case AMD64_SSE:
regnum = sse_regnum[sse_reg++];
break;
case AMD64_SSEUP:
gdb_assert (sse_reg > 0);
regnum = sse_regnum[sse_reg - 1];
offset = 8;
break;
default:
gdb_assert (!"Unexpected register class.");
}
...
}
...
when processing theclass[0], which is AMD64_NO_CLASS:
...
(gdb) p theclass
$1 = {AMD64_NO_CLASS, AMD64_INTEGER}
...
The layout of struct s is that the empty field es1 occupies one byte (due to
c++) at offset 0, and the long field f occupies 8 bytes at offset 8.
When compiling at -O2, we can see from the disassembly of main:
...
4003f0: 48 8b 3d 41 0c 20 00 mov 0x200c41(%rip),%rdi \
# 601038 <ref+0x8>
4003f7: e9 e4 00 00 00 jmpq 4004e0 <_Z5check1s>
4003fc: 0f 1f 40 00 nopl 0x0(%rax)
...
that check is called with field f passed in %rdi, meaning that the
classification in theclass is correct, it's just not supported in the loop in
amd64_push_arguments mentioned above.
Fix the assert by implementing support for 'AMD64_NO_CLASS' in that loop.
This exposes 9 more FAILs of the PR tdep/25096 type, so mark all 12 of them as
KFAIL.
Tested on x86_64-linux.
Tested with g++ 4.8.5, 7.4.1, 8.3.1, 9.2.1. With 4.8.5, 3 of the 12 KFAILs
are KPASSing.
Tested with clang++ 5.0.2 (which requires removing additional_flags=-Wno-psabi
and adding additional_flags=-Wno-deprecated).
gdb/ChangeLog:
2019-10-16 Tom de Vries <tdevries@suse.de>
PR tdep/24104
* amd64-tdep.c (amd64_push_arguments): Handle AMD64_NO_CLASS in loop
that handles 'theclass'.
gdb/testsuite/ChangeLog:
2019-10-16 Tom de Vries <tdevries@suse.de>
PR tdep/24104
* gdb.base/infcall-nested-structs.exp: Remove XFAIL for PR tdep/24104.
Add KFAIL for PR tdep/25096.
Change-Id: I8b66345bbf5c00209ca75b1209fd4d60b36e9ede
Diffstat (limited to 'gdb/gdbsupport/cleanups.h')
0 files changed, 0 insertions, 0 deletions