sunfishcode / llvm2cranelift

LLVM IR to Cranelift IR translator
Apache License 2.0
36 stars 4 forks source link

segfault: missing function prelude / stack frames? #1

Closed m4b closed 6 years ago

m4b commented 7 years ago

Consider the following bitcode, deadbeef.ll:

define i32 @deadbeef(i32 %param) {
    %temp = add i32 %param, 3735928559
    ret i32 %temp
}

define i32 @foo() {
    %t = call i32 @deadbeef(i32 15)
    ret i32 %t
}

and (optionally) the following C to call it:

#include<stdio.h>

extern int foo();

int main() {
  printf("0x%x\n", foo());
}

If I compile deadbeef.ll using llvm2cretonne -> deadbeef.txt, and llc -> gcc -> lldeadbeef.txt, we can see the following difference:

diff -y /tmp/deadbeef.txt /tmp/lldeadbeef.txt 

deadbeef.o:     file format elf64-x86-64              | lldeadbeef.o:     file format elf64-x86-64

Disassembly of section .text.deadbeef:                | Disassembly of section .text:

0000000000000000 <deadbeef>:                    0000000000000000 <deadbeef>:
   0:   40 b8 ef be ad de       rex mov $0xdeadbeef,%eax      |    0:   8d 87 ef be ad de       lea    -0x21524111(%rdi),%eax
   6:   40 01 c7                rex add %eax,%edi         |    6:   c3                      retq   
   9:   40 89 f8                rex mov %edi,%eax         |    7:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
   c:   c3                      retq                  |    e:   00 00 

Disassembly of section .text.foo:                 | 0000000000000010 <foo>:
                                  |   10:   50                      push   %rax
0000000000000000 <foo>:                       |   11:   bf 0f 00 00 00          mov    $0xf,%edi
   0:   40 b8 0f 00 00 00       rex mov $0xf,%eax         |   16:   e8 00 00 00 00          callq  1b <foo+0xb>
   6:   40 89 c7                rex mov %eax,%edi         |   1b:   5a                      pop    %rdx
   9:   e8 00 00 00 00          callq  e <foo+0xe>        |   1c:   c3                      retq   
   e:   c3                      retq                  <

You'll notice that foo does not have a function prelude, and if the function is large enough, it will spill onto the stack like 0x4(rsp) even though no stack local space has been allocated/adjusted.

Even still, if you compile the above, via something like gcc main.c deadbeef.o -o main, the resulting binary will segfault inside of the function deadbeef; I don't really know why, it doesn't deref any pointers, but my best guess is the stack isn't aligned somehow, or the rex instruction(s) are doing something funky?

sunfishcode commented 7 years ago

Yeah; Cretonne isn't yet emitting the code to adjust the stack pointer. I've now filed https://github.com/stoklund/cretonne/issues/187 to track this issue.

tyler commented 6 years ago

This should be fixed now. 👍

sunfishcode commented 6 years ago

Specifically, stoklund/cretonne#201 is now merged, and basic function prologues and epilogues work.

One caveat is that the original testcase probably doesn't work yet, because it calls printf, which needs varargs ABI support, which Cretonne doesn't have yet (I've now filed https://github.com/stoklund/cretonne/issues/212 to track this).