iOS底层原理:PAGEZERO的作用

1. Page Zero的作用

Making a big __PAGEZERO in a 64-bit architecture makes a whole lot of sense. The address range of a 64-bit system, even when the upper 16 bits are "cropped off" like that of x86_64, allows for a huge amount of memory (the 48-bit address space of x86_64 is 256TB of memory address space). It is highly likely that this will be thought of as "small" at some point in the future, but right now, the biggest servers have 1-4TB, so there's plenty of room to grow, and more ordinary machines have 16-32GB.

Note also that no memory is actually OCCUPIED. It's just "reserved virtual space" (that is, "it will never be used"). It takes up absolutely zero resources, because it's not mapped in the page-table, it's not there physically. It's just an entry in the file, which tells the loader to reserve this space to it can never be used, and thus "safeguarded". The actual "data" of this section is zero in size, since, again, there's actually nothing there, just a "make sure this is not used". So your actual file size won't be any larger or smaller if this section is changed in size. It would be a few bytes smaller (the size of the section description) if it didn't exist at all. But that's really the only what it would make any difference at all.

The purpose of a __PAGEZERO is to catch NULL pointer dereferences. By reserving a large section of memory at the beginning of memory, any access through a NULL pointer will be caught and the application aborted. In a 32-bit architecture, something like:

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

is likely to succeed, because at 0x400000 (4MB) the code-space starts (trying to write to such a location is likely to crash, but reading will work - assuming of course the code-space actually starts there and not someplace else in the address range.

Edit:

This presentation shows that ARM, the latest entrant into the 64-bit processor sapce, is also using 48-bit virtual address space, and enforces canonical addresses (top 16 bits need to all be the same value) so it can be expanded in the future. In other words, the virtual space available on a 64-bit ARM processor is also 256TB.

In addition to catching NULL dereferences, using a size of 0x100000000 in 64-bit means that no 32-bit pointer is valid. This helps catch buggy software that has been compiled for 64-bit but is not 64-bit safe. For example, it copies a pointer to an int and then back to a pointer variable, truncating it.

2. 翻译

让 64 位架构中的 __PAGEZERO 尽可能大有许多意义:

首先,64 系统下,地址够用。虽然很多 64 位架构和 x86_64 架构一样,将 64 中的高 16 位剪掉了,但是仍然有 48 位可以用来表示地址。48 位意味着 256TB 的大小,而如今服务器最大的内存大概是 1-4TB,一般机器的内存时 16-32GB,所以 256TB 在很长一段时间内具备增长的空间,即:够用!

另外,__PAGEZERO 所指代的内存并没有真正被分配(或占用)。首先,在文件在硬盘上时,__PAGEZERO 的 filesize 为 0,即不分配硬盘空间。再者,mach-O 是被加载进入虚拟内存而不是物理内存,物理内存的使用需要通过 MMU 进行印射。因此,__PAGEZERO 占用的虚拟内存在物理内存中并没有被分配。如果程序访问该段内存,肯定会直接被系统拦截,报出 BAD_ACCESS 的错误,即:

  1. 存储在硬盘上时,不占用硬盘空间;
  2. 被加载进入虚拟内存时,不会分配真实的物理内存;
  3. 只是起到一个作用:告诉加载者(进程)分配固定虚拟内存,告诉使用者这段虚拟内存不能使用;

至此,__PAGEZERO 的使用方式了解了,但是 __PAGEZERO 这段的具体作用是什么?

  1. 拦截空指针的异常访问;

如下图,在 macOS 中测试,来看一个空指针异常的正常流程:

空指针访问

如上图,0x80000000__PAGEZERO 段内,访问时直接报错;

再来看一个特殊情况:

pagezero

结果就是 p 虽然是空指针,但是依然访问成功了。其本质就是访问元素类型为 char 的数组中的第 0x100000000 个元素。因为 0x100000000 超出了 __PAGEZERO 的范围(这里使用0x100000000 会更清晰),所以虚拟内存校验通过,会去取真实的物理内存中的数据,即取到了 mach-O header 中的第一个字节;

这里 read 是可以的 write 是不行的。write 的限制很多,如类型判断,起始位置判断等等,read 可能只需要判断该虚拟空间是否有印射到真实的物理内存中;

其实这个测试也可以在 ARM64 的 iphone 上验证,只不过 iOS 中有 Slide,所以需要用 expression 来实时赋值:

iOS中的PageZero

直接访问 0x100000000 会报错,因为 Slide 的原因,该内存未被分配物理内存,也会报 Bad Access;所以这里感觉可以验证指针访问的内存如果没有印射到物理内存的话,实际是会报错的,即:指针访问的有效内存都是已经 Page In 过的,否则就会 Bad Access;

至此,可以做出总结:

__PAGEZERO 的目的就是为了拦截空指针的访问,因此这个地址越大,其有效性就越高;

另外,__PAGEZERO 还有一个作用:

  1. 隔绝 32 位系统的程序

__PAGEZERO 设置成 4GB 的另外一个原因是为了隔绝 32 位系统,比如指针小于 4GB 时,那这大概率是一个 32 位系统的指针,那么指向了 __PAGEZERO 就会直接报错。这就意味着 arm64 架构不支持 32 位的软件了;

总结:

  1. PAGEZERO 在 iOS 中大小为 4GB;
  2. iOS 中源码体现的虚拟内存最大为 64GB ,比 PAGEZERO 多一个比特位(0x10|0000|0000);
  3. arm64 使用 48 位做内存地址,虚拟内存最大可以是 256TB;
  4. PAGEZERO 的目的之一是为了捕获空指针的访问;
  5. PAGEZERO 的目的之二是为了隔绝 32 程序的运行;

3. 为什么64位系统的高16 位会被剪掉

32 位系统最大 CPU 最大寻址能力是 4GB,这已经有点不够用了,64位架构应运而生。

首先,64位系统的寻址能力是这么大:

64位地址范围

但是当前的电脑内存一般是 16~32GB,手机一般 2~16GB,所以使用 64位来寻址会造成:

  1. 硬件设计更复杂;
  2. 性价比不高;

虽然有些架构确实采用了 64 位寻址地址来进行设计和实现,如 SPARC 的 64 位版就允许完整的 64 位寻址空间,AArch64 允许用高 8 位来做tag,那么还有56 位寻址空间~~

但是主流的 64 位架构都是使用 48 位地址进行寻址,高 16 位做保留,这样做有几个好处:

  1. 性价比高;
  2. 以后逐步放开高 16 位即可兼容;
  3. 寻址设计相对简单(如 Page Table 的设计);

因此,48 位寻址的架构,其地址的范围就是 0~256TB,这在一段时间内已经很够用了。

另外需要注意一点:

  • 高16位必须是全1或全0,而且必须与低48位的最高位(第47位)一致;

设计为带符号扩展的原因也很简单:很多环境中,寻址空间的高一半(higher-half)有特殊用途,而低一半(lower-half)给用户做一般用途。这“高/低”可以通过最高位是1还是0来判断;如果把地址看成带符号整数,那么“负数”部分就是高一半,“正数”部分就是低一半。

维基百科:


维基百科
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容