Since Xcode 15.1, when Xcode launches an app it places a software breakpoint (brk / int3) instruction at the beginning of the notification_address returned by all_image_infos. That's a function which the cache invalidator hooks with Interceptor in order to trigger when any libraries are loaded or unloaded at runtime. The problem with this approach is that in this way Interceptor relocates the breakpoint instruction, so when it gets executed Xcode can't match it with the address it expected, resulting into an uncaught exception crashing the app.
In cases where Interceptor can't work on system code (like the Gadget with required code-signing) the symbolicator cache is never invalidated
To overcome these problems what this change proposes is:
use _dyld_register_func_for_add_image / _dyld_register_func_for_remove_image when TeardownRequirement is MINIMAL (because there's no good way to unregister those handlers, so it's safe only if frida-gum knows it will never be unloaded)
otherwise still place an instruction-level hook using Interceptor, but on the instruction following the breakpoint if present
In order to do so, though, other 2 changes are present in this MR:
one brings back disassemble_instruction_at () in arm64-reader, so we can use it to check the breakpoint instruction presence
move the TeardownRequirement setting from the Gadget library to Gum's Process (following the same semantics as the codesign setting), so Gum can make better decisions taking into account its own promised lifetime like in this case
There are 2 problems with the existing logic:
brk
/int3
) instruction at the beginning of thenotification_address
returned byall_image_infos
. That's a function which the cache invalidator hooks withInterceptor
in order to trigger when any libraries are loaded or unloaded at runtime. The problem with this approach is that in this wayInterceptor
relocates the breakpoint instruction, so when it gets executed Xcode can't match it with the address it expected, resulting into an uncaught exception crashing the app.Interceptor
can't work on system code (like the Gadget withrequired
code-signing) the symbolicator cache is never invalidatedTo overcome these problems what this change proposes is:
_dyld_register_func_for_add_image
/_dyld_register_func_for_remove_image
whenTeardownRequirement
isMINIMAL
(because there's no good way to unregister those handlers, so it's safe only if frida-gum knows it will never be unloaded)Interceptor
, but on the instruction following the breakpoint if presentIn order to do so, though, other 2 changes are present in this MR:
disassemble_instruction_at ()
in arm64-reader, so we can use it to check the breakpoint instruction presenceTeardownRequirement
setting from the Gadget library to Gum's Process (following the same semantics as the codesign setting), so Gum can make better decisions taking into account its own promised lifetime like in this casehttps://github.com/frida/frida-core/pull/498 depends on this