Skip to content

True segment bounds not visible in Dyld cache #26090

Description

@jonpalmisc

Environment

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions