mach-o结构分为三部分
header,LoadCommands,Section64
LoadCommands结构
1,获取文件中的header内容
mach_header_64 mhHeader;
[fileData getBytes:&mhHeader range:NSMakeRange(0, sizeof(mach_header_64))];
2,获取文件中的load_command
unsigned long long currentLcLocation = sizeof(mach_header_64);//通过地址偏移获取第一个Load_command
load_command* cmd = (load_command *)malloc(sizeof(load_command));
[fileData getBytes:cmd range:NSMakeRange(currentLcLocation, sizeof(load_command))];
//根据cmd找到对应的segment
cmd->cmd == LC_SEGMENT_64
3,找到segment_command_64
segment_command_64 segmentCommand;
[fileData getBytes:&segmentCommand range:NSMakeRange(currentLcLocation, sizeof(segment_command_64))];
4,获取section
unsigned long long currentSecLocation = currentLcLocation + sizeof(segment_command_64);//获取第一个section地址
section_64 sectionHeader;
[fileData getBytes:§ionHeader range:NSMakeRange(currentSecLocation, sizeof(section_64))];
NSString *secName = [[NSString alloc] initWithUTF8String:sectionHeader.sectname];//根据名字找到特定的section
nlist_64 nlist;
ptrdiff_t off = symTabCommand.symoff;
char * p = (char *)fileData.bytes;//指针地址
p = p+off;//加上偏移量可以找到对应的section
memcpy(&nlist, p, sizeof(nlist_64));
4,获取链接基地址
uintptr_t linkBase = linkEdit.vmaddr - linkEdit.fileoff;
//header结构
struct mach_header_64 {
uint32_t magic; /* mach magic number identifier */
cpu_type_t cputype; /* cpu specifier */
cpu_subtype_t cpusubtype; /* machine specifier */
uint32_t filetype; /* type of file */
uint32_t ncmds; /* number of load commands */
uint32_t sizeofcmds; /* the size of all the load commands */
uint32_t flags; /* flags */
uint32_t reserved; /* reserved */
};
//load_command 结构
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
//segment_command_64
struct segment_command_64 { /* for 64-bit architectures */
uint32_t cmd; /* LC_SEGMENT_64 */
uint32_t cmdsize; /* includes sizeof section_64 structs */
char segname[16]; /* segment name */
uint64_t vmaddr; /* memory address of this segment */
uint64_t vmsize; /* memory size of this segment */
uint64_t fileoff; /* file offset of this segment */
uint64_t filesize; /* amount to map from the file */
vm_prot_t maxprot; /* maximum VM protection */
vm_prot_t initprot; /* initial VM protection */
uint32_t nsects; /* number of sections in segment */
uint32_t flags; /* flags */
};
struct section_64 { /* for 64-bit architectures */
char sectname[16]; /* name of this section */
char segname[16]; /* segment this section goes in */
uint64_t addr; /* memory address of this section */
uint64_t size; /* size in bytes of this section */
uint32_t offset; /* file offset of this section */
uint32_t align; /* section alignment (power of 2) */
uint32_t reloff; /* file offset of relocation entries */
uint32_t nreloc; /* number of relocation entries */
uint32_t flags; /* flags (section type and attributes)*/
uint32_t reserved1; /* reserved (for offset or index) */
uint32_t reserved2; /* reserved (for count or sizeof) */
uint32_t reserved3; /* reserved */
};
struct symtab_command {
uint32_t cmd; /* LC_SYMTAB */
uint32_t cmdsize; /* sizeof(struct symtab_command) */
uint32_t symoff; /* symbol table offset */
uint32_t nsyms; /* number of symbol table entries */
uint32_t stroff; /* string table offset */
uint32_t strsize; /* string table size in bytes */
};
读取mach-o文件section方法
//方法一,知道偏移和长度,获取
nlist_64 symbol = {0};
NSData *symbolData = [WBBladesTool readBytes:range length:sizeof(nlist_64) fromFile:fileData];
[symbolData getBytes:&symbol range:NSMakeRange(0, sizeof(nlist_64))];
+ (NSData *)readBytes:(NSRange &)range length:(NSUInteger)length fromFile:(NSData *)fileData {
range = NSMakeRange(NSMaxRange(range), length);
uint8_t *buffer = (uint8_t *)malloc(length);
[fileData getBytes:buffer range:range];
NSData *ret = [NSData dataWithBytes:buffer length:length];
free (buffer);
return ret;
}
//方法二,获取bytes,和偏移量,获得指针
nlist_64 nlist;
ptrdiff_t off = symTabCommand.symoff;
char * p = (char *)fileData.bytes;//指针地址
p = p+off;//加上偏移量可以找到对应的section
memcpy(&nlist, p, sizeof(nlist_64));