Как определить архитектуру двоичного образа во время выполнения? - PullRequest
5 голосов
/ 06 апреля 2011

Журнал сбоев содержит раздел «Двоичные изображения» с информацией об архитектуре (armv6 / armv7) и идентификатором всех загруженных модулей.Как определить эту информацию во время выполнения?(по крайней мере, только для исполняемого файла приложения)
NSBundle имеет метод executetableArchitectures, но как определить, какая архитектура работает?

Ответы [ 3 ]

14 голосов
/ 08 апреля 2011

Хорошо время для длинного ответа. Заголовки mach изображений dyld в приложении содержат информацию, которую вы ищете. Я добавил пример, который я тестировал только для работы и ничего больше, поэтому я бы не рекомендовал вставлять его непосредственно в рабочий код. Для чего он получает все заголовки mach для всех загруженных в настоящее время изображений dyld и печатает вывод, очень похожий на раздел Binary Images в журнале сбоев. Методы, которые я вызываю, не являются потокобезопасными. Единственное, чего мне не хватает, это конечного адреса двоичного изображения, потому что я не стал искать, как его найти.

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;
}

Пример вывода:

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
...
2 голосов
/ 07 апреля 2011

Чтобы получить быстрый ответ об одной только архитектуре, поскольку вы создаете свое приложение, вы можете проверить некоторые определения препроцессора, чтобы определить текущую архитектуру, для которой создано ваше приложение.Сначала убедитесь, что вы установили самую высокую версию оружия, доступную в первую очередь, поскольку каждая более новая версия определяет все более старые версии.

#if __arm__
#import <arm/arch.h>

#ifdef __ARM_ARCH_6K__
//This is armv6
#endif //__ARM_ARCH_6K__
#endif //__arm__
0 голосов
/ 20 апреля 2016

Мы можем использовать системный вызов sysctl, sysctlbyname для получения или установки системной информации.

Пример кода:

#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
}

Я просто перечислю наиболее распространенную арку в 2016 году. Ищите «hw.cpusubtype ", чтобы получить больше detial, как CPU_SUBTYPE_ARM_V6 CPU_SUBTYPE_ARM_V7 CPU_SUBTYPE_ARM_V7S

...