Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
April 16, 2013 Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
The following code will result in a bus error on Mac OS X 10.8.2 using DMD 2.062 compiled for 32bit (segfault on 64bit). A couple of notes: * This code runs fine on Mac OS X 10.6.3 * It seems the struct has to be over 64 bits in size * "foo" need to take an argument Dissassembly at the bottom. I think this is the same problem I had with interfacing with the objc_msgSend_stret function, see other post: http://forum.dlang.org/thread/kkefk8$2663$1@digitalmars.com C code: struct Foo { int a; int b; int c; }; typedef struct Foo Foo; Foo foo (int a) { Foo f; f.a = 1; f.b = 2; f.c = 3; return f; } D code: struct Foo { int a; int b; int c; } extern (C) Foo foo (int a); Foo bar () { return foo(0); } extern (C) int printf(in char*, ...); void main () { auto frame = bar(); printf("a=%d b=%d c=%d\n".ptr, frame.a, frame.b, frame.c); } GDB session with dissassembly: http://pastebin.com/rguwXucR Dissassembly of the corresponding C program compiled with Clang: http://pastebin.com/MG8Tnkzp Dissassembly of "foo" on Mac OS X 10.8.2 using Clang 4.1: http://pastebin.com/0jKqksxx Dissassembly of "foo" on Mac OS X 10.6.3 using Clang 1.5: http://pastebin.com/kbdfuVcB -- /Jacob Carlborg |
April 16, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 2013-04-16 21:26, Jacob Carlborg wrote: > The following code will result in a bus error on Mac OS X 10.8.2 using > DMD 2.062 compiled for 32bit (segfault on 64bit). A couple of notes: > > * This code runs fine on Mac OS X 10.6.3 > * It seems the struct has to be over 64 bits in size > * "foo" need to take an argument If I a store the return value of "foo" in a temporary variable in "bar" the bus error goes away. -- /Jacob Carlborg |
April 16, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Tuesday, 16 April 2013 at 19:26:09 UTC, Jacob Carlborg wrote:
> The following code will result in a bus error on Mac OS X 10.8.2 using DMD 2.062 compiled for 32bit (segfault on 64bit). A couple of notes:
>
> * This code runs fine on Mac OS X 10.6.3
> * It seems the struct has to be over 64 bits in size
> * "foo" need to take an argument
>
> Dissassembly at the bottom.
>
> I think this is the same problem I had with interfacing with the objc_msgSend_stret function, see other post:
>
> http://forum.dlang.org/thread/kkefk8$2663$1@digitalmars.com
>
> C code:
>
> struct Foo
> {
> int a;
> int b;
> int c;
> };
>
> typedef struct Foo Foo;
>
> Foo foo (int a)
> {
> Foo f;
> f.a = 1;
> f.b = 2;
> f.c = 3;
> return f;
> }
>
> D code:
>
> struct Foo
> {
> int a;
> int b;
> int c;
> }
>
> extern (C) Foo foo (int a);
>
> Foo bar ()
> {
> return foo(0);
> }
>
> extern (C) int printf(in char*, ...);
>
> void main ()
> {
> auto frame = bar();
> printf("a=%d b=%d c=%d\n".ptr, frame.a, frame.b, frame.c);
> }
>
> GDB session with dissassembly:
>
> http://pastebin.com/rguwXucR
>
> Dissassembly of the corresponding C program compiled with Clang:
>
> http://pastebin.com/MG8Tnkzp
>
> Dissassembly of "foo" on Mac OS X 10.8.2 using Clang 4.1:
>
> http://pastebin.com/0jKqksxx
>
> Dissassembly of "foo" on Mac OS X 10.6.3 using Clang 1.5:
>
> http://pastebin.com/kbdfuVcB
Some observations:
Assuming main is doing everything properly, it's passing a pointer to 12 bytes of stack space to bar in eax (as per the D ABI). bar then puts that pointer on the stack for foo (as per the IA32 OS X ABI). However, it looks to me like it's in the wrong place, because of this line:
0x00002673 <D4test3barFZS4test3Foo+11>: sub $0x8,%esp
This is just from a quick glance, I may have added my hexes wrongly.
|
April 17, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On 2013-04-17 01:03, John Colvin wrote: > Some observations: > > Assuming main is doing everything properly, it's passing a pointer to 12 > bytes of stack space to bar in eax (as per the D ABI). bar then puts > that pointer on the stack for foo (as per the IA32 OS X ABI). However, > it looks to me like it's in the wrong place, because of this line: > 0x00002673 <D4test3barFZS4test3Foo+11>: sub $0x8,%esp > > This is just from a quick glance, I may have added my hexes wrongly. I don't know, that's why I'm asking here :) This is what Martin Nowak said in the bug report: "Seems like OSX deviates from the SysV IA-32 ABI for memory struct returns. The callee does NOT return the hidden pointer in EAX. Instead the caller has to use the value passed as argument." http://d.puremagic.com/issues/show_bug.cgi?id=9931#c7 The ABI documentation says: "When a function returns a structure or union larger than 8 bytes, the caller passes a pointer to appropriate storage as the first argument to the function." And: "The called function returns structures according to their aligned size. * Structures 1 or 2 bytes in size are placed in EAX. * Structures 4 or 8 bytes in size are placed in: EAX and EDX. * Structures of other sizes are placed at the address supplied by the caller. For example, the C++ language occasionally forces the compiler to return a value in memory when it would normally be returned in registers. See “Passing Arguments” for more information." http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4 -- /Jacob Carlborg |
April 17, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Tuesday, 16 April 2013 at 23:03:44 UTC, John Colvin wrote:
> On Tuesday, 16 April 2013 at 19:26:09 UTC, Jacob Carlborg wrote:
>> The following code will result in a bus error on Mac OS X 10.8.2 using DMD 2.062 compiled for 32bit (segfault on 64bit). A couple of notes:
>>
>> * This code runs fine on Mac OS X 10.6.3
>> * It seems the struct has to be over 64 bits in size
>> * "foo" need to take an argument
>>
>> Dissassembly at the bottom.
>>
>> I think this is the same problem I had with interfacing with the objc_msgSend_stret function, see other post:
>>
>> http://forum.dlang.org/thread/kkefk8$2663$1@digitalmars.com
>>
>> C code:
>>
>> struct Foo
>> {
>> int a;
>> int b;
>> int c;
>> };
>>
>> typedef struct Foo Foo;
>>
>> Foo foo (int a)
>> {
>> Foo f;
>> f.a = 1;
>> f.b = 2;
>> f.c = 3;
>> return f;
>> }
>>
>> D code:
>>
>> struct Foo
>> {
>> int a;
>> int b;
>> int c;
>> }
>>
>> extern (C) Foo foo (int a);
>>
>> Foo bar ()
>> {
>> return foo(0);
>> }
>>
>> extern (C) int printf(in char*, ...);
>>
>> void main ()
>> {
>> auto frame = bar();
>> printf("a=%d b=%d c=%d\n".ptr, frame.a, frame.b, frame.c);
>> }
>>
>> GDB session with dissassembly:
>>
>> http://pastebin.com/rguwXucR
>>
>> Dissassembly of the corresponding C program compiled with Clang:
>>
>> http://pastebin.com/MG8Tnkzp
>>
>> Dissassembly of "foo" on Mac OS X 10.8.2 using Clang 4.1:
>>
>> http://pastebin.com/0jKqksxx
>>
>> Dissassembly of "foo" on Mac OS X 10.6.3 using Clang 1.5:
>>
>> http://pastebin.com/kbdfuVcB
>
> Some observations:
>
> Assuming main is doing everything properly, it's passing a pointer to 12 bytes of stack space to bar in eax (as per the D ABI). bar then puts that pointer on the stack for foo (as per the IA32 OS X ABI). However, it looks to me like it's in the wrong place, because of this line:
> 0x00002673 <D4test3barFZS4test3Foo+11>: sub $0x8,%esp
>
> This is just from a quick glance, I may have added my hexes wrongly.
I was wrong. Ignore the previous post.
|
April 17, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Tuesday, 16 April 2013 at 19:26:09 UTC, Jacob Carlborg wrote:
> The following code will result in a bus error on Mac OS X 10.8.2 using DMD 2.062 compiled for 32bit (segfault on 64bit). A couple of notes:
>
> * This code runs fine on Mac OS X 10.6.3
> * It seems the struct has to be over 64 bits in size
> * "foo" need to take an argument
>
> Dissassembly at the bottom.
>
> I think this is the same problem I had with interfacing with the objc_msgSend_stret function, see other post:
>
> http://forum.dlang.org/thread/kkefk8$2663$1@digitalmars.com
>
> C code:
>
> struct Foo
> {
> int a;
> int b;
> int c;
> };
>
> typedef struct Foo Foo;
>
> Foo foo (int a)
> {
> Foo f;
> f.a = 1;
> f.b = 2;
> f.c = 3;
> return f;
> }
>
> D code:
>
> struct Foo
> {
> int a;
> int b;
> int c;
> }
>
> extern (C) Foo foo (int a);
>
> Foo bar ()
> {
> return foo(0);
> }
>
> extern (C) int printf(in char*, ...);
>
> void main ()
> {
> auto frame = bar();
> printf("a=%d b=%d c=%d\n".ptr, frame.a, frame.b, frame.c);
> }
>
> GDB session with dissassembly:
>
> http://pastebin.com/rguwXucR
>
> Dissassembly of the corresponding C program compiled with Clang:
>
> http://pastebin.com/MG8Tnkzp
>
> Dissassembly of "foo" on Mac OS X 10.8.2 using Clang 4.1:
>
> http://pastebin.com/0jKqksxx
>
> Dissassembly of "foo" on Mac OS X 10.6.3 using Clang 1.5:
>
> http://pastebin.com/kbdfuVcB
Martins reply in the bug report correctly identifies the problem, it's a bug in dmds implementation of the OS X IA32 ABI.
This is quite a severe bug, it's only by luck that eax was set to 0 causing an immediate error.
I suggest it should be marked critical.
|
April 17, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On 2013-04-17 12:05, John Colvin wrote: > Martins reply in the bug report correctly identifies the problem, it's a > bug in dmds implementation of the OS X IA32 ABI. I see. I'm still wondering why it works on Mac OS X 10.6.3, just luck? > This is quite a severe bug, it's only by luck that eax was set to 0 > causing an immediate error. > > I suggest it should be marked critical. Ok, perhaps we can come up with a better description for the issue as well. -- /Jacob Carlborg |
April 17, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On Wednesday, 17 April 2013 at 11:14:52 UTC, Jacob Carlborg wrote:
> On 2013-04-17 12:05, John Colvin wrote:
>
>> Martins reply in the bug report correctly identifies the problem, it's a
>> bug in dmds implementation of the OS X IA32 ABI.
>
> I see. I'm still wondering why it works on Mac OS X 10.6.3, just luck?
clang just happened to put the arguments to foo in to registers different on 10.6.3
Instead of loading the 0 argument in to eax it loaded the pointer to the struct like it would in system V ABI (linux)
I have no idea whether this is a complete coincidence, or whether clang has changed it's approach to the OS X abi, or whether the ABI itself has changed.
|
April 17, 2013 Re: Bus error interfacing with C function returning large struct | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On 2013-04-17 13:43, John Colvin wrote: > clang just happened to put the arguments to foo in to registers > different on 10.6.3 > Instead of loading the 0 argument in to eax it loaded the pointer to the > struct like it would in system V ABI (linux) > > I have no idea whether this is a complete coincidence, or whether clang > has changed it's approach to the OS X abi, or whether the ABI itself has > changed. Ok, I see. The docs for the ABI says: The called function returns structures according to their aligned size. * Structures 1 or 2 bytes in size are placed in EAX. * Structures 4 or 8 bytes in size are placed in: EAX and EDX. * Structures of other sizes are placed at the address supplied by the caller. For example, the C++ language occasionally forces the compiler to return a value in memory when it would normally be returned in registers. See “Passing Arguments” for more information. -- /Jacob Carlborg |
Copyright © 1999-2021 by the D Language Foundation