Repository navigation
fastffi attribute is sometimes ignored or incorrectly assigned #6660
Description
Activity
I'm not entirely clear what's going on here. Both functions appear to have the same type but the testcase says it's testing them being different. Can you clarify?
Woah, I forgot about this bug. This is an interesting test case. It has nothing to do with fastffi. In fact, i'm not sure why it crashes, it kind of .. looks like an LLVM bug? But something fishy is definitely going on. Here is an updated test:
// Test what happens when we link to the same function name with // different types. This situation can easily arise when linking two // crates that make use of the same C library, for example. mod A { pub struct TwoU32s { one: u32, two: u32 } extern { pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; } } mod B { pub struct TwoU32s { one: u32, two: u32 } extern { pub fn rust_dbg_extern_return_TwoU32s() -> TwoU32s; } } fn wrapper() { } #[fixed_stack_segment] fn main() { unsafe { let a = A::rust_dbg_extern_return_TwoU32s(); } unsafe { let b = B::rust_dbg_extern_return_TwoU32s(); } }On my branch for #8535, this code crashes when
maintries to return to an invalid address. This only happens if BOTH calls are present. The assembly code shows that between the two calls, there is a subtract of $esp which misaligns the stack frame (look for// XXX):subl $36, %esp .Ltmp12: .cfi_offset %ebx, -12 calll .L1$pb .L1$pb: popl %eax .Ltmp13: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp13-.L1$pb), %eax leal -16(%ebp), %ecx movl %ecx, (%esp) movl %eax, %ebx movl %eax, -28(%ebp) calll rust_dbg_extern_return_TwoU32s@PLT subl $4, %esp // XXX leal -24(%ebp), %eax movl %eax, (%esp) movl -28(%ebp), %ebx calll rust_dbg_extern_return_TwoU32s@PLT addl $36, %esp popl %ebx popl %ebp retHowever, when I dump the LLVM output with
--emit-llvm -S, I get nonsense:; Function Attrs: fixedstacksegment noinline uwtable define void @"_ZN4main16_cd92990fc38403c7_0$x2e0E"({ i32, %tydesc*, i8*, i8*, i8 }*) #1 { "function top level": %a = alloca %"struct.A::TwoU32s" %b = alloca %"struct.B::TwoU32s" call void @rust_dbg_extern_return_TwoU32s(%"struct.A::TwoU32s"* %a) call void bitcast (void (%"struct.A::TwoU32s"*)* @rust_dbg_extern_return_TwoU32s to void (%"struct.B::TwoU32s"*)*)(%"struct.B::TwoU32s"* %b) ret void }There is only one call here at all?
Anyway, an interesting bug. (note that I am running on 32 bit linux, btw, which may be relevant)
Should it be casting the whole function as opposed to just the argument in the second call?
Oh, wait, you're right, I misread that LLVM code, there are in fact two calls. I'd say it... looks about right, actually. Yes, it should be casting the function.
This is no longer used.
- added a commit that references this issue
on Feb 11, 2021
The following test, originally written for #3678, results in a segfault because insufficient stack is allocated (at least it does on the branch I plan to land that fixes #3678).
Paging @pcwalton, maybe you could take a look (once the PR for #3678 lands?)