我在MIPS(32位)中加载一个普通的静态链接ELF二进制文件。在映射可加载段之后,这是我在跳转到目标ELF的CRT的_start
函数之前设置堆栈的方式:
__asm__(" \
addi $2, %[envN], 0 ;\
.env_loop: \
addi $2, $2, -4 ;\
lw $3, 0($2) ;\
addi $sp, $sp, -4 ;\
sw $3, 0($sp) ;\
bne $2, %[env0], .env_loop ;\
addi $2, %[argN], 0 ;\
.arg_loop: \
addi $2, $2, -4 ;\
lw $3, 0($2) ;\
addi $sp, $sp, -4 ;\
sw $3, 0($sp) ;\
bne $2, %[arg0], .arg_loop ;\
addi $2, %[argc], 0 ;\
addi $sp, $sp, -4 ;\
sw $2, 0($sp) ;\
addi $2, %[func], 0 ;\
jr $2 ;"
:
: [envN] "r" (envp + envc + 1),
[env0] "r" (envp),
[argN] "r" (argv + argc + 1),
[arg0] "r" (argv),
[argc] "r" ((int32_t)argc),
[func] "r" (entry_point)
: "$2", "$3", "cc", "memory"
);
这样我就可以在堆栈上推送环境变量,命令行参数argc
,最后跳转到目标ELF的入口点。这工作正常,我最终在我的加载程序的主函数内使用正确的命令行参数和所有内容,除了一件事:malloc
不起作用!对它的任何调用都返回null并将errno设置为ENOMEM
。
我正在使用的MIPS模拟器(qemu-system-mips)有足够的内存空间,如果我只是在不使用我的加载器的情况下启动程序它可以正常工作,所以它必须来自加载器。但我不明白为什么;我使用与x86,x86_64和arm相同的加载技术,它们都运行良好,但由于某些原因,malloc在加载器的MIPS版本中出现故障。
我在这里错过了什么吗?在跳转到加载的可执行文件之前实际需要做的事情,这可能对MIPS有用,但对于我成功尝试的其他架构却没有?我想我会在这里询问是否有人之前遇到过这个问题,因为我真的无法想象这里出了什么问题。
我在Linux下运行它并使用musl作为libc。经过一些调试后,我发现musl的expand_heap
函数出现了差异,但我还没有汇编信息的来源,因此不清楚bug是什么(musl对其他架构使用相同的malloc代码,以及他们的工作很好。)
二进制文件是静态链接的(包括libc;它没有动态依赖关系),其他所有东西(printf,fopen等等)在加载的二进制文件中工作正常,只有malloc(当然还有realloc /) calloc,我想是免费的)。所以这真的令人费解。
答案 0 :(得分:3)
自从我尝试做MIPS之后已经有一段时间了,但我认为你的辅助矢量需要看起来像这样:
pointerRelease
我记得,页面大小auxv条目对于musl的MIPS是唯一的。
答案 1 :(得分:1)
我不会说MIPS汇编,但看起来你并没有设置"辅助矢量"从位于此处的MIPS ABI的第3-30页开始定义:http://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - 这可能是问题的原因?