How to obtain the list of loaded symbols of another process

894 views Asked by At

I'm trying to obtain the list of shared libs / images of another process at runtime, without reading the executable file, just by the data the process has in memory. Debuggers like gdb and lldb can attach to a process and then do something like the "image list" command e.g.:

(lldb) image list
[  0] 84C51E40-00C5-3710-8A99-04A0F6D078F5 0x000000010d29b000 /Applications/Mail.app/Contents/MacOS/Mail 
[  1] 4CDB0F7B-C0AF-3424-BC39-495696F0DB1E 0x00007fff82680000 /usr/lib/libDiagnosticMessagesClient.dylib 
[  2] 7DB320AB-4ED4-391E-89CC-125826D94026 0x00007fff87af2000 /System/Library/Frameworks/AddressBook.framework/Versions/A/AddressBook 
[  3] 195DA868-47A5-37E6-8CF0-9BCF11846899 0x00007fff89cff000 /System/Library/PrivateFrameworks/Backup.framework/Versions/A/Backup 
[  4] 27072D7F-8281-3958-A66C-3A3F862F3458 0x00007fff834e2000 /System/Library/Frameworks/CalendarStore.framework/Versions/A/CalendarStore 
[  5] E90E99D7-A425-3301-A025-D9E0CD11918E 0x00007fff8e5f3000 /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa 
[  6] 0F44FFB3-8C65-3565-9262-CF6FA0AE0C8A 0x00007fff86a75000 /System/Library/PrivateFrameworks/CoreRecents.framework/Versions/A/CoreRecents 
[  7] 187DF89C-8A64-366D-8782-F90315FA3CD7 0x00007fff875ed000 /System/Library/PrivateFrameworks/CoreUI.framework/Versions/A/CoreUI 
[  8] B25A09EC-A021-32EC-86F8-05B4837E0EDE 0x00007fff8f045000 /System/Library/PrivateFrameworks/CrashReporterSupport.framework/Versions/A/CrashReporterSupport 
[  9] 1C4C33FE-F364-3DBA-A1BC-4A53E594CFD3 0x00007fff87990000 /System/Library/PrivateFrameworks/DataDetectors.framework/Versions/A/DataDetectors 
[ 10] AB4C59AB-A5A7-3514-820D-11C5DAB24DAF 0x00007fff862d1000 /System/Library/PrivateFrameworks/EmailAddressing.framework/Versions/A/EmailAddressing 
[ 11] 34C0DAD6-763D-3760-93BA-54C5DC7D81DA 0x00007fff8af4c000 /System/Library/Frameworks/EventKit.framework/Versions/A/EventKit 
[ 12] 867EDAF0-5863-397E-BA75-855878D68949 0x00007fff87918000 /System/Library/PrivateFrameworks/ExchangeWebServices.framework/Versions/A/ExchangeWebServices 
[ 13] 326F679E-7ADF-38BB-9EAD-BD08FA65573E 0x00007fff8fdaa000 /System/Library/PrivateFrameworks/IMAP.framework/Versions/A/IMAP 
[ 14] D7175985-03A5-315B-B788-FBDC0019B0EA 0x00007fff8c981000 /System/Library/PrivateFrameworks/InternetAccounts.framework/Versions/A/InternetAccounts 
[ 15] 057FDBA3-56D6-3903-8C0B-849214BF1985 0x00007fff86cd0000 /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit 
[ 16] C617BE97-1D88-380F-B6EC-6D33485A44D0 0x00007fff847e4000 /System/Library/PrivateFrameworks/Mail.framework/Versions/A/Mail 
[ 17] ED4787DA-CBFC-3216-BE76-999597FF725C 0x00007fff86942000 /System/Library/PrivateFrameworks/MailCore.framework/Versions/A/MailCore 
[ 18] 9D8CEFF2-6ABD-3654-B70D-D878BB61EBD3 0x00007fff875e3000 /System/Library/PrivateFrameworks/MailService.framework/Versions/A/MailService 
[ 19] 2D08FD02-754E-3197-AB5F-7DF58946BF67 0x00007fff89172000 /System/Library/PrivateFrameworks/MailUI.framework/Versions/A/MailUI 
[ 20] CE4A0FC6-6E65-38AC-BC8E-74821D713B43 0x00007fff8cb38000 /System/Library/PrivateFrameworks/PassKit.framework/Versions/A/PassKit 
[ 21] 7B73DFF4-75DB-3403-80D2-0F3FE48764C3 0x00007fff8fd35000 /System/Library/PrivateFrameworks/PerformanceAnalysis.framework/Versions/A/PerformanceAnalysis 
[ 22] 08E58C71-D16C-3357-989C-780A08994B27 0x00007fff8e34c000 /System/Library/Frameworks/QTKit.framework/Versions/A/QTKit 
[ 23] 3B2A72DB-39FC-3C5B-98BE-605F37777F37 0x00007fff89f01000 /System/Library/Frameworks/Quartz.framework/Versions/A/Quartz 
[ 24] B3C61C91-E9D6-3A3C-99CF-665D54D13C34 0x00007fff88f0d000 /System/Library/Frameworks/Security.framework/Versions/A/Security 
[ 25] 0346D8A9-2CAA-38F3-A741-5FBA5E9F1E7C 0x00007fff85589000 /System/Library/Frameworks/SecurityInterface.framework/Versions/A/SecurityInterface 
[ 26] 4D9C44FF-5403-3372-A90E-CBF2A34D7CE7 0x00007fff8ef67000 /System/Library/PrivateFrameworks/SleepServices.framework/Versions/A/SleepServices 
[ 27] B7E5B685-C6A4-35DB-BA0A-8DBA2BF4ADF6 0x00007fff87117000 /System/Library/PrivateFrameworks/Suggestions.framework/Versions/A/Suggestions 
[ 28] EB8D3D78-92E7-3B67-8AAF-B51A181461E0 0x00007fff8c0fe000 /System/Library/Frameworks/WebKit.framework/Versions/A/WebKit 
[ 29] 24349208-3603-3F5D-95CC-B379616FBEF8 0x00007fff8cb7c000 /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation

