fishhook源码问题

fishhook的源码中有如下代码:

//找到__LINKEDIT的基地址
uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;
//找到符号表的地址
nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff);
//找到字符串表的地址
char *strtab = (char *)(linkedit_base + symtab_cmd->stroff);
//indirect symbol table
uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff);

对linkedit_base有点不理解:

  1. 这个值不就是header的内存地址吗?也就是MachO文件映射到内存后,文件开头位置0x0对应到内存的位置值

  2. MachO文件映射到内存后占用的内存大小就是MachO文件的大小吗?

  3. 看到有说VM大小应该是大于等于文件大小的,如果是这样,那计算符号表地址的时候是linkedit_base + symtab_cmd->symoff, symtab_cmd->symoff 的意思应该是符号表的位置相对于文件开头0x0的偏移量啊,感觉MachO文件里的各个地址应该是和内存里的地址一一对应才对啊

来个懂MachO的大佬说几句呀

映射是分段的 不然ASLR就白ASLR了,而且会有问题,例如bss(未初始化堆)在文件里是0大小,但是映射到内存的时候要把这部分空出来,也就是macho装载到内存之后比文件大
符号在LINKEDIT段里面,所以先从文件的加载指令里面找到当前段相对于加载开始位置的偏移(linkedit_base)然后再从中找符号表

意思是符号表的这个偏移量(symtab_cmd->symoff)或者字符串表的偏移量(symtab_cmd->stroff)是相对于__LINKEDIT段的真实内存起始地址而言的?而不是相对于MachO文件的header内存地址而言的 是吧?

符号表偏移是相对于文件开始位置的,但是映射到内存的时候应该按照vm_off这个内存偏移来找。

这个linkedit_base,通过 加内存偏移 减文件偏移 相当于是把文件偏移转换成了内存偏移。所以可以直接拿任何属于__linkedit的文件偏移加到这个值上变成内存地址