Skip to content

Objective-C++ Wrong Assignment of arguments to registers on Windows ARM64 when returning an instance of C++ Class. #88273

Closed
@hmelder

Description

@hmelder

The libobjc2 objc_msgSend implementation for aarch64 expects the receiver and selector to be passed in x0 and x1 respectively.

On Windows ARM64, the pointer to the (uninitialised) instance of the C++ Class is assigned to x0, shifting receiver and selector into x1 and x2. This results in a crash.

This does not happen on Ubuntu aarch64, as seen in the lldb snippet below.

I am using the GNUstep Windows SDK from https://github.com/gnustep/tools-windows-msvc.

Here is the test code:

#import <Foundation/Foundation.h>

class Bar
{
public:
    Bar(int i) : m_i(i) {}
private:
    int m_i;
};

@interface Test : NSObject
@end

@implementation Test

+ (Bar)bar
{
	return Bar(42);
}

@end

int main(int argc, char *argv[])
{
	NSLog(@"Hello");
	
	auto pair = [Test bar]; // crashes

	NSLog(@"Success");

	return 0;
}

Windows 11 ARM64

Machine Information

WindowsBuildLabEx: 22621.1.arm64fre.ni_release.220506-1250
WindowsProductName: Windows 10 Pro
OSDisplayVersion: 23H2
WindowsKit: 10.0.22621.0

Clang Version

clang version 18.1.3
Target: aarch64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

Build Command (Inside MSYS2)

clang crash.mm -o crash.exe -g -gcodeview `gnustep-config --objc-flags` `gnustep-config --base-libs` -Xclang -fobjc-dispatch-method=non-legacy

LLDB

