Apple M2 ARM汇编程序:Shell输出路径与LLDB内存中argv[0]不一致
LLDB调试时argv[0]始终为绝对路径的原因与验证
问题背景
在Apple Silicon M2芯片上编写ARM汇编程序,通过write系统调用读取并打印argv,程序直接运行时会输出调用时使用的相对/绝对路径;但用LLDB调试时,内存中argv[0]始终存储的是二进制文件的完整绝对路径。
核心结论
LLDB确实会将程序的绝对路径传递给被调试进程的argv[0],这是LLDB的预期行为,而非bug。
验证方法
方法1:查看LLDB实际传递的启动参数
在LLDB中启动程序后,执行以下命令查看进程的完整启动参数:
process launch --show-args
该命令会显示LLDB传递给被调试程序的所有参数,你会看到argv[0]是二进制文件的绝对路径,而非你输入的相对路径。
方法2:对比直接运行与LLDB调试的差异
编写一个极简C程序打印原始argv[0](排除汇编代码中字符串处理的干扰):
#include <stdio.h> int main(int argc, char *argv[]) { printf("argv[0] = %s\n", argv[0]); return 0; }
编译后测试:
- 直接运行:
./test,输出相对路径./test - LLDB调试:
lldb -- ./test,运行后输出二进制文件的绝对路径(如/Users/me/get_args/test)
原因分析
LLDB作为调试器,需要精准定位被调试的二进制文件,用于加载符号表、设置断点、读取调试信息等核心操作。使用绝对路径可以避免当前工作目录变化导致的路径解析错误,确保调试流程的稳定性。这是调试器的通用设计逻辑,并非LLDB特有的行为。
附:原始汇编程序与测试信息
汇编源码
// ARM assembly program on M2 for mac OS 14.7.1 // print argv separated by newlines, return argc .global _start .p2align 2 // input from OS: W0 ... argc // X1 ... **char argv // argv[0] points to NULL separated concatenation // of elements of argv (for some reason) // // WORKING MEM: W19 argc // X1 previous *argv for print // X2 current str length // W21 argc loop decr counter // X22 *chr argv loop incr counter // X23 *chr newline _start: mov W19, W0 // W0 holds the number of args, copy adr X23, chr_newline // make *"\n" available for printing // set up loop to print all arguments mov W21, W19 // put argc into loop counter ldr X22, [X1] // X22 := *char argv[0] loop_argv: bl handle_arg // print one argument sub W21, W21, #1 // decr loop counter cmp W21, #0 // loop if > 0 b.gt loop_argv // exit mov W0, W19 // return code := argc mov X16, #1 // service code for termination svc #0x80 // make sys call // local function handle_arg handle_arg: mov X1, X22 // save start *char in X1 mov X2, #0 // X2 should contain len at end count_chars_loop: // search for NULL char separating args ldrb W0, [X22], #1 // W0 = &X22, incr *char X22 after cmp W0, #0 // check if prev X22 pointed to NULL char add X2, X2, #1 // incr len b.gt count_chars_loop sub X2, X2, #1 // correct for overcounting // X22 = *next argv now //print argv[i] mov X0, #1 // to stdout // *char next argv is already in X1 // len(argv[i]) is already in X2 mov X16, #4 // nr for write call svc #0x80 // make sys call // print newline mov X0, #1 // to stdout mov X1, X23 // X1 = *char newline mov X2, #1 // len("\n") mov X16, #4 // nr for write call svc #0x80 // make sys call ret .align 2 chr_newline: .ascii "\n"
编译链接命令
as get_args.s -o get_args.o ld -o bin/get_args_min get_args_min.o -lSystem -syslibroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -e _start -arch arm64
直接运行结果
me@c get_args % ./bin/get_args_min test test ./bin/get_args_min test test me@c get_args %
LLDB调试步骤
lldb -- ./bin/get_args_min test test
在LLDB中执行:
b handle_arg r re r # 复制X22中的地址后执行 memory read [PASTE_ADDRESS]
内容的提问来源于stack exchange,提问作者relatively
相关产品推荐
相关产品推荐

