NAME=mach0 relocs apply keeps the load-time table, its flags and the slot writes
FILE=bins/mach0/FileDP
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF
ir~0x[0,1,2,3,4]
f~reloc.[0,2]
p8 4 @ 0x4074
p8 4 @ 0x4084
p8 4 @ 0x40a4
EOF
EXPECT=<<EOF
0x00000000 0x00000000 SET_32 6 NSAutoreleasePool
0x00003020 0x00002020 SET_32 6 exit
0x00003024 0x00002024 SET_32 6 NSFileProtectionKey
0x00003028 0x00002028 SET_32 6 NSLog
0x0000302c 0x0000202c SET_32 6 objc_enumerationMutation
0x00003030 0x00002030 SET_32 6 objc_msgSend
0x00003034 0x00002034 SET_32 6 puts
0x00003038 0x00002038 SET_32 6 strcmp
0x00006000 0x00000000 UNKNOWN 0 NSAutoreleasePool
0x00006004 0x00000000 UNKNOWN 0 NSFileManager
0x00006008 0x00000000 UNKNOWN 0 NSString
0x0000600c 0x00000000 UNKNOWN 0 __CFConstantStringClassReference
0x00003020 reloc.exit
0x00003024 reloc.NSFileProtectionKey
0x00003028 reloc.NSLog
0x0000302c reloc.objc_enumerationMutation
0x00003030 reloc.objc_msgSend
0x00003034 reloc.puts
0x00003038 reloc.strcmp
0x00006000 reloc.NSAutoreleasePool
0x00006004 reloc.NSFileManager
0x00006008 reloc.NSString
0x0000600c reloc.__CFConstantStringClassReference
00600000
0c604002
0c600000
EOF
RUN

NAME=mach0 relocs apply bin.limit truncates the combined table, slots first
FILE=bins/mach0/FileDP
ARGS=-e bin.relocs.apply=true -e bin.limit=8
CMDS=ir~0x[0,1,2,3,4]
EXPECT=<<EOF
0x00000000 0x00000000 SET_32 6 NSAutoreleasePool
0x00003020 0x00002020 SET_32 6 exit
0x00003024 0x00002024 SET_32 6 NSFileProtectionKey
0x00003028 0x00002028 SET_32 6 NSLog
0x00006030 0x00000000 UNKNOWN 0 NSAutoreleasePool
0x00006034 0x00000000 UNKNOWN 0 NSFileManager
0x00006038 0x00000000 UNKNOWN 0 NSString
0x0000603c 0x00000000 UNKNOWN 0 __CFConstantStringClassReference
EOF
RUN

NAME=mach0 relocs apply with no io bank
FILE=bins/mach0/FileDP
CMDS=<<EOF
omb-0
e bin.relocs.apply=true
ir~0x[0,1,2,3,4]
EOF
EXPECT=<<EOF
0x00000000 0x00000000 SET_32 6 NSAutoreleasePool
0x00003020 0x00002020 SET_32 6 exit
0x00003024 0x00002024 SET_32 6 NSFileProtectionKey
0x00003028 0x00002028 SET_32 6 NSLog
0x0000302c 0x0000202c SET_32 6 objc_enumerationMutation
0x00003030 0x00002030 SET_32 6 objc_msgSend
0x00003034 0x00002034 SET_32 6 puts
0x00003038 0x00002038 SET_32 6 strcmp
EOF
RUN

NAME=mach0 relocs apply is inert without external relocs
FILE=bins/mach0/ls-m1
ARGS=-a arm -b 64 -e bin.relocs.apply=true
CMDS=ir~?
EXPECT=<<EOF
201
EOF
RUN

NAME=mach0 relocs apply slot stride is a pointer on bits 16
FILE=malloc://18512
ARGS=-e bin.relocs.apply=true
CMDS=<<EOF
wff bins/mach0/FileDP
wx 0000000c @ 8
om 3 0x8000 0x10
oba 0
i~^bits
ir~UNKNOWN
EOF
EXPECT=<<EOF
bits     16
0x00007010 0x00000000 UNKNOWN 0     NSAutoreleasePool
0x00007014 0x00000000 UNKNOWN 0     NSFileManager
0x00007018 0x00000000 UNKNOWN 0     NSString
0x0000701c 0x00000000 UNKNOWN 0     __CFConstantStringClassReference
EOF
RUN


