为什么我回显到 shell 的程序路径与我使用调试器在内存中找到的路径不匹配?

问题描述 投票:0回答:1

我刚刚开始在我的 Mac Silicon M2 上学习 ARM 汇编。我编写了一个程序,它只获取其命令行参数(又名 argv)并使用 write 系统调用打印它们(并返回它们的编号 argc)。

该程序有效:它使用我调用它的确切路径输出二进制文件的完整路径。

但是当我使用 lldb 检查内存中我确信从中获取 argv[0] 的位置时,它总是包含绝对路径。

这是因为 lldb 总是使用绝对路径运行它吗?有办法找出来吗?如果是,这是 lddb 应该做的还是一个错误?

这是我的程序的源代码。

  1 // ARM assembly program on M2 for mac OS 14.7.1
  2 // print argv separated by newlines, return argc
  3 .global _start
  4 .p2align 2
  5 // input from OS:       W0 ... argc
  6 //                      X1 ... **char argv
  7 //                             argv[0] points to NULL separated concatenation
  8 //                             of elements of argv (for some reason)
  9 //
 10 // WORKING MEM: W19 argc
 11 //              X1 previous *argv for print
 12 //              X2 current str length
 13 //              W21 argc loop decr counter
 14 //              X22 *chr argv loop incr counter
 15 //              X23 *chr newline
 16 
 17 _start: 
 18         mov W19, W0             // W0 holds the number of args, copy
 19         adr X23, chr_newline    // make *"\n" available for printing
 20 // set up loop to print all arguments
 21         mov W21, W19       // put argc into loop counter
 22         ldr X22, [X1]      // X22 := *char argv[0]
 23 loop_argv:
 24         bl handle_arg      // print one argument
 25         sub W21, W21, #1   // decr loop counter
 26         cmp W21, #0        // loop if > 0
 27         b.gt loop_argv
 28 // exit
 29         mov  W0,   W19     // return code := argc
 30         mov  X16,  #1      // service code for termination
 31         svc  #0x80         // make sys call
 32 // local function handle_arg
 33 handle_arg:
 34         mov X1, X22        // save start *char in X1
 35         mov X2, #0         // X2 should contain len at end 
 36 count_chars_loop: // search for NULL char separating args
 37         ldrb W0, [X22], #1  // W0 = &X22, incr *char X22 after 
 38         cmp W0, #0          // check if prev X22 pointed to NULL char
 39         add X2, X2, #1      // incr len
 40         b.gt count_chars_loop
 41         sub X2, X2, #1      // correct for overcounting
 42         // X22 = *next argv now 
 43 //print argv[i] 
 44         mov X0, #1                // to stdout
 45         // *char next argv is already in X1
 46         // len(argv[i]) is already in X2
 47         mov  X16, #4              // nr for write call
 48         svc       #0x80           // make sys call
 49 // print newline
 50         mov X0, #1                // to stout
 51         mov X1, X23               // X1 = *char newline
 52         mov X2, #1                // len("\n")
 53         mov  X16, #4              // nr for write call
 54         svc       #0x80           // make sys call
 55         ret
 56 .align 2
 57 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 %

注意相对路径。 (我也尝试用绝对路径调用它,然后我确实在终端上得到了它。)但是我们打印的位置似乎always包含二进制文件的完整绝对路径。为了检查这一点,我使用了

lldb -- ./bin/get_args_min test test

...然后是 lldb 命令

b handle_args
r
re r

...然后复制X22中的地址,然后

memory read [PASTE]
macos shell arm64 argv apple-silicon
1个回答
0
投票

这可能是由

lldb
启动程序的方式引起的,即使用其绝对路径,而 shell 使用您指定的路径(相对或绝对)。

当您启动

lldb
时,它会显示它将启动的可执行文件。即使您没有向可执行文件路径添加目录前缀,它也会将可执行文件设置为其绝对路径:

$ lldb -- get_args_min foo bar
(lldb) target create "get_args_min"
Current executable set to '/tmp/get_args_min' (arm64).

我对

man execve
的理解是,
argv[0]
的值不是标准化的,它由调用程序(因此shell或
lldb
)来设置它。

© www.soinside.com 2019 - 2024. All rights reserved.