How to determine binary image architecture at runtime?

前端 未结 3 1149
北荒
北荒 2020-12-29 00:43

Crash log contains \"Binary Images\" section with information about architecture (armv6/armv7) and identifier of all loaded modules. How to determine this information at run

相关标签:
3条回答
  • 2020-12-29 01:32

    For a quick answer about architecture alone since you are building your application you can check some preprocessor defines to determine the current architecture that your application is built for. Make sure you check for the highest version of arm available first because each newer version defines all older versions.

    #if __arm__
    #import <arm/arch.h>
    
    #ifdef __ARM_ARCH_6K__
    //This is armv6
    #endif //__ARM_ARCH_6K__
    #endif //__arm__
    
    0 讨论(0)
  • 2020-12-29 01:34

    We can use sysctl, sysctlbyname system call to get or set system information.

    Sample code:

    #import <sys/sysctl.h>
    #import <mach/machine.h>
    
    int32_t value = 0;
    size_t length = sizeof(value);
    sysctlbyname("hw.cputype", &value, &length, NULL, 0);
    
    if (value == CPU_TYPE_ARM64) {
        // arm64
    }
    else if (value == CPU_TYPE_ARM) {
        // armv7/armv7s
    }
    else if (value == CPU_TYPE_X86) {
        // simulator
    }
    

    I just list most common arch at 2016. Look for "hw.cpusubtype" to get more detial, like CPU_SUBTYPE_ARM_V6 CPU_SUBTYPE_ARM_V7 CPU_SUBTYPE_ARM_V7S

    0 讨论(0)
  • 2020-12-29 01:35

    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
    ...
    
    0 讨论(0)
提交回复
热议问题