Segfault when calling malloc or puts from Cranelift-generated code

168 Views Asked by At

I'm working on a small programming language compiled using cranelift. Now, my generated code segfaults whenever I call malloc or even puts. I'll focus on a small example with malloc:

The code I'm trying to compile is roughly equivalent to the following pseudo-C program:

void _start(){
   malloc(8);
   exit(0);
   return;
}

Note that I'm not actually compiling C and therefore using the _start entrypoint, like you would in assembler, instead of Cs main.

The generated Cranelift IR:

function u0:0() system_v {
    sig0 = (i64) -> i64 system_v    # malloc
    sig1 = (i32) system_v           # exit
    fn0 = u0:0 sig0
                                    # fn1 is not defined for some reason?
block0:
    v0 = iconst.i64 8
    v1 = call fn0(v0)  ; v0 = 8
    v2 = iconst.i32 0
    call fn1(v2)  ; v2 = 0
    return
}

Which is compiled to an object file which I link using

ld -pie -O2 --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -o test -lc test.o

I tried omitting the -pie and -O2 with no effect. The default link interpreter is /lib/ld64 for some reason which does not produce a valid executable on my system.

This Cranelift IR is equvalent to the following assembly:

Dissassembled using objdump -d test.o:

<other functions omitted>

00000000000010f0 <_start>:
    10f0:       55                      push   %rbp
    10f1:       48 89 e5                mov    %rsp,%rbp
    10f4:       bf 08 00 00 00          mov    $0x8,%edi
    10f9:       48 8b 15 f0 1e 00 00    mov    0x1ef0(%rip),%rdx        # 2ff0 <malloc@GLIBC_2.2.5>
    1100:       ff d2                   call   *%rdx
    1102:       31 ff                   xor    %edi,%edi
    1104:       48 8b 15 ed 1e 00 00    mov    0x1eed(%rip),%rdx        # 2ff8 <exit@GLIBC_2.2.5>
    110b:       ff d2                   call   *%rdx
    110d:       48 89 ec                mov    %rbp,%rsp
    1110:       5d                      pop    %rbp
    1111:       c3                      ret   

Dissassembled using Cranelift itself:

  pushq   %rbp
  unwind PushFrameRegs { offset_upward_to_caller_sp: 16 }
  movq    %rsp, %rbp
  unwind DefineNewFrame { offset_upward_to_caller_sp: 16, offset_downward_to_clobbers: 0 }
block0:
  movl    $8, %edi
  load_ext_name userextname0+0, %rdx
  call    *%rdx
  xorl    %edi, %edi, %edi
  load_ext_name userextname1+0, %rdx
  call    *%rdx
  movq    %rbp, %rsp
  popq    %rbp
  ret

A GDB-Stacktrace of the segfault:

(gdb) backtrace
#0  0x00007ffff7ca4540 in _int_malloc (av=av@entry=0x7ffff7e19c80 <main_arena>, bytes=bytes@entry=640) at ./malloc/malloc.c:4375
#1  0x00007ffff7ca4a49 in tcache_init () at ./malloc/malloc.c:3245
#2  0x00007ffff7ca525e in tcache_init () at ./malloc/malloc.c:3241
#3  __GI___libc_malloc (bytes=8) at ./malloc/malloc.c:3306
#4  0x0000555555555102 in _start ()

Used Cranelift Options:

use_colocated_libcalls: "false"
is_pic: "true"
opt_level: "speed"
regalloc_checker: "true"
enable_alias_analysis: "true"
enable_verifier: "true"
enable_probestack: "false"

I can update the question with strace and valgrind output if needed. I'm on Ubuntu 22.04 x64 using Cranelift 0.93.1 (using cranelift-object for emitting the obj-file).

0

There are 0 best solutions below