#26090·radare2

True segment bounds not visible in Dyld cache

Author: jonpalmiscCreated Jun 11, 2026Updated Jun 12, 2026

Environment

bash
Fri Jun 12 09:17:26 AEST 2026
radare2 6.1.7 +36062 abi:109 @ darwin-arm_64
birth: git.6.1.7 2026-06-11__10:44:32
commit: 5224c1d67858d909841d84c3e26772ce726785fc
options: gpl -O2 cs:5 cl:2 make
Darwin arm64

Description

Normally when looking at a Mach-O, I would use iSS to see the segment bounds:

$ r2 /bin/ls
[0x100000960]> iSS
nth paddr         size vaddr         vsize perm flags type name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00010000  0x8000 0x100000000  0x8000 -r-x 0x0   MAP  __TEXT
1   0x00018000  0x4000 0x100008000  0x4000 -rw- 0x0   MAP  __DATA_CONST
2   0x0001c000  0x4000 0x10000c000  0x4000 -rw- 0x0   MAP  __DATA
3   0x00020000  0x8000 0x100010000  0x8000 -r-- 0x0   MAP  __LINKEDIT

We can see that this info matches the load commands, which is what I want:

$ otool -l /bin/ls
...
Load command 1
      cmd LC_SEGMENT_64
  cmdsize 472
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x0000000000008000
  fileoff 0
 filesize 32768
  maxprot 0x00000005
 initprot 0x00000005
   nsects 5
    flags 0x0

However, when loading a Dyld cache, iSS only returns cache_map entries:

[0x180000000]> iSS
nth paddr              size vaddr             vsize perm flags type name
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000000      0xa0000 0x180000000     0xa0000 -r-x 0x0   MAP  cache_map.0
1   0x000a4000    0x7d34000 0x180400000   0x7d34000 -r-x 0x0   MAP  cache_map.1
2   0x07e18000      0x38000 0x188134000     0x38000 -r-x 0x0   MAP  cache_map.2
...

Using iS (sections) instead is insufficient, because the lowest (address) section inside of a segment is not necessarily the start of the segment:

40  0x1193c6610  0x3670bfc 0x2b0406610  0x3670bfc -r-x 0x0   ---- WebCore.framework/WebCore.0.__TEXT.__text
41  0x11ca37210     0x58f4 0x2b3a77210     0x58f4 -r-x 0x0   ---- WebCore.framework/WebCore.1.__TEXT.__objc_methlist
42  0x11ca3cb04     0x1284 0x2b3a7cb04     0x1284 -r-x 0x0   ---- WebCore.framework/WebCore.2.__TEXT.__getClass_cstr
43  0x11ca3dd88     0x75d7 0x2b3a7dd88     0x75d7 -r-x 0x0   ---- WebCore.framework/WebCore.3.__TEXT.__dlsym_cstr

If we split this library out of the shared cache and then open it, we can see the true segment bounds:

[0x2b0406610]> iSS
nth paddr            size vaddr            vsize perm flags type name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000000  0x3c3a278 0x2b0404000  0x3c3a278 -r-x 0x0   MAP  __TEXT

It would be great if the Dyld cache loader could retain the segment bounds info of the images inside the cache so that it can be looked up.