我正在研究一种使用 cranelift 编译的小型编程语言。现在,每当我调用
malloc
甚至 puts
时,我生成的代码都会出现段错误。我将专注于malloc
的一个小例子:
我尝试编译的代码大致相当于下面的伪C程序:
void _start(){
malloc(8);
exit(0);
return;
}
请注意,我实际上并没有编译 C,因此使用
_start
入口点,就像在汇编程序中一样,而不是 Cs main
.
生成的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
}
它被编译成一个目标文件,我使用它链接
ld -pie -O2 --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -o test -lc test.o
我尝试省略
-pie
和 -O2
没有效果。由于某些原因,默认链接解释器是/lib/ld64
,它不会在我的系统上生成有效的可执行文件。
此 Cranelift IR 相当于以下组件:
Dissassembled使用
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
使用 Cranelift 本身进行拆卸:
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
段错误的 GDB-Stacktrace:
(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 ()
二手起重机选项:
use_colocated_libcalls: "false"
is_pic: "true"
opt_level: "speed"
regalloc_checker: "true"
enable_alias_analysis: "true"
enable_verifier: "true"
enable_probestack: "false"
如果需要,我可以使用
strace
和 valgrind
输出更新问题。我在 Ubuntu 22.04 x64 上使用 Cranelift 0.93.1
(使用 cranelift-object
发出 obj 文件)。