You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug Description:
When applying a custom calling convention that states certain registers are callee saved, like; x0, x1, x2, etc. (the ones that are usually clobbered or used as arguments in the default calling convention) I would expect the caller to assume its values for those registers persist across the call. Instead those registers seem to be being considered clobbered by the call because HLIL shows the call returning values into all registers that are used later on by the caller, that under the default calling convention would be considered clobbered.
____chkstk_darwin only clobbers x9 so the values of the argument registers are exactly as they were when the function was called when they are assigned to the registers; x19, x20, x21, x22, after the ____chkstk_darwin call.
However you can see from the HLIL in the first snippet that Binary Ninja is getting confused and assuming the call to ____chkstk_darwin is returning values via x1, x2, x3, x4. Coincidentally these are 4 of the 5 argument registers that are used later on and are typically considered clobbered by the default calling convention.
Steps To Reproduce:
Please provide all steps required to reproduce the behavior:
Compile into a plugin the native code provided below for the custom calling convention (don't forget to call Register())
Expected Behavior:
Analysis should recognise that registers saved by the callee do not have their values modified and can therefore be assumed to be unchanged across calls. As far as I can tell Binary Ninja does this fine for default calling conventions. It just seems it ignores this for custom calling conventions. It feels like its hardcoded to only consider the default calling convention but I haven't done enough testing to confirm this theory.
Binary:
Tested against DYLD Shared Cache for iOS 26.2 for an iPhone 17 Pro Max.
Additional Information:
I've noticed before and can confirm its still the same, that the clobbered registers tick box list view in the edit function properties dialog doesn't seem to do anything. I'm not 100% sure what the exact purpose of these tick boxes are. I assumed it was to tell callers what register values they can assume have been modified/clobbered by calling the function but I've never seen any change in analysis when modifying this list.
Version and Platform (required):
Bug Description:
When applying a custom calling convention that states certain registers are callee saved, like;
x0,x1,x2, etc. (the ones that are usually clobbered or used as arguments in the default calling convention) I would expect the caller to assume its values for those registers persist across the call. Instead those registers seem to be being considered clobbered by the call because HLIL shows the call returning values into all registers that are used later on by the caller, that under the default calling convention would be considered clobbered.I don't know the exact function type of this function but it clearly takes 5 arguments, which can be seen in the disassembly:
____chkstk_darwinonly clobbersx9so the values of the argument registers are exactly as they were when the function was called when they are assigned to the registers;x19,x20,x21,x22, after the____chkstk_darwincall.However you can see from the HLIL in the first snippet that Binary Ninja is getting confused and assuming the call to
____chkstk_darwinis returning values viax1,x2,x3,x4. Coincidentally these are 4 of the 5 argument registers that are used later on and are typically considered clobbered by the default calling convention.Steps To Reproduce:
Please provide all steps required to reproduce the behavior:
Register())libsystem_pthread.dyliblibrary____chkstk_darwinvoid ____chkstk_darwin(uint64_t amountToIncreaseTheStackBy @ x9)(this has to be done due to Using the UI to change a function's type removes the assigned custom calling convention #8052, see what happens if you skip this step if you're curious).apple-chkstk_glob0____chkstk_darwinExpected Behavior:
Analysis should recognise that registers saved by the callee do not have their values modified and can therefore be assumed to be unchanged across calls. As far as I can tell Binary Ninja does this fine for default calling conventions. It just seems it ignores this for custom calling conventions. It feels like its hardcoded to only consider the default calling convention but I haven't done enough testing to confirm this theory.
Binary:
Tested against DYLD Shared Cache for iOS 26.2 for an iPhone 17 Pro Max.
Additional Information:
I've noticed before and can confirm its still the same, that the clobbered registers tick box list view in the edit function properties dialog doesn't seem to do anything. I'm not 100% sure what the exact purpose of these tick boxes are. I assumed it was to tell callers what register values they can assume have been modified/clobbered by calling the function but I've never seen any change in analysis when modifying this list.