View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Mac OS X 32-bits crash

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

28 replies to this topic

### #1Vasil Boshnyakov  Members

Posted 25 March 2012 - 05:00 PM

Hello,

when I compile "tutorial" example to MacOS X 64 bits, everything works normal. When I switch to 32 bits (Intel 32 bits) the application crashes (please check the attached file).

Any help how to get it working is greatly appreciated! Thank you!

Best regards, Vasil

### #2Andreas Jonsson  Moderators

Posted 26 March 2012 - 09:26 AM

Hi, Vasil,

which version of AngelScript are you using? Are you compiling the library with optimizations turned on or off?

I fixed a similar crash on Mac OS X 32bit in version 2.23.0 thanks to the help from Matt Bush.

Regards,
Andreas
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #3Vasil Boshnyakov  Members

Posted 26 March 2012 - 03:43 PM

Hello Andreas,

Here is more detailed information:
AngelScript library 2.23.0
The platform is Mac OS 10.7.3 (Lion)
XCode 4.3.2 (the latest)

Create new project for Mac OS X - command line tool
Select "Type: C++", No Automated Reference Counting

replace "main.cpp" the file from "tutorial".
Add to the same folder angelscript.h + all source files + scriptarray + scriptstdstring

Fix the include defines (#include <angelscript.h> -> #include "angelscript.h")

Compile and run the project in 64 bits (Debug) - works
Compile and run the project in 64 bits (Release) - works
Add 32 bits support:
Compile and run the project in 32 bits (Debug) - check attachment1.png
Compile and run the project in 32 bits (Release) - check attachment2.png

The only two files for the callfunc are:
as_callfunc_x64_gcc.cpp
as_callfunc_x86.cpp

Thank you for your help!

Best regards, Vasil

### #4Andreas Jonsson  Moderators

Posted 26 March 2012 - 06:41 PM

Thanks. I'll try to reproduce the problem on my old Mac.

However, I'm pretty sure this is a problem that only happens with the new CLang compiler that Apple has adopted lately for their development tools. If this is the case, then I'll most likely need your help to debug and find the cause for the problem.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #5Vasil Boshnyakov  Members

Posted 27 March 2012 - 02:44 AM

Thank you! I will help you to fix this problem (just give me a task).
I have changed the compiler to LLVM GCC 4.2 (Instead of Apple LLVM Compiler 3.1) and the problem still exists.

### #6Andreas Jonsson  Moderators

Posted 28 March 2012 - 09:11 PM

As I suspected; I was not able to reproduce this on my old Mac. My Mac is still running Mac OS X 10.4.11 with XCode 2.4.1, and AngelScript still runs without a problem on it. The problem you're facing really must be something triggered by this new version of the compiler that you have.

OK. I guess we'll have to do this the hard way, with me trying to guide you through the debugging process until we find the problem and I can have it fixed.

The first thing I need to know is which registered function AngelScript is trying to call when it crashes. Can you set a breakpoint in the CallSystemFunctionNative() in the as_callfunc_x86.cpp file, and there let me know the values of the following variables?

- descr->name
- descr->objectType
- descr->parameterTypes.length

This will let me know which function is being called when the crash happens, and then I can determine what to expect from the rest of the values. We will then have to debug step by step until we find out where something goes wrong.

This will unfortunately be a long process if I have to guide you through each step, so hopefully you are willing to do a little debugging on your own and try to figure out why it is not working.

One thing that you can try that might solve the problem is to change the value of the CLEAR_FPU_STACK define on line 68 in as_callfunc_x86.cpp to emms. This will change the way the FPU stack is cleared with each call. It might be this that is causing the crash, though I just making a wild guess here.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #7Vasil Boshnyakov  Members

Posted 30 March 2012 - 01:26 AM

Running tutorial:

as_callfunc_x86.cpp:

CallSystemFunctionNative()

Executing the script.
---
name: _string_factory_
objectType: NULL
parameterTypes.length: 2

About the next idea:

... change the value of the CLEAR_FPU_STACK define on line 68 in as_callfunc_x86.cpp to emms.

no difference.

The application always crashes on row (around) 317 - the first asm __volatile__(

### #8Andreas Jonsson  Moderators

Posted 01 April 2012 - 08:55 AM

Can you show me the disassembly of the StringFactory() function in the add_on/scriptstdstring/scriptstdstring.cpp file?

I suspect the inline assembler code I has is not compatible with what the new LLVM compiler generates (whether it be Clang or GCC). If I can see the disassembly I may be able to identify the difference.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #9m4ttbush  Members

Posted 11 April 2012 - 05:54 AM

Hey Andreas,
I'm having the same issue, I couldn't get the disassembly to work, but here's the assembly from what I think is the StringFactory function
http://pastebin.com/UZagTvCa

Let me know if there's anything else I can do.

### #10Andreas Jonsson  Moderators

Posted 11 April 2012 - 02:53 PM

Hi Matt,

are you using the same version of Mac and XCode as Vasil is? I.e. Mac OS 10.7.3 and XCode 4.3.2?

I'll check out the pastebin content when I get home to see if I can figure out what's causing the problem.

Regards,
Andreas
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #11Andreas Jonsson  Moderators

Posted 11 April 2012 - 06:51 PM

The disassembly of the StringFactory doesn't show any difference in the calling convention. It is taking the function arguments on the stack, returning the value in eax, and makes sure not to modify the registers ebp, ebx, esi, and edi.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #12Andreas Jonsson  Moderators

Posted 11 April 2012 - 07:42 PM

It might be a difference in one of the other calling conventions. The fact that it fails when calling the StringFactory may not mean the problem is with the StringFactory itself, it could be a previous call that is causing the problem.

Can you run the test_features project (from the svn)? I need to see which of the following tests pass:


// The following tests are designed specifically to test the native calling conventions.
// These are grouped by calling convention and ordered in increasing complexity.
{
// cdecl
if( TestExecute()                 ) goto failed; else printf("-- TestExecute passed\n");
if( TestCDeclReturn::Test()       ) goto failed; else printf("-- TestCDeclReturn passed\n");
if( TestExecute1Arg()             ) goto failed; else printf("-- TestExecute1Arg passed\n");
if( TestExecute2Args()            ) goto failed; else printf("-- TestExecute2Args passed\n");
if( TestExecute4Args()            ) goto failed; else printf("-- TestExecute4Args passed\n");
if( TestExecute4Argsf()           ) goto failed; else printf("-- TestExecute4Argsf passed\n");
if( TestExecuteMixedArgs()        ) goto failed; else printf("-- TestExecuteMixedArgs passed\n");
if( TestExecute32Args()           ) goto failed; else printf("-- TestExecute32Args passed\n");
if( TestExecute32MixedArgs()      ) goto failed; else printf("-- TestExecute32MixedArgs passed\n");
if( TestCDecl_Class()             ) goto failed; else printf("-- TestCDecl_Class passed\n");
if( TestCDecl_ClassA()            ) goto failed; else printf("-- TestCDecl_ClassA passed\n");
if( TestCDecl_ClassC()            ) goto failed; else printf("-- TestCDecl_ClassC passed\n");
if( TestCDecl_ClassD()            ) goto failed; else printf("-- TestCDecl_ClassD passed\n");
if( TestCDecl_ClassK()            ) goto failed; else printf("-- TestCDecl_ClassK passed\n");

// cdecl_objlast and cdecl_objfirst
if( TestReturnString::Test()      ) goto failed; else printf("-- TestReturnString passed\n");
if( TestNegateOperator()          ) goto failed; else printf("-- TestNegateOperator passed\n");
if( TestReturnWithCDeclObjFirst() ) goto failed; else printf("-- TestReturnWithCDeclObjFirst passed\n");

// thiscall
if( TestExecuteThis32MixedArgs()  ) goto failed; else printf("-- TestExecuteThis32MixedArgs passed\n");
if( TestNotComplexThisCall()      ) goto failed; else printf("-- TestNotComplexThisCall passed\n");
if( TestVirtualMethod()           ) goto failed; else printf("-- TestVirtualMethod passed\n");
if( TestMultipleInheritance()     ) goto failed; else printf("-- TestMultipleInheritance passed\n");
if( TestVirtualInheritance()      ) goto failed; else printf("-- TestVirtualInheritance passed\n");

// stdcall
if( TestStdcall4Args()            ) goto failed; else printf("-- TestStdcall4Args passed\n");
if( TestNotComplexStdcall()       ) goto failed; else printf("-- TestNotComplexStdcall passed\n");
}


Comment out all the other tests above these in the main() function (in main.cpp), as they test features, etc. But before those will work the native calling conventions must work.

Based on which of the tests for the calling conventions that work or not it should be easier to narrow in on where the problem really lies.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #13m4ttbush  Members

Posted 11 April 2012 - 09:49 PM

Every one of the tests crashes inside CallSystemFunctionNative when it gets to "asm __volatile__"

TestExecute crashes calling "cfunction" from "ExecuteString"
TestCDeclReturn::Test crashes calling "reti64" from "ExecuteString"
TestExecute1Arg crashes calling "cfunction"
...etc

Only one that didn't crash was TestVirtualInheritance, but I think it got skipped because virtual inheritance wasn't detected.

Let me know if there's anything more I can do.

Edit: I'm on

OS 10.7.3 and Xcode 4.3.2

Edit 2: If I compile for 64 bit, all tests pass (Except TextVirtualInheritance which is skipped).

### #14Andreas Jonsson  Moderators

Posted 12 April 2012 - 06:20 AM

If all of them crashes, then I can only think that the inline assembly in as_callfunc_x86.cpp is causing this.

Something is going wrong when the code is being compiled.

I'll need the assembler code produced for the CallCDeclFunction(). The same way you sent it for the StringFactory.

Hopefully I'll spot what is wrong. It might be a register that is getting incorrectly mangled (though the inline assembler is using the clobber lists).

Matt, in your previous post you were using XCode 4.2.1. Was that with Mac OS 10.7.3? or a previous version of Mac OS too? At that time we got it to work. I'm wondering if this might not be a bug in XCode itself (or rather the compiler it is using).
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #15m4ttbush  Members

Posted 12 April 2012 - 07:32 AM

I think I was on 10.7.2 and I updated to 10.7.3 when I updated Xcode.
Can't remember if I tried 2.23.0 before updating or not, sorry.

Here's the assembly for CallCDeclFunction, I think
http://pastebin.com/VpMwk3HF

Thanks

Edit: Btw, it's crashing on line 47 of that paste, 2 lines after "copyloop:" at "pushl (%eax)"

### #16Andreas Jonsson  Moderators

Posted 12 April 2012 - 08:40 AM

In which test does it crash on this line? The TextExecute() test? It shouldn't even be hitting that instruction in that test.

I'm not seeing anything wrong with the assembly that was produced.

I can only imagine that LLVM that XCode is using is not recognizing some instructions, possibly "pushl (%eax)". It's a longshot, but perhaps changing the inline assembly a bit might work. Can you try changing the inline assembly in CallCDeclFunction to the following:


asm __volatile__(
_S(CLEAR_FPU_STACK)  "\n"
"pushl %%ebx            \n"
"movl  %%edx, %%ebx     \n"

// Need to align the stack pointer so that it is aligned to 16 bytes when making the function call.
// It is assumed that when entering this function, the stack pointer is already aligned, so we need
// to calculate how much we will put on the stack during this call.
"movl  4(%%ebx), %%eax  \n" // paramSize
"addl  $4, %%eax \n" // counting esp that we will push on the stack "movl %%esp, %%ecx \n" "subl %%eax, %%ecx \n" "andl$15, %%ecx       \n"
"movl  %%esp, %%eax     \n"
"subl  %%ecx, %%esp     \n"
"pushl %%eax            \n" // Store the original stack pointer

"movl  4(%%ebx), %%ecx  \n" // paramSize
"movl  0(%%ebx), %%eax  \n" // args
"addl  %%ecx, %%eax     \n" // push arguments on the stack
"cmp   $0, %%ecx \n" "je endcopy \n" "copyloop: \n" "subl$4, %%eax        \n"
// "pushl (%%eax)          \n"                     <----- comment out
"movl (%%eax), %%edx  \n"                    <----- add
"pushl %%edx         \n"                            <----- add
"subl  $4, %%ecx \n" "cmp$0, %%ecx      \n"                         <------ add
"jne   copyloop         \n"
"endcopy:               \n"
"call  *8(%%ebx)        \n"
"addl  4(%%ebx), %%esp  \n" // pop arguments

// Pop the alignment bytes
"popl  %%esp            \n"
"popl  %%ebx            \n"
:                          // output
: "d"(&args)               // input - pass pointer of args in edx
: "%eax", "%ecx", "%esp"   // clobber
);


I replaced the 'pushl (%%eax)' with 'movl (%%eax), %%edx' and 'pushl %%edx'. Then I also added an explicit 'cmp \$0, %%ecx' before the jne instruction.

Neither of these changes should be necessary, but who knows what LLVM does.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #17m4ttbush  Members

Posted 12 April 2012 - 09:02 AM

Yep, this is in TestExecute()
I tried that code, it still crashes. This is what it looks like when it crashes with call stack and disassembly:
http://snag.gy/jDB74.jpg

### #18Andreas Jonsson  Moderators

Posted 12 April 2012 - 09:09 AM

OK. So the code changes didn't make a difference. The problem is happening when attempting to access the memory pointed to by the address in eax.

TestExecute() is calling a global function without any arguments, so it shouldn't even try to push any arguments on the stack.

Do you think you can single step through the CallCDeclFunction() at assembler level and check what the values are on the registers? The code really should be jumping to endcopy at the first 'je endcopy'. For some reason it isn't doing that, and instead tries to read from 'eax' that is seemingly pointing to some invalid memory position.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #19Andreas Jonsson  Moderators

Posted 12 April 2012 - 09:27 AM

Nevermind. I figured it out.

In the inline assembly I'm asking the compiler to pass the address of the parameter 'args' in the edx register. I'm then using this address to determine the location of the other two parameters so I do not have to rely on ebp or esp to get to them. Relying on ebp or esp is not possible because they are used differently in different optimization levels.

The problem here is that for some reason the compiler is not passing the address of the parameter, but instead the address of a local temporary variable with the same value. Because of this my code fails to retrieve the correct values for 'paramSize' and 'func'.

I'll have to rewrite the inline assembly to pass each of the values in explicit registers to avoid this unexpected behaviour.

Thanks for all the help in figuring this out.

Unfortunately I'll be traveling today, and will only be back in a week. I will only be able to work on this fix when I get back.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

### #20Andreas Jonsson  Moderators

Posted 12 April 2012 - 10:23 AM

One thing that might resolve the problem until I get to reimplement the inline assembler code is to remove the macros "UNUSED_VAR()" in the CallCDeclFunction, etc. It might be because of these macros that the compiler decides to copy the parameters to local variables.
AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.