NAME=mach0 relocs apply closes .got.r2 when no external reloc is patched
FILE=malloc://0x1000
CMDS=<<EOF
wx cffaedfe0700000103000000020000000300000000010000
wx 19000000980000005f5f54455854 @ 0x20
wx 01000000001000000000000000000000000000000010000000000000070000000500000001 @ 0x3c
wx 5f5f74657874000000000000000000005f5f54455854 @ 0x68
wx 0004000001000000000100000000000000040000 @ 0x88
wx 0200000018000000000600000100000000070000100000000b00000050 @ 0xb8
wx 01 @ 0xec
wx 0008000001 @ 0x110
wx 0100000001 @ 0x600
wx 5f70757473 @ 0x701
wx 100400000000001e @ 0x800
om 3 0x100000000 0x1000
e bin.relocs.apply=true
oba 0
ir~puts
o~[0-1]
om~got.r2
EOF
EXPECT=<<EOF
3 *
EOF
RUN

NAME=mach0 chained fixups with 8 byte pages walk each pointer once
FILE=bins/mach0/chained-fixups-tiny-pages
TIMEOUT=10
CMDS=<<EOF
i~^format
ir~?
EOF
EXPECT=<<EOF
format   mach064
2050
EOF
RUN

NAME=mach0 repeated LC_DYLD_CHAINED_FIXUPS commands are parsed once
FILE=bins/mach0/chained-fixups-repeated-commands
TIMEOUT=10
CMDS=<<EOF
i~^format
ir~?
EOF
EXPECT=<<EOF
format   mach064
2
EOF
RUN

NAME=mach0 threaded bind chain applied many times is walked once
FILE=bins/mach0/threaded-bind-reapply
TIMEOUT=10
CMDS=<<EOF
ir~SET_64?
EOF
EXPECT=<<EOF
2000
EOF
RUN

NAME=mach0 __TEXT,__chain_starts arm64e kernel pointer chains are rebased
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 070000000100000000100000 @ 0x800
wx 00080000000010801000000000000000 @ 0x1000
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00001000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00001008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 __chain_starts file offsets when segment vm and file offsets differ
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000001000000000000000000000019000000480000005f5f444154415f434f4e53540000000000700027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 070000000100000000100000 @ 0x800
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00003000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00003008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 __chain_starts vm offsets when segment vm and file offsets differ
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000002000000000000000000000019000000480000005f5f444154415f434f4e53540000000000700027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 070000000100000000300000 @ 0x800
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00003000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00003008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 __chain_starts keeps every head on the same page
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff1000000000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 07000000020000000010000020100000 @ 0x800
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
wx 2000000000000000 @ 0x1020
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00001000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00001008 0x00001008 SET_64 0      - 0xfd8ffbff0
0x00001020 0x00001020 SET_64 0      - 0xfd8ffbfe0
EOF
RUN

NAME=mach0 __chain_starts chains cross segments
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 0700000001000000f80f0000 @ 0x800
wx 3000000000001000 @ 0xff8
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00000ff8 0x00000ff8 SET_64 0      - 0xfd8ffbfd0
0x00001000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00001008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 __chain_starts table larger than the file is rejected
FILE=malloc://8192
ARGS=-n -w
TIMEOUT=10
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0000004000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 07000000f0ffff0f00100000 @ 0x800
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
EOF
RUN

NAME=mach0 __chain_starts with an LC_DYLD_INFO_ONLY bind stream
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c00000102000080020000000300000010010000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000220000803000000000000000000000000009000001000000000000000000000000000000000000000000000000000000
wx 070000000100000000100000 @ 0x800
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00001000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00001008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 __chain_starts repeated heads are walked once
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff1000000000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 0700000002000000f80f0000f80f0000 @ 0x800
wx 3000000000001000 @ 0xff8
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
0x00000ff8 0x00000ff8 SET_64 0      - 0xfd8ffbfd0
0x00001000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00001008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 __chain_starts only takes DYLD_CHAINED_PTR_ARM64E_KERNEL
FILE=malloc://8192
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001020000800200000002000000e0000000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000000000000000000000000000019000000480000005f5f444154415f434f4e53540000000000500027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 050000000100000000100000 @ 0x800
wx 0008000000001080 @ 0x1000
wx 1000000000000000 @ 0x1008
oba 0
iI~^class
ir~SET_64
EOF
EXPECT=<<EOF
class    MACH064
EOF
RUN

NAME=mach0 chained fixups are listed and applied at their segment address
FILE=malloc://12288
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c00000102000080020000000300000028010000000020000000000019000000980000005f5f544558540000000000000000000000400027f0ffffff001000000000000000000000000000000010000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f544558540000000000000000000000480027f0ffffff0c00000000000000000800000200000000000000000000000000000001000000000000000000000019000000480000005f5f444154410000000000000000000000500027f0ffffff0010000000000000002000000000000000100000000000000300000003000000000000000000000019000000480000005f5f444154415f434f4e53540000000000600027f0ffffff00100000000000000010000000000000001000000000000003000000030000000000000000000000
wx 070000000100000000100000 @ 0x800
wx 00080000000010801000000000000000 @ 0x1000
wx 41414141414141414242424242424242 @ 0x2000
wtf .tmp_mach0_fixup_va.bin 12288
e bin.relocs.apply=true
o .tmp_mach0_fixup_va.bin
pxq 16 @ 0xfffffff027005000
pxq 16 @ 0xfffffff027006000
ir~SET_64
rm .tmp_mach0_fixup_va.bin
EOF
EXPECT=<<EOF
0xfffffff027005000  0x4141414141414141  0x4242424242424242   AAAAAAAABBBBBBBB
0xfffffff027006000  0xfffffff027004800  0xfffffff027004010   .H.'.....@.'....
0xfffffff027006000 0x00001000 SET_64 0      - 0xfd8ffb800
0xfffffff027006008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN

