How does __TEXT encode address in __DATA?

Session 406 of WWDC 2016 is great! It explains clearly how the iOS application is settled in memory before running, with ASLR and code-signing. The key point is the indirect pointers in __DATA avoided patching the __TEXT, which is required by ASLR but impossible because of code-signing.

There is this one point confusing me, __TEXT still needs to encode address pointing to __DATA segment, but __DATA page address is randomised now.

The answer is quite simple indeed: the offset between __TEXT and __DATA is not changing between runs, the offset is encoded in __TEXT.

In 64bit Mac OS X, it implements as:

movl 0xae(%rip), %edi

iOS ARMv7 generates:

0000bf9c f240037c movw r3, #0x7c
0000bfa0 f2c00300 movt r3, #0x0
0000bfa4 447b add r3, pc ;$pc(0xbfa8) + 0x7c -> global_var in __DATA

iOS ARMv8 (64) generates:

0000000100007f2c adrp x8, 1 ; 0x100007000 + 4k*1
0000000100007f30 add x8, x8, #64 ; +0x40 -> 0x100008040
;-> global_var in __DATA
* adrp xd label  mask out lower 12bits of pc then add label<<12 to generate an address.