Search code examples
iosc++11objective-c++mach-o

Detect if code is in a Framework vs. App vs. Bundle


Is there a way to detect if the code being compiled is in a Framework, a Bundle, or a Dynamic Library?

The reason is because of a crash reporter library that needs to know if a struct variable exists before taking the address of it..

IE:

#ifdef MH_EXECUTE_SYM
return (uint8_t*)&_mh_execute_header;
#else
return (uint8_t*)&_mh_dylib_header;
#endif

The problem is that MH_EXECUTE_SYM, MH_BUNDLE_SYM, MH_DYLIB_SYM is always defined for every kind of executable, bundle, framework..

So I need a way of determining which struct variable to take the address of.. Any ideas?


Solution

  • It looks like you really just want to get a pointer to the appropriate mach_header_64 (or mach_header on 32-bit systems).

    If you have a pointer, you can use the dladdr function to find out which (if any) mach-o it was loaded from. That function fills in a Dl_info structure which includes, amongst other things, a pointer to the mach_header_64 for the mach-o.

    // For TARGET_RT_64_BIT:
    #import <TargetConditionals.h>
    
    // For dladdr:
    #import <dlfcn.h>
    
    // For mach_header and mach_header_64:
    #import <mach-o/loader.h>
    
    #ifdef TARGET_RT_64_BIT
    
    struct mach_header_64 *mach_header_for_address(const void *address) {
        Dl_info info;
        if (dladdr(address, &info) == 0) {
            // address doesn't point into a mach-o.
            return 0;
        }
        struct mach_header_64 *header = (struct mach_header_64 *)info.dli_fbase;
        if (header->magic != MH_MAGIC_64) {
            // Something went wrong...
            return 0;
        }
    
        return header;
    }
    
    #else
    
    struct mach_header mach_header_for_address(const void *address) {
        Dl_info info;
        if (dladdr(address, &info) == 0) {
            // address doesn't point into a mach-o.
            return 0;
        }
        struct mach_header *header = (struct mach_header *)info.dli_fbase;
        if (header->magic != MH_MAGIC) {
            // Something went wrong...
            return 0;
        }
    
        return header;
    }
    
    #endif