iphoneioscpu-architecturearmv7armv6

How to determine binary image architecture at runtime?


Crash log contains "Binary Images" section with information about architecture (armv6/armv7) and identifier of all loaded modules. How to determine this information at runtime? (at least, just for application executable)
NSBundle has method executableArchitectures, but how to determine which architecture is running?


Solution

  • Alright time for the long answer. The mach headers of the dyld images in the application contain the information you are looking for. I have added an example that I only tested to work and nothing else so I would not recommend pasting it directly into production code. What it does it get all of the mach headers for all of the currently loaded dyld images and prints an output very similar to the Binary Images section of the crash log. The methods I call are not thread safe. The one thing I am missing is the end address to the binary image because I did not bother looking up how to find that.

    Main.m

    #import <UIKit/UIKit.h>
    
    #include <string.h>
    #import <mach-o/loader.h>
    #import <mach-o/dyld.h>
    #import <mach-o/arch.h>
    
    void printImage(const struct mach_header *header)
    {
        uint8_t *header_ptr = (uint8_t*)header;
        typedef struct load_command load_command;
    
        const NXArchInfo *info = NXGetArchInfoFromCpuType(header->cputype, header->cpusubtype);
    
        //Print the architecture ex. armv7
        printf("%s ", info->name);
    
        header_ptr += sizeof(struct mach_header);
        load_command *command = (load_command*)header_ptr;
    
        for(int i = 0; i < header->ncmds > 0; ++i)
        {
            if(command->cmd == LC_UUID)
            {
                struct uuid_command ucmd = *(struct uuid_command*)header_ptr;
    
                CFUUIDRef cuuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *((CFUUIDBytes*)ucmd.uuid));
                CFStringRef suuid = CFUUIDCreateString(kCFAllocatorDefault, cuuid);
                CFStringEncoding encoding = CFStringGetFastestEncoding(suuid);
    
                //Print UUID
                printf("<%s> ", CFStringGetCStringPtr(suuid, encoding));
    
                CFRelease(cuuid);
                CFRelease(suuid);
    
                break;
            }
    
            header_ptr += command->cmdsize;
            command = (load_command*)header_ptr;
        }
    }
    
    void printBinaryImages()
    {
        printf("Binary Images:\n");
        //Get count of all currently loaded DYLD
        uint32_t count = _dyld_image_count();
    
        for(uint32_t i = 0; i < count; i++)
        {
            //Name of image (includes full path)
            const char *dyld = _dyld_get_image_name(i);
    
            //Get name of file
            int slength = strlen(dyld);
    
            int j;
            for(j = slength - 1; j>= 0; --j)
                if(dyld[j] == '/') break;
    
            //strndup only available in iOS 4.3
            char *name = strndup(dyld + ++j, slength - j);
            printf("%s ", name);
            free(name);
    
            const struct mach_header *header = _dyld_get_image_header(i);
            //print address range
            printf("0x%X - ??? ", (uint32_t)header);
    
            printImage(header);
    
            //print file path
            printf("%s\n",  dyld);
        }
        printf("\n");
    }
    
    int main(int argc, char *argv[])
    {        
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        printBinaryImages();
        [pool release];
        return retVal;
    }
    

    Example output:

    Binary Images:
    TestBed 0x1000 - ??? i386 <E96D079C-E035-389D-AA12-71E968C76BFE> /Users/username/Library/Application Support/iPhone Simulator/4.3/Applications/6F64D9F8-9179-4E21-AE32-4D4604BE77E5/TestBed.app/TestBed
    UIKit 0x8000 - ??? i386 <72030911-362F-3E47-BAF3-ACD2CB6F88C0> /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/UIKit.framework/UIKit
    Foundation 0x772000 - ??? i386 <EB718CBD-1D57-3D31-898D-7CFA9C172A46> /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/Foundation.framework/Foundation
    CoreGraphics 0xA10000 - ??? i386 <D168A716-71F2-337A-AE0B-9DCF51AE9181> /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
    libSystem.dylib 0xCAA000 - ??? i386 <8DF0AFCD-FFA5-3049-88E2-7410F8398749> /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/lib/libSystem.dylib
    ...