mach_header 64bit和__PAGEZERO段64bit

时间:2014-04-20 22:37:27

标签: c++ ios objective-c c

const struct mach_header *mach = _dyld_get_image_header(0);
struct load_command *lc;
struct segment_command_64 *sc64;
struct segment_command *sc;

if (mach->magic == MH_MAGIC_64) {
    lc = (struct load_command *)((unsigned char *)mach + sizeof(struct mach_header_64));
    printf("[+] detected 64bit ARM binary in memory.\n");
} else {
    lc = (struct load_command *)((unsigned char *)mach + sizeof(struct mach_header));
    printf("[+] detected 32bit ARM binary in memory.\n");
}

for (int i = 0; i < mach->ncmds; i++) {

    if (lc->cmd == LC_SEGMENT) {
        sc = (struct segment_command *)lc;
        NSLog(@"32Bit: %s (%x - 0x%x)",sc->segname,sc->vmaddr,sc->vmsize);
    } else if (lc->cmd == LC_SEGMENT_64) {
        sc64 = (struct segment_command_64 *)lc;
        NSLog(@"64Bit: %s (%llx - 0x%llx)",sc64->segname,sc64->vmaddr,sc64->vmsize);
    }
    lc = (struct load_command *)((unsigned char *)lc+lc->cmdsize);
}

当我在32Bit中运行此代码时,我得到正常输出:

__PAGEZERO (0 - 0x1000) 
But on 64Bit: __PAGEZERO (0 - 0x100000000) 

__PAGEZERO goes from 0x1000 to over 0x100000000的大小,是否有任何解决方法或任何解决方案,为什么会发生这种情况?

1 个答案:

答案 0 :(得分:4)

在64位架构中创建一个大__PAGEZERO非常有意义。 64位系统的地址范围,即使高16位像x86_64那样“被裁掉”,也允许大量内存(x86_64的48位地址空间是256TB的内存地址空间)。很有可能在未来的某个时候将其视为“小”,但是现在,最大的服务器有1-4TB,因此有足够的发展空间,而更多的普通机器有16-32GB。

另请注意,实际上没有内存占用。它只是“保留虚拟空间”(即“永远不会被使用”)。它占用绝对零资源,因为它没有映射到页面表中,它不是物理上的。它只是文件中的一个条目,它告诉加载器保留这个空间,它永远不会被使用,因此“得到了保护”。这部分的实际“数据”大小为零,因为实际上没有任何东西,只是“确保不使用”。因此,如果更改此部分的大小,您的实际文件大小将不会更大或更小。如果它根本不存在,它将减少几个字节(部分描述的大小)。但这真的是唯一可以产生任何差异的东西。

__PAGEZERO的目的是捕获NULL指针取消引用。通过在内存开头保留大部分内存,将捕获通过NULL指针的任何访问并中止应用程序。在32位架构中,类似于:

int *p = NULL;
int x = p[0x100000]; 

可能会成功,因为在0x400000(4MB)处代码空间开始(尝试写入这样的位置可能会崩溃,但是读取会起作用 - 当然假设代码空间实际上是从那里开始而不是某个地方否则在地址范围内。

编辑:

This presentation表明ARM是64位处理器sapce的最新进入者,它也使用48位虚拟地址空间,并强制执行规范地址(前16位需要都是相同的值)所以它可以在未来扩展。换句话说,64位ARM处理器上可用的虚拟空间也是256TB。