NAME=mach0 32-bit chained fixups patch only their own width
FILE=malloc://12288
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001000000000200000004000000e8000000000020000000000019000000480000005f5f54455854
wx 010000000010 @ 0x3c
wx 100000000000000500000005 @ 0x51
wx 19000000480000005f5f444154415f434f4e53540000000000000100010000000010000000000000001000000000000000100000000000000300000003 @ 0x68
wx 19000000480000005f5f4c494e4b45444954 @ 0xb0
wx 0200010000000010000000000000002000000000000000100000000000000100000001 @ 0xca
wx 34000080100000000020000050 @ 0xf8
wx 3412000041414141 @ 0x1000
wx 2000000048000000480000000000000001 @ 0x2004
wx 030000000000000010000000000000001800000000100500000001 @ 0x2020
wx 01 @ 0x2044
wtf .tmp_mach0_fw5.bin 12288
e bin.relocs.apply=true
o .tmp_mach0_fw5.bin
pxw 8 @ 0x100010000
ir~SET
rm .tmp_mach0_fw5.bin
EOF
EXPECT=<<EOF
0x100010000  0x00001234 0x41414141                        4...AAAA
0x100010000 0x00001000 SET_32 0      0x00001234
EOF
RUN

NAME=mach0 32-bit chained fixup in the last word of the file
FILE=malloc://12288
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c000001000000000200000004000000e8000000000020000000000019000000480000005f5f54455854
wx 010000000010 @ 0x3c
wx 100000000000000500000005 @ 0x51
wx 19000000480000005f5f444154415f434f4e53540000000000000100010000000010000000000000002000000000000000100000000000000300000003 @ 0x68
wx 19000000480000005f5f4c494e4b45444954 @ 0xb0
wx 0200010000000010000000000000001000000000000000100000000000000100000001 @ 0xca
wx 34000080100000000010000050 @ 0xf8
wx 2000000048000000480000000000000001 @ 0x1004
wx 030000000000000010000000000000001800000000100500000001 @ 0x1020
wx 0100fc0f @ 0x1044
wx 34120000 @ 0x2ffc
wtf .tmp_mach0_fw5end.bin 12288
e bin.relocs.apply=true
o .tmp_mach0_fw5end.bin
pxw 4 @ 0x100010ffc
ir~SET
rm .tmp_mach0_fw5end.bin
EOF
EXPECT=<<EOF
0x100010ffc  0x00001234                                   4...
0x100010ffc 0x00002ffc SET_32 0      0x00001234
EOF
RUN

NAME=mach0 chained fixups in a segment at address zero are applied
FILE=malloc://12288
ARGS=-n -w
CMDS=<<EOF
e log.quiet=true
wx cffaedfe0c00000102000080020000000300000028010000000020000000000019000000980000005f5f54455854
wx 400027f0ffffff0010 @ 0x39
wx 10000000000000050000000500000001000000000000005f5f636861696e5f73746172747300005f5f54455854 @ 0x51
wx 480027f0ffffff0c @ 0x89
wx 08000002 @ 0x99
wx 01 @ 0xac
wx 19000000480000005f5f44415441 @ 0xb8
wx 500027f0ffffff0010000000000000002000000000000000100000000000000300000003 @ 0xd1
wx 19000000480000005f5f444154415f434f4e5354 @ 0x100
wx 10000000000000001000000000000000100000000000000300000003 @ 0x121
wx 07000000010000000010 @ 0x800
wx 0800000000108010 @ 0x1001
wx 41414141414141414242424242424242 @ 0x2000
wtf .tmp_mach0_va0.bin 12288
e bin.relocs.apply=true
o .tmp_mach0_va0.bin
pxq 16 @ 0
ir~SET
rm .tmp_mach0_va0.bin
EOF
EXPECT=<<EOF
0x00000000  0xfffffff027004800  0xfffffff027004010   .H.'.....@.'....
0x00000000 0x00001000 SET_64 0      - 0xfd8ffb800
0x00000008 0x00001008 SET_64 0      - 0xfd8ffbff0
EOF
RUN
