[Issue 19017] New: Calling objc method returning struct segfaults

d-bugmail at puremagic.com d-bugmail at puremagic.com
Sat Jun 23 07:56:48 UTC 2018


https://issues.dlang.org/show_bug.cgi?id=19017

          Issue ID: 19017
           Summary: Calling objc method returning struct segfaults
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Mac OS X
            Status: NEW
          Severity: critical
          Priority: P1
         Component: dmd
          Assignee: nobody at puremagic.com
          Reporter: doob at me.com

Calling an Objective-C method that returns a struct that is too big to fit in
registers will result in a segmentation fault when accessing fields of the
returned struct. Example:

// foo.m

#import <Foundation/Foundation.h>

typedef struct
{
    int a, b, c, d, e;
} Bar;

@interface Foo : NSObject
-(Bar) getValue;
@end

@implementation Foo
-(Bar) getValue
{
    Bar s = { 3, 3, 3, 3, 3 };
    return s;
}
@end

// main.d

extern (C) int printf(in char*, ...);

struct Bar
{
    int a, b, c, d, e;
}

extern (Objective-C)
interface Foo
{
    static Foo alloc() @selector("alloc");
    Foo init() @selector("init");
    Bar getValue() @selector("getValue");
}

void main()
{
    auto f = Foo.alloc.init;
    auto b = f.getValue;
    printf("%d\n", b.a);
}

Compile with:
clang foo.m -o foo.o
dmd main.d foo.o -L-framework -LFoundation

Running this in a debugger results in:

lldb main
(lldb) target create "main"
Current executable set to 'main' (x86_64).
(lldb) r
Process 84149 launched: 'main' (x86_64)
Process 84149 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
(code=EXC_I386_GPFLT)
    frame #0: 0x00007fff6ac2030a libdyld.dylib`stack_not_16_byte_aligned_error
libdyld.dylib`stack_not_16_byte_aligned_error:
->  0x7fff6ac2030a <+0>: movdqa %xmm0, (%rsp)
    0x7fff6ac2030f <+5>: int3

libdyld.dylib`_dyld_func_lookup:
    0x7fff6ac20310 <+0>: pushq  %rbp
    0x7fff6ac20311 <+1>: movq   %rsp, %rbp
Target 0: (main) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS
(code=EXC_I386_GPFLT)
  * frame #0: 0x00007fff6ac2030a libdyld.dylib`stack_not_16_byte_aligned_error
    frame #1: 0x00007ffeefbff390
    frame #2: 0x000000010001f4ac
main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv + 40
    frame #3: 0x000000010001f33c
main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 32
    frame #4: 0x000000010001f417
main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZv + 139
    frame #5: 0x000000010001f33c
main`_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ7tryExecMFMDFZvZv + 32
    frame #6: 0x000000010001f2aa main`_d_run_main + 486
    frame #7: 0x0000000100000cd0 main`main + 16
    frame #8: 0x00007fff6ac20015 libdyld.dylib`start + 1

An Objective-C call like "f.getValue" is supposed to be lowered to this C call
[1]:

Bar tmp;
objc_msgSend_stret(&tmp, f, "getValue");

As far as I know this is the same ABI as a regular C function returning a
struct.

[1] For more details see the Objective-C ABI documentation:
https://github.com/dlang/dmd/blob/master/docs/objective-c_abi.md#returning-a-struct

--


More information about the Digitalmars-d-bugs mailing list