I want to create such a list using task_for_pid and vm_read and then iterate over the list of symbols each image contains.

Has anyone ever done something like that and can you give me a hint where to start? I also looked at the source code of lldb and libdyld but I couldn't find the interesting parts yet.

2

There are 2 answers

0
Technologeeks On BEST ANSWER

Actually, it is quite trivial. Assuming you can read the image memory (use mach_vm_* APIs for that), it's just a matter of getting dyld's data, and walking it:

The right header file to consult in /usr/include/mach-o/dyld_images.h, wherein you find the symbol for dyld_all_image_infos. This is what lldb and others use, only they show you uuidArray from the structure below:

struct dyld_all_image_infos {
        uint32_t                                                version;                /* 1 in Mac OS X 10.4 and 10.5 */
        uint32_t                                                infoArrayCount;
        const struct dyld_image_info*   infoArray;
        dyld_image_notifier                             notification;           
        bool                                                    processDetachedFromSharedRegion;
        /* the following fields are only in version 2 (Mac OS X 10.6, iPhoneOS 2.0) and later */
        bool                                                    libSystemInitialized;
        const struct mach_header*               dyldImageLoadAddress;
        /* the following field is only in version 3 (Mac OS X 10.6, iPhoneOS 3.0) and later */
        void*                                                   jitInfo;
        /* the following fields are only in version 5 (Mac OS X 10.6, iPhoneOS 3.0) and later */
        const char*                                             dyldVersion;
        const char*                                             errorMessage;
        uintptr_t                                               terminationFlags;
        /* the following field is only in version 6 (Mac OS X 10.6, iPhoneOS 3.1) and later */
        void*                                                   coreSymbolicationShmPage;
        /* the following field is only in version 7 (Mac OS X 10.6, iPhoneOS 3.1) and later */
        uintptr_t                                               systemOrderFlag;
        /* the following field is only in version 8 (Mac OS X 10.7, iPhoneOS 3.1) and later */
        uintptr_t                                               uuidArrayCount;
        const struct dyld_uuid_info*    uuidArray;              /* only images not in dyld shared cache */
        /* the following field is only in version 9 (Mac OS X 10.7, iOS 4.0) and later */
        struct dyld_all_image_infos*    dyldAllImageInfosAddress;
        /* the following field is only in version 10 (Mac OS X 10.7, iOS 4.2) and later */
        uintptr_t                                               initialImageCount;
        /* the following field is only in version 11 (Mac OS X 10.7, iOS 4.2) and later */
        uintptr_t                                               errorKind;
        const char*                                             errorClientOfDylibPath;
        const char*                                             errorTargetDylibPath;
        const char*                                             errorSymbol;
        /* the following field is only in version 12 (Mac OS X 10.7, iOS 4.3) and later */
        uintptr_t                                               sharedCacheSlide;
        /* the following field is only in version 13 (Mac OS X 10.9, iOS 7.0) and later */
        uint8_t                                                 sharedCacheUUID[16];
        /* the following field is only in version 14 (Mac OS X 10.9, iOS 7.0) and later */
        uintptr_t                                               reserved[16];
};

The field you need is the infoArray, which points to

struct dyld_image_info {
        const struct mach_header*       imageLoadAddress;       /* base address image is mapped into */
        const char*                                     imageFilePath;          /* path dyld used to load the image */
        uintptr_t                                       imageFileModDate;       /* time_t of image file */
0
Jim Ingham On

This is not entirely trivial to do, but the code in sources/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDyld.cpp is the code that does this (and a few other things) in lldb. You might also want to take a look at /usr/include/mach-o/loader.h.