コマンドotool
あなたは(1)埋め込みplistの収容部の内容をダンプするコマンドotool使用できる:
otool -s __TEXT __info_plist /path/to/executable
、次いでパイプその出力がxxdのために(1)を得るために対応するASCII表現:
otool -X -s __TEXT __info_plist /path/to/executable | xxd -r
ただし、otool is only available in machines where Xcode has been installedです。 NSBundleを使用することができるプログラムは、独自の埋め込みプロパティリストを読み取る必要がある場合、について
NSBundle
:
id someValue = [[NSBundle mainBundle] objectForInfoDictionaryKey:someKey];
マッハO
プログラムをする必要がある場合についてotoolに依存せずに任意のファイルの埋め込みplistを読み込むと、プログラムはファイル内のMach-O情報を解析し、埋め込みplistを以下のように抽出することができます:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <mach-o/loader.h>
#include <sys/mman.h>
#include <sys/stat.h>
#import <Foundation/Foundation.h>
id embeddedPlist(NSURL *executableURL) {
id plist = nil;
int fd;
struct stat stat_buf;
size_t size;
char *addr = NULL;
char *start_addr = NULL;
struct mach_header_64 *mh = NULL;
struct load_command *lc = NULL;
struct segment_command_64 *sc = NULL;
struct section_64 *sect = NULL;
// Open the file and get its size
fd = open([[executableURL path] UTF8String], O_RDONLY);
if (fd == -1) goto END_FUNCTION;
if (fstat(fd, &stat_buf) == -1) goto END_FILE;
size = stat_buf.st_size;
// Map the file to memory
addr = start_addr = mmap(0, size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) goto END_FILE;
// The first bytes are the Mach-O header
mh = (struct mach_header_64 *)addr;
// Load commands follow the header
addr += sizeof(struct mach_header_64);
for (int icmd = 0; icmd < mh->ncmds; icmd++) {
lc = (struct load_command *)addr;
if (lc->cmd != LC_SEGMENT_64) {
addr += lc->cmdsize;
continue;
}
if (lc->cmdsize == 0) continue;
// It's a 64-bit segment
sc = (struct segment_command_64 *)addr;
if (strcmp("__TEXT", sc->segname) != 0 || sc->nsects == 0) {
addr += lc->cmdsize;
continue;
}
// It's the __TEXT segment and it has at least one section
// Section data follows segment data
addr += sizeof(struct segment_command_64);
for (int isect = 0; isect < sc->nsects; isect++) {
sect = (struct section_64 *)addr;
addr += sizeof(struct section_64);
if (strcmp("__info_plist", sect->sectname) != 0) continue;
// It's the __TEXT __info_plist section
NSData *data = [NSData dataWithBytes:(start_addr + sect->offset)
length:sect->size];
plist = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:NULL
error:NULL];
goto END_MMAP;
}
}
END_MMAP:
munmap(addr, size);
END_FILE:
close(fd);
END_FUNCTION:
return plist;
}
と:それは、ファイルが薄いマッハ-Oファイルであることを期待(すなわち、それは非マッハ-Oファイルでクラッシュすると、それはないでしょう:embeddedPlist()
はいくつかの制限があることを
NSURL *url = [NSURL fileURLWithPath:@"/path/to/some/file"];
id plist = embeddedPlist(url);
if ([plist isKindOfClass:[NSDictionary class]]) {
NSDictionary *info = plist;
id someValue = [info objectForKey:someKey];
}
注意たとえば、i386とx86_64の両方のMach-Oデータを含むfatファイルで作業します。 x86_64ファイルでのみ動作します。エラーを報告しません。
私はMITライセンスでBVPlistExtractorをリリースしました。ファイルが本当に薄いMach-Oファイルかfat/universalファイルかを検出し、i386とx86_64の両方で動作します。
は、私は[BVPlistExtractor](https://github.com/bavarious/BVPlistExtractor)をリリースしました。 –
@Bavariousありがとう! BVPlistExtractorは完璧です。 – ETroll