You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 11:22:05