2011-04-06 44 views
5

Kilitlenme günlüğü, mimariyle (armv6/armv7) ve yüklü tüm modüllerin tanımlayıcısına ilişkin bilgileri içeren "Binary Images" bölümünü içerir. Çalışma zamanında bu bilgileri nasıl belirleyebilirim? (en azından, yalnızca uygulama yürütülebilir)
NSBundle, çalıştırılabilir bir programa sahiptir, ancak hangi mimarinin çalıştığını nasıl belirleriz?Çalışma zamanında ikili görüntü mimarisi nasıl belirlenir?

cevap

14

Uzun cevap için tam zamanı. Uygulamadaki dyld görüntülerinin makine başlıkları, aradığınız bilgileri içerir. Sadece çalışmam için test ettiğim bir örnek ekledim ve bu yüzden doğrudan üretim koduna yapıştırmanızı önermem. Bu, yüklü olan tüm dyld görüntüleri için tüm mach başlıklarını alır ve kilitlenme günlüğünün İkili Resimler bölümüne çok benzer bir çıktıyı yazdırır. Aradığım yöntemler iş parçacığı güvenli değil. Kaybettiğim tek şey, ikili imajın son adresiydi, çünkü onu nasıl bulacağımı düşünmüyorum.

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

Örnek çıkışı:

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

CPU_SUBTYPE_ARM_V6 gibi cevap için teşekkür ederiz! Uygulama mimarisi için sadece CPU mimarisine ihtiyaç duyduğumdan, dladdr (this_function) ve sonra Dl_info.dli_fbase öğesini struct mach_header öğesine bir işaretçi olarak kullandım. – michelnok

+0

@Joe, _mh_execute_header'dan (neredeyse aynı şekilde) bundle uuid'in Appstore binary'de çalışıp çalışmayacağını biliyor musunuz? Hem geliştirici hem de geçici yapımlarda çalışır, ancak emin olmak isterim. – Tertium

+0

@Tertium Bu işlevin nerede bulunduğundan emin değilim, ancak özel bir çerçevenin parçasıysa, buna izin verilmeyecektir. – Joe

2

Uygulamanızı oluşturduğunuzdan beri mimariyle ilgili hızlı bir yanıt için, uygulamanızın oluşturulduğu geçerli mimariyi belirlemek üzere bazı önişlemci tanımlarını kontrol edebilirsiniz. Her yeni sürüm daha eski sürümleri tanımladığından, ilk olarak en yüksek kol sürümüne sahip olduğunuzdan emin olun.

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

#ifdef __ARM_ARCH_6K__ 
//This is armv6 
#endif //__ARM_ARCH_6K__ 
#endif //__arm__ 
0

Biz almak veya set sistem bilgileri için sysctl, sysctlbyname sistem çağrısını kullanabilirsiniz.

örnek kod:

#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 
} 
Sadece daha detial elde etmek için "hw.cpusubtype" için 2016 Look en yaygın kemer listelemek

, CPU_SUBTYPE_ARM_V7CPU_SUBTYPE_ARM_V7S

+0

Bu, ikili modülün derlendiği mimariyle ilgili olduğunda, cihazın CPU tipini döndürür. Yani, Joe'nun cevabı doğruydu. – michelnok

İlgili konular