LLDB和库函数的内存地址

LLDB and the memory addresses of library functions

我有一个 "Hello World" 程序,我附加了 lldb。我试图为自己回答几个关于我尝试获取库函数地址时得到的结果的问题:

(lldb) image lookup -n printf
1 match found in /usr/lib/system/libsystem_c.dylib:
        Address: libsystem_c.dylib[0x000000000003f550] (libsystem_c.dylib.__TEXT.__text + 253892)
        Summary: libsystem_c.dylib`printf
(lldb) image lookup -n scanf
1 match found in /usr/lib/system/libsystem_c.dylib:
        Address: libsystem_c.dylib[0x000000000003fc69] (libsystem_c.dylib.__TEXT.__text + 255709)
        Summary: libsystem_c.dylib`scanf
(lldb) expr &printf
(int (*)(const char *__restrict, ...))  = 0x00007fff6f8c5550 (libsystem_c.dylib`printf)
(lldb) expr &scanf
error: unsupported expression with unknown type

我这里有三个问题:

  1. 0x00007fff6f8c5550是个什么样的地址?我假设它是指向 printf 的函数指针。这是一个只存在于当前进程映射space中的虚拟地址吗?如果是,为什么另一个程序 return 与 printf 的地址相同?

  2. 假设它是每个进程都相同的某个全局共享地址,将修改该地址处的数据内容(我还不能这样做)创建一个副本修改后的内存页和地址会改变吗? (我在 Mac OS 并且我假设一个进程不能为另一个进程更改共享内存)

  3. 为什么 expr &scanf 不行,而 expr &printf 可以?

  1. What kind of address is 0x00007fff6f8c5550? I assume it is the function pointer to printf.

是的,没错。

Is this a virtual address that exists only in the mapped space of the current process?

好吧,是的,也不是。它是特定于您的进程的虚拟地址,您不应假定它在另一个进程中有效。但是:

If yes, why does another program return the same address for printf?

作为一项优化,macOS 对许多系统库使用共享映射。它们在启动时加载一次并被所有进程使用。对于给定的引导,地址在所有此类进程中都是恒定的。但是,为了安全起见,地址在每次启动时都是随机的。

  1. Assuming it's some global shared address that is the same for every process, would modifying the contents of the data at this address (which I haven't been able to do yet) create a copy of the modified memory page and will the address change?

好吧,它是写时复制映射的。因此,修改它会创建一个副本。但是,这不会改变它的地址。 OS 将简单地修改映射,以便该地址周围的内存对您的进程是私有的。

(i'm on Mac OS and I assume one process cannot change shared memory for another process)

好吧,进程可以合作拥有可写的共享内存。但是,总的来说,您是正确的,安全预防措施可以防止对进程的内存进行不必要的修改。

  1. Why does expr &scanf not work, but expr &printf does?

您的程序(大概)没有使用 scanf,因此没有关于它的调试信息。 lldb 缺少的主要内容是 scanf 的类型。如果你使用强制转换表达式,它可以工作:

(lldb) p scanf
error: 'scanf' has unknown type; cast it to its declared type to use it
(lldb) p &scanf
error: unsupported expression with unknown type
(lldb) p (int(*)(const char * __restrict, ...))scanf
(int (*)(const char *__restrict, ...))  = 0x00007fffd7e958d4 (libsystem_c.dylib`scanf)

相反,它适用于 printf,因为您的程序确实使用了它。