ARM架构下调用execve系统调用(syscall 11)的方法及报错排查
解决ARM架构下execve系统调用的NULL argv[0]错误
首先直接点出问题根源:你把r1置为0(也就是传递了NULL作为argv参数),但execve系统调用要求argv必须是一个非空的、以NULL结尾的字符串数组,而且数组的第一个元素(argv[0])不能为NULL——这就是你看到报错的核心原因。另外你写的路径"\bin\ls"也有问题:Unix系统里路径用正斜杠/分隔,而\b是退格转义符,实际路径会变成无效格式,这也会导致找不到ls程序。
正确的代码修改方案
下面是修正后的汇编代码,我会逐点说明修改细节:
@ execve takes 3 arguments (r0,r1,r2) mov r7,#11 @ syscall number for execve ldr r0,=addr_of_string @ r0 = 程序路径 "/bin/ls" ldr r1,=argv @ r1 = argv数组的地址,数组第一个元素是程序路径,结尾为NULL sub r2,r2,r2 @ r2 = NULL,表示环境变量为空 svc #0 end: mov r7,#1 svc 0 .data addr_of_string: .asciz "/bin/ls" @ 修正路径:用正斜杠,去掉错误的转义符 argv: .word addr_of_string, 0 @ 定义argv数组:[ "/bin/ls", NULL ]
关键修改点解释
- 修正程序路径:把原来的
"\bin\ls"改成"/bin/ls",这是Unix系统下正确的可执行文件路径格式,避免因路径无效导致的"文件不存在"错误。 - 添加合法的argv数组:在
.data段定义argv数组,第一个元素指向程序路径字符串,第二个元素是0(即NULL),满足execve对argv的要求——数组必须以NULL结尾,且至少包含一个有效元素(argv[0])。 - 正确赋值r1:不再把
r1清零,而是加载argv数组的地址到r1,这样传递给execve的就是合法的参数数组了。
为什么不能传递NULL作为argv?
虽然早期Unix系统允许argv为NULL,但现代Linux系统会严格检查这个参数:如果argv是NULL,或者argv[0]是NULL,就会抛出你看到的A NULL argv[0] was passed through an exec system call错误。这是一种安全机制,确保程序执行时能获取到合法的程序名参数。
现在编译链接修改后的代码,应该就能正常执行ls命令了!
内容的提问来源于stack exchange,提问作者user7083361
相关产品推荐
相关产品推荐

