I have a "Hello World" program to which I've attached lldb. I'm trying to answer a few questions for myself about the results I get when I try to get the address of library functions:
(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, ...)) $2 = 0x00007fff6f8c5550 (libsystem_c.dylib`printf)
(lldb) expr &scanf
error: unsupported expression with unknown type
I have three questions here:
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
?
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? (i'm on Mac OS and I assume one process cannot change shared memory for another process)
Why does expr &scanf
not work, but expr &printf
does?
- What kind of address is
0x00007fff6f8c5550
? I assume it is the function pointer to printf.
Yes, that's correct.
Is this a virtual address that exists only in the mapped space of the current process?
Well, yes and no. It is a virtual address specific to your process and you should not assume it's valid in another process. But:
If yes, why does another program return the same address for
printf
?
As an optimization, macOS uses a shared mapping for a lot of the system libraries. They are loaded once at boot and used by all processes. For a given boot, the address is constant across all such processes. However, the address is randomized each boot for security.
- 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?
Well, it is mapped copy-on-write. So, modifying it would create a copy. However, that wouldn't change its address. The OS would simply modify the mapping so that the memory around that address is private to your process.
(i'm on Mac OS and I assume one process cannot change shared memory for another process)
Well, processes can cooperate to have writable shared memory. But, in general, you're correct that security precautions prevent unwanted modifications to a process's memory.
- Why does
expr &scanf
not work, butexpr &printf
does?
Your program (presumably) doesn't use scanf
, so there's no debugging information regarding it. The main thing lldb
is missing is the type of scanf
. If you use a cast expression, it can work:
(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, ...)) $3 = 0x00007fffd7e958d4 (libsystem_c.dylib`scanf)
Conversely, it works for printf
because your program does use it.