Process 6408 stopped
* thread #1, stop reason = breakpoint 2.1
    frame #0: 0x00007ff738e61048 crash.exe`main(argc=867171612, argv=0x00007ff738e640b0) at crash.mm:27
   24   {
   25           NSLog(@"Hello");
   26
-> 27           auto pair = [Test bar]; // crashes
   28
   29           NSLog(@"Success");
   30
(lldb) di
crash.exe`main:
    0x7ff738e6100c <+0>:   sub    sp, sp, #0x20
    0x7ff738e61010 <+4>:   str    x19, [sp, #0x10]
    0x7ff738e61014 <+8>:   str    x30, [sp, #0x18]
    0x7ff738e61018 <+12>:  mov    x0, #0x2c ; =44
    0x7ff738e6101c <+16>:  adrp   x19, 2
    0x7ff738e61020 <+20>:  movk   x0, #0xe000, lsl #16
    0x7ff738e61024 <+24>:  ldr    x19, [x19, #0x5e8]
    0x7ff738e61028 <+28>:  movk   x0, #0x66cd, lsl #32
    0x7ff738e6102c <+32>:  movk   x0, #0x9197, lsl #48
    0x7ff738e61030 <+36>:  blr    x19
    0x7ff738e61034 <+40>:  adrp   x8, 5
    0x7ff738e61038 <+44>:  adrp   x2, 5
    0x7ff738e6103c <+48>:  add    x2, x2, #0x10 ; __start_.objcrt$PCR
    0x7ff738e61040 <+52>:  ldr    x1, [x8]
    0x7ff738e61044 <+56>:  add    x0, sp, #0xc
->  0x7ff738e61048 <+60>:  bl     0x7ff738e62384 ; objc_msgSend_stret
    0x7ff738e6104c <+64>:  mov    x0, #0x803c ; =32828
    0x7ff738e61050 <+68>:  movk   x0, #0xbcf9, lsl #16
    0x7ff738e61054 <+72>:  movk   x0, #0x1e3c, lsl #32
    0x7ff738e61058 <+76>:  movk   x0, #0xa7d7, lsl #48
    0x7ff738e6105c <+80>:  blr    x19
    0x7ff738e61060 <+84>:  mov    w0, wzr
    0x7ff738e61064 <+88>:  ldr    x30, [sp, #0x18]
    0x7ff738e61068 <+92>:  ldr    x19, [sp, #0x10]
    0x7ff738e6106c <+96>:  add    sp, sp, #0x20
    0x7ff738e61070 <+100>: ret
(lldb) register read
General Purpose Registers:
        x0 = 0x000000e233affd1c
        x1 = 0x00007ff738e640b0  $_OBJC_CLASS_Test
        x2 = 0x00007ff738e66010  __start_.objcrt$PCR
        x3 = 0x0000000010000000
        x4 = 0x0000000000000150
        x5 = 0x000000006d9d3bcf
        x6 = 0x00007ff8b4129000  NlsAnsiCodePage + 26720
        x7 = 0x5d4b1dcd6d097720
        x8 = 0x00007ff738e66000  __start_.objcrt$CAL
        x9 = 0x0000000000000000
       x10 = 0x000000007ffe0380
       x11 = 0x0000000000000000
       x12 = 0x0000000000000000
       x13 = 0xa2e64eada2e64ead
       x14 = 0x0000000000000001
       x15 = 0x0000000000000070
       x16 = 0x0000000080000001
       x17 = 0x00005859193355a3
       x18 = 0x000000e233970000
       x19 = 0x00007ff857942570  gnustep-base-1_29.dll`NSLog at NSLog.m:293
       x20 = 0x000002a841621080
       x21 = 0x0000000000000000
       x22 = 0x0000000000000000
       x23 = 0x0000000000000000
       x24 = 0x0000000000000000
       x25 = 0x0000000000000000
       x26 = 0x0000000000000000
       x27 = 0x0000000000000000
       x28 = 0x0000000000000000
        fp = 0x000000e233affd30
        lr = 0x00007ff738e61034  crash.exe`main + 40 at crash.mm:27
        sp = 0x000000e233affd10
        pc = 0x00007ff738e61048  crash.exe`main + 60 at crash.mm:27
      cpsr = 0x80000000

(lldb)

Ubuntu 23.10 aarch64

Clang Version

Ubuntu clang version 18.1.3 (++20240322073236+ef6d1ec07c69-1~exp1~20240322193248.98)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

Build Command

clang-18 ObjcCXXObjectReturnTest.mm -o ObjcCXXObjectReturnTest -g `gnustep-config --objc-flags` `gnustep-config --base-libs` -Xclang -fobjc-dispatch-method=non-legacy -fuse-ld=lld-18
* thread #1, name = 'ObjcCXXObjectRe', stop reason = breakpoint 2.1
    frame #0: 0x0000aaaaaaab0dcc ObjcCXXObjectReturnTest`main(argc=<unavailable>, argv=<unavailable>) at ObjcCXXObjectReturnTest.mm:27:14
   24  	{
   25  		NSLog(@"Hello");
   26
-> 27  		auto pair = [Test bar]; // crashes
   28
   29  		NSLog(@"Success");
   30
(lldb) di
ObjcCXXObjectReturnTest`main:
    0xaaaaaaab0d9c <+0>:  stp    x29, x30, [sp, #-0x10]!
    0xaaaaaaab0da0 <+4>:  mov    x29, sp
    0xaaaaaaab0da4 <+8>:  mov    x0, #0x2c ; =44
    0xaaaaaaab0da8 <+12>: movk   x0, #0xe000, lsl #16
    0xaaaaaaab0dac <+16>: movk   x0, #0x66cd, lsl #32
    0xaaaaaaab0db0 <+20>: movk   x0, #0x9197, lsl #48
    0xaaaaaaab0db4 <+24>: bl     0xaaaaaaab0e90 ; symbol stub for: NSLog
    0xaaaaaaab0db8 <+28>: adrp   x8, 17
    0xaaaaaaab0dbc <+32>: nop
    0xaaaaaaab0dc0 <+36>: adr    x1, 0xaaaaaaad12b0 ; ObjcCXXObjectReturnTest.PT_LOAD[3].__objc_selectors + 0
    0xaaaaaaab0dc4 <+40>: ldr    x8, [x8, #0xd0]
    0xaaaaaaab0dc8 <+44>: ldr    x0, [x8]
->  0xaaaaaaab0dcc <+48>: bl     0xaaaaaaab0ea0 ; symbol stub for: objc_msgSend
    0xaaaaaaab0dd0 <+52>: mov    x0, #0x803c ; =32828
    0xaaaaaaab0dd4 <+56>: movk   x0, #0xbcf9, lsl #16
    0xaaaaaaab0dd8 <+60>: movk   x0, #0x1e3c, lsl #32
    0xaaaaaaab0ddc <+64>: movk   x0, #0xa7d7, lsl #48
    0xaaaaaaab0de0 <+68>: bl     0xaaaaaaab0e90 ; symbol stub for: NSLog
    0xaaaaaaab0de4 <+72>: mov    w0, wzr
    0xaaaaaaab0de8 <+76>: ldp    x29, x30, [sp], #0x10
    0xaaaaaaab0dec <+80>: ret
(lldb) register read
General Purpose Registers:
        x0 = 0x0000aaaaaaad11a0  ._OBJC_CLASS_Test
        x1 = 0x0000aaaaaaad12b0  ObjcCXXObjectReturnTest.PT_LOAD[3].__objc_selectors + 0
        x2 = 0x0000000000000007
        x3 = 0x0000aaaaaaad2010
        x4 = 0x0000000000000004
        x5 = 0x0000aaaaaaebc7f0
        x6 = 0xb3c97132ac52cb5b
        x7 = 0x0000fffff7e1f3a8  ._OBJC_CLASS_GSMutableString
        x8 = 0x0000aaaaaaad12d0  ObjcCXXObjectReturnTest`._OBJC_REF_CLASS_Test
        x9 = 0x0000000000000000
       x10 = 0x0000fffff7f884cc  libobjc.so.4.6`objc_slot_lookup_super2 + 264
       x11 = 0x0000000000000003
       x12 = 0x0000fffff7f87bd0  libobjc.so.4.6`objc_msg_lookup_sender + 100
       x13 = 0x0000000000000003
       x14 = 0x000000000042a2d5
       x15 = 0x0000ffffffff8b88
       x16 = 0x0000fffff7fb00d0
       x17 = 0x0000fffff76d47f0  libc.so.6`free
       x18 = 0x0000000000000034
       x19 = 0x0000fffffffff0d8
       x20 = 0x0000000000000001
       x21 = 0x0000aaaaaaac0ed8
       x22 = 0x0000aaaaaaab0d9c  ObjcCXXObjectReturnTest`main at ObjcCXXObjectReturnTest.mm:24
       x23 = 0x0000fffffffff0e8
       x24 = 0x0000fffff7ffdb90  ld-linux-aarch64.so.1`_rtld_global_ro
       x25 = 0x0000000000000000
       x26 = 0x0000fffff7ffe008  _rtld_global
       x27 = 0x0000aaaaaaac0ed8
       x28 = 0x0000000000000000
        fp = 0x0000ffffffffef50
        lr = 0x0000aaaaaaab0db8  ObjcCXXObjectReturnTest`main + 28 at ObjcCXXObjectReturnTest.mm:27:14
        sp = 0x0000ffffffffef50
        pc = 0x0000aaaaaaab0dcc  ObjcCXXObjectReturnTest`main + 48 at ObjcCXXObjectReturnTest.mm:27:14
      cpsr = 0x40001000

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions