First use task_for_pid() to obtain a task port.
Then find the "dyld all images info address" using task_info:
struct task_dyld_info dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
if (task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count) == KERN_SUCCESS)
{
// retrieve dyld_info.all_image_info_addr;
}
This address will point to a struct dyld_all_image_infos in memory:
struct dyld_all_image_infos {
uint32_t version;
uint32_t infoArrayCount;
const struct dyld_image_info* infoArray;
// ...
}
The infoArrayCount and infoArray entries are important here. You have to retrieve these values (use mach_vm_read) and iterate through the infoArray. Each entry is a struct dyld_image_info:
struct dyld_image_info {
const struct mach_header* imageLoadAddress;
const char* imageFilePath;
uintptr_t imageFileModDate;
};
In this struct, you are interested in retrieving the values to imageLoadAddress (an address to the library in memory) and imageFilePath (an address to the NULL terminated file path in memory).
Important note: the fields that are marked as a pointer or as uintptr_t in the structs above have a different byte size depending on whether the running process is 32 or 64 bit. You may be able to determine pointer size by seeing if dyld_info.all_image_info_format is TASK_DYLD_ALL_IMAGE_INFO_32 or TASK_DYLD_ALL_IMAGE_INFO_64 (should work, but I have not tested this myself).
Lastly, this will still not include an entry to the dynamic linker itself. To retrieve that, one way I've found is to iterate through the vm regions (i.e, mach_vm_region), and find the first region that looks like it's a mach dylinker (check for MH_DYLINKER as the file type; see mach-o file format for more info). Last I recall checking, gdb and/or lldb have a function for doing this too. Parsing the mach header is also one possible way to tell if the process is 32 or 64 bit.
After you retrieve all the dyld image info entries, you may also want to sort them by address.
I recommend not looking at newosxbook's code for its vmmap implementation. It is outdated (since it still uses DYLD_ALL_IMAGE_INFOS_OFFSET_OFFSET), and it does some unnecessary brute-forcing.