Iphone 如何在运行时确定二进制映像体系结构?

Iphone 如何在运行时确定二进制映像体系结构?,iphone,ios,cpu-architecture,armv7,armv6,Iphone,Ios,Cpu Architecture,Armv7,Armv6,崩溃日志包含“二进制映像”部分,其中包含有关体系结构(armv6/armv7)和所有加载模块的标识符的信息。如何在运行时确定此信息?(至少,仅适用于应用程序可执行文件) NSBundle有方法ExecutableArchitecture,但如何确定正在运行的体系结构?由于您正在构建应用程序,因此您可以查看一些预处理器定义,以确定构建应用程序的当前体系结构。确保首先检查可用的arm的最高版本,因为每个较新版本定义了所有较旧版本 #if __arm__ #import <arm/arch.h&

崩溃日志包含“二进制映像”部分,其中包含有关体系结构(armv6/armv7)和所有加载模块的标识符的信息。如何在运行时确定此信息?(至少,仅适用于应用程序可执行文件)

NSBundle有方法ExecutableArchitecture,但如何确定正在运行的体系结构?

由于您正在构建应用程序,因此您可以查看一些预处理器定义,以确定构建应用程序的当前体系结构。确保首先检查可用的arm的最高版本,因为每个较新版本定义了所有较旧版本

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

#ifdef __ARM_ARCH_6K__
//This is armv6
#endif //__ARM_ARCH_6K__
#endif //__arm__
#如果#__
#进口
#ifdef uu臂u拱u 6K__
//这是armv6
#endif/______拱_6K__
#endif/\uu臂__

好了,是时候给出长答案了。应用程序中dyld图像的马赫头包含您要查找的信息。我添加了一个示例,我只测试了它的工作性能,没有其他功能,因此我不建议将其直接粘贴到生产代码中。它所做的是获取当前加载的所有dyld图像的所有马赫头,并打印一个与崩溃日志的二进制图像部分非常相似的输出。我调用的方法不是线程安全的。我缺少的一件事是二进制图像的结束地址,因为我没有费心查找如何找到它

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;
}
#导入
#包括
#进口
#进口
#进口
无效打印图像(常量结构马赫数页眉*页眉)
{
uint8_t*头文件_ptr=(uint8_t*)头文件;
类型定义结构加载命令加载命令;
const nxarcinfo*info=nxGetArchinformCPUType(header->cputype,header->cpusubtype);
//打印架构,例如armv7
printf(“%s”,信息->名称);
收割台ptr+=sizeof(结构马赫数收割台);
加载命令*命令=(加载命令*)标题\u ptr;
对于(int i=0;incmds>0;++i)
{
如果(命令->命令==LC_UUID)
{
结构uuid_命令ucmd=*(结构uuid_命令*)头\u ptr;
CFUUIDRef cuuid=CFUUIDCreateFromUUIDBytes(kFallocatorDefault,*((CFUUIDBytes*)ucmd.uuid));
CFStringRef suuid=CFUUIDCreateString(kCFAllocatorDefault,cuuid);
CFStringEncoding=cfStringGetFastTestEncoding(suuid);
//打印UUID
printf(“,CFStringGetCStringPtr(suuid,encoding));
cfd释放(cuuid);
CFRelease(suuid);
打破
}
标头_ptr+=命令->cmdsize;
command=(load_command*)头文件\u ptr;
}
}
作废printBinaryImages()
{
printf(“二进制图像:\n”);
//获取当前加载的所有DYLD的计数
uint32_t count=_dyld_image_count();
对于(uint32_t i=0;i=0;--j)
如果(dyld[j]=='/')中断;
//strndup仅在iOS 4.3中可用
char*name=strndup(dyld+++j,slength-j);
printf(“%s”,名称);
免费(姓名);
const struct mach_header*header=\u dyld\u get\u image\u header(i);
//打印地址范围
printf(“0x%X-?”,(uint32_t)标题);
打印图像(标题);
//打印文件路径
printf(“%s\n”,dyld);
}
printf(“\n”);
}
int main(int argc,char*argv[])
{        
NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init];
printBinaryImages();
[池释放];
返回返回;
}
示例输出:

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
...
二进制图像:
试验台0x1000-???i386/Users/username/Library/Application Support/iPhone Simulator/4.3/Applications/6F64D9F8-9179-4E21-AE32-4D4604BE77E5/TestBed.app/TestBed
UIKit 0x8000-???i386/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/UIKit.framework/UIKit
基金会0x77 2000????i386/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/Foundation.framework/Foundation
CoreGraphics 0xA10000-???i386/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
libSystem.dylib 0xCAA000-???i386/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.3.sdk/usr/lib/libSystem.dylib
...

我们可以使用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
}
#导入
#进口
int32_t值=0;
尺寸长度=sizeof(值);
sysctlbyname(“hw.cputype”、&value、&length,NULL,0);
如果(值==CPU\U类型\U ARM64){
//arm64
}
else if(值==CPU\U类型\U ARM){
//armv7/armv7s
}
else if(值==CPU\U类型\U X86){
//模拟机
}

我只是列出了2016年最常见的拱门。查找“hw.cpusubtype”以获得更多详细信息,如
CPU\u SUBTYPE\u ARM\u V6
CPU\u SUBTYPE\u ARM\u V7
CPU\u SUBTYPE\u ARM\u V7S

谢谢您的回答!由于我只需要CPU体系结构来执行应用程序的可执行文件,所以我使用了dladdr(此函数),然后使用Dl_info.dli_fbase作为指向struct mach_头的指针。@Joe,你知道从_mh_execute_头获取bundle uuid(几乎相同的方式)是否可以在Appstore二进制文件中工作吗?它在开发人员和特别构建中都能工作,但我想确定。@Tertium我不确定该函数位于何处,但如果它是私有框架的一部分,则不允许使用。@Joe mh_execute_header不是函数,它是应用程序映像的mach_header。我的捆绑包已使用Organizer->Archives->Validate成功验证,因此我认为这并不是禁止的。但我想确定的是,你会得到。。。函数工作,mach_头在为appstore编译的包中包含uuid信息,就像在开发/特殊构建中一样。@Tertium我不相信