Hello,

currently i'm trying to get wxD running on my opensuse 11.4 64bit box.

I've got it running before on opensuse 11.3 32bit using dmd 2.41 (with some little tweaking to the wxd sources).

After Upgrading my box, I installed the 64bit version of dmd 2.43 and tried to compile it in 64bit mode. It needed a little more tweaking (casting down some length properties where wxWidgets expected int), but finally I got it to compile and link with my app. But when I tried to run it I only got a segfault.

Using GDB on it I was able to locate the problem. For passing strings to cpp wxD makes use of a neat little trick. Strings were just passed to a C function expecting a struct of type 'dstr' like in this testing code.

app.d ================================
import std.stdio;

// struct d_str {
//    size_t length;
//    const(char) *data;

//    this( string text) {
//       length = text.length;
//       data = text.ptr;
//    }
// }
// static extern (C) void cpp_test( d_str text);

static extern (C) void cpp_test( string text);

void main( string[] args) {
   //d_str dtext = "this is a testcall";
   string dtext = "this is a testcall";
   cpp_test( dtext);
}

test.cpp ==============================
#include <stdio.h>
#include <string.h>

struct dstr {
    size_t          length;
    const char*     data;
};

extern "C"
void cpp_test( dstr ctext) {
    printf( "string is: %.*s\n", (int)ctext.length, ctext.data);
    return;
}

===================================
compiled with:
g++ -g -Wall -c -o test.o test.cpp && dmd -gc test.o app.

As said above this worked fine in 32 bit mode but stopped working when compiled in 64 bit mode. The received struct in the called cpp function just contains garbage. The calling and receiving functions disassemble to the following sequences.

Dump of assembler code for function D main:
   0x000000000045ae40 <+0>:     push   %rbp
   0x000000000045ae41 <+1>:     mov    %rsp,%rbp
   0x000000000045ae44 <+4>:     sub    $0x10,%rsp
0x000000000045ae48 <+8>: mov 0x3fdb9(%rip),%rdx # 0x49ac08 <_TMP0+8> 0x000000000045ae4f <+15>: mov 0x3fdaa(%rip),%rax # 0x49ac00 <_TMP0>
   0x000000000045ae56 <+22>:    mov    %rax,-0x10(%rbp)
   0x000000000045ae5a <+26>:    mov    %rdx,-0x8(%rbp)
   0x000000000045ae5e <+30>:    rex.W push %rdx
   0x000000000045ae60 <+32>:    rex.W push %rax
   0x000000000045ae62 <+34>:    callq  0x45adf4 <cpp_test(dstr)>
   0x000000000045ae67 <+39>:    add    $0x10,%rsp
   0x000000000045ae6b <+43>:    xor    %eax,%eax
   0x000000000045ae6d <+45>:    leaveq
   0x000000000045ae6e <+46>:    retq
End of assembler dump.

Dump of assembler code for function cpp_test(dstr):
   0x000000000045adf4 <+0>:     push   %rbp
   0x000000000045adf5 <+1>:     mov    %rsp,%rbp
   0x000000000045adf8 <+4>:     sub    $0x10,%rsp
   0x000000000045adfc <+8>:     mov    %rdi,%rdx
   0x000000000045adff <+11>:    mov    %rsi,%rax
   0x000000000045ae02 <+14>:    mov    %rdx,-0x10(%rbp)
   0x000000000045ae06 <+18>:    mov    %rax,-0x8(%rbp)
   0x000000000045ae0a <+22>:    mov    -0x8(%rbp),%rdx
   0x000000000045ae0e <+26>:    mov    -0x10(%rbp),%rax
   0x000000000045ae12 <+30>:    mov    %eax,%esi
   0x000000000045ae14 <+32>:    mov    $0x49abc4,%edi
   0x000000000045ae19 <+37>:    mov    $0x0,%eax
   0x000000000045ae1e <+42>:    callq  0x45a728 <printf@plt>
   0x000000000045ae23 <+47>:    leaveq
   0x000000000045ae24 <+48>:    retq
End of assembler dump.

If I interpret this right then the problem is D pushing the array on the stack while cpp is expecting the structs values in the rdi and rsi registers. The GDB command 'ptype dtext' returns 'type = ucent' for the D string type. Since this is a 128 bit type I thought it may be passed on the stack because it doesn't fit in the registers. I the tried to pass an explicit struct (outcommented code) but with the same outcome. It also seems to be passed on the stack. So now I'm at the end of my wits. Is this expected or a bug in the 64bit linux implementation? And what can i do to keep this neat little trick alive?


Gerrit Wichert

Reply via email to