Overly aggressive usage of `__builtin_memcpy`
Version and Platform (required):
- Binary Ninja Version: 5.3.8707-dev Ultimate (a74ed668)
- Edition: Ultimate
- OS: macOS
- OS Version: 15.6
- CPU Architecture: M1
Bug Description:
I am noticing an over aggressive use of __builtin_memcpy in situations for structure field assignments (see the screenshots below). This is basically happening everytime for Objective-C block variables when I assign them the Block_layout struct type.
Steps To Reproduce: Please provide all steps required to reproduce the behavior:
- Open a Mach-O binary that contains Objective-C blocks or the DYLD Shared Cache.
- The example screenshots below are taken from
__UIResponderForwarderWantsForwardingFromResponderinUIKitCorein the DYLD Shared Cache for iOS 26.0 for an iPhone 17 Pro Max. - Define the
Block_layoutstruct. - Apply it to the stack variable which is being assigned the address of the symbol
__NSConcreteStackBlock. - If analysis is running it make take some time for the HLIL to update to using the struct and doing the
__builtin_memcpycall.
enum BlockFlags : uint32_t
{
BLOCK_DEALLOCATING = 0x1,
BLOCK_REFCOUNT_MASK = 0xfffe,
BLOCK_IS_NOESCAPE = 0x800000,
BLOCK_NEEDS_FREE = 0x1000000,
BLOCK_HAS_COPY_DISPOSE = 0x2000000,
BLOCK_HAS_CTOR = 0x4000000,
BLOCK_IS_GC = 0x8000000,
BLOCK_IS_GLOBAL = 0x10000000,
BLOCK_USE_STRET = 0x20000000,
BLOCK_HAS_SIGNATURE = 0x40000000,
BLOCK_HAS_EXTENDED_LAYOUT = 0x80000000
};
struct Block_layout
{
void* isa;
enum BlockFlags flags;
int32_t reserved;
void (* invoke)(void*, ...);
struct Block_descriptor_1* descriptor;
};
Expected Behavior:
The call to __builtin_memcpy when assigning to struct fields makes it hard to read whats going. I don't think there's a good reason to ever turn this into a call to __builtin_memcpy because thats almost never how its written and you can no longer really see what the values are and in the case of pointers, what is being referenced by the pointer being assigned.
Screenshots/Video Recording:
Assigning the fields of the Objective-C block in HLIL:
The respective disassembly:
Additional Information: I've only noticed this happening more recently but it may not be the result of some recent change.