如何在运行时确定二进制映像架构?

崩溃日志包含“二进制映像”部分,其中包含关于所有已加载模块的体系结构(armv6 / armv7)和标识符的信息。 如何在运行时确定这些信息? (至less,只适用于可执行的应用程序)
NSBundle有方法executableArchitectures,但如何确定哪个架构正在运行?

长时间的答案好的时候。 应用程序中的dyld图像的mach标题包含您正在查找的信息。 我添加了一个例子,我只testing工作,没有别的,所以我不会build议直接粘贴到生产代码。 它的function是获取所有当前加载的dyld映像的所有mach标题,并输出与崩溃日志的Binary Images部分非常相似的输出。 我所调用的方法不是线程安全的。 我缺less的一件事是二进制图像的结束地址,因为我没有打扰如何find。

的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 ... 

有关构build应用程序的简单答案,您可以检查一些预处理器定义来确定应用程序的当前体系结构。 请确保先检查可用的最高版本的arm,因为每个较新的版本都定义了所有旧版本。

 #if __arm__ #import <arm/arch.h> #ifdef __ARM_ARCH_6K__ //This is armv6 #endif //__ARM_ARCH_6K__ #endif //__arm__ 

我们可以使用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”以获得更多信息,如CPU_SUBTYPE_ARM_V6 CPU_SUBTYPE_ARM_V7 CPU_SUBTYPE_ARM_V7S