[gdb/testsuite] Fix gdb.rust/methods.exp on i686-linux
On i686-linux, with test-case gdb.rust/methods.exp I get:
...
(gdb) print x.take()
$5 = methods::HasMethods {value: 4}
(gdb) FAIL: $exp: print x.take()
...
The instructions for the function methods::HasMethods::take look like this:
...
00007b90 <_ZN7methods10HasMethods4take17hf373500ea3bd6e27E>:
7b90: 8b 44 24 04 mov 0x4(%esp),%eax
7b94: c3 ret
...
which is equivalent to what you get for:
...
$ cat test.c
int foo (int val) { return val; }
$ gcc test.c -O2 -S -o-
...
movl 4(%esp), %eax
ret
...
$
...
The inferior call mechanism however decides that this is a return_method_struct
function, and adds an implicit first parameter pointing to the return value
location. Then two things go wrong:
- the argument is written to a place where the code doesn't read from, and
- the return value is read from a place where the code doesn't write to.
AFAIU, both gdb and rustc are behaving correctly:
- there's no stable ABI and consequently rustc is at liberty to optimize this
function how it wants, and
- gdb cannot be expected to target an unstable ABI.
The solution is to mark the function for interoperability using 'extern "C"'.
Doing so causes a compilation warning:
...
warning: `extern` fn uses type `HasMethods`, which is not FFI-safe
--> gdb.rust/methods.rs:50:28
|
50 | pub extern "C" fn take(self) -> HasMethods {
| ^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute
to this struct
= note: this struct has unspecified layout
...
which we fix by using '#[repr(C)]'.
Likewise in gdb.rust/generics.exp.
Tested on i686-linux and x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
2 files changed