Skip to content

Running properly with ldc -g or ldc -O while setgmentfault with ldc #1057

Closed
@codesun

Description

@codesun

Development Environment: Arch Linux(kernel 4.1) 64bit with ldc 0.15.1
This is my test code:
md.S

/*
 * Internal regbuf layout
 */
#define JB_RSP  0*8
#define JB_RBX  1*8
#define JB_RBP  2*8
#define JB_R12  3*8
#define JB_R13  4*8
#define JB_R14  5*8
#define JB_R15  6*8
#define JB_PC   7*8

        .file "md.S"
        .text

        /* setreg(regbuf env) */
.globl setreg
        .type setreg, @function
        .align 16
setreg:
        /*
         * Save registers.
         */
        movq %rbx, (JB_RBX)(%rdi)
        movq %rbp, (JB_RBP)(%rdi)
        movq %r12, (JB_R12)(%rdi)
        movq %r13, (JB_R13)(%rdi)
        movq %r14, (JB_R14)(%rdi)
        movq %r15, (JB_R15)(%rdi)
        /* Save SP */
        leaq 8(%rsp), %rdx
        movq %rdx, (JB_RSP)(%rdi)
        /* Save PC we are returning to */
        movq (%rsp), %rax
        movq %rax, (JB_PC)(%rdi)
        xorq %rax, %rax
        ret
        .size _co_setjmp, .-_co_setjmp

        /* regjmp(regbuf env, int val) */
.globl regjmp
        .type regjmp, @function
        .align 16
regjmp:
        /*
         * Restore registers.
         */
        movq (JB_RBX)(%rdi), %rbx
        movq (JB_RBP)(%rdi), %rbp
        movq (JB_R12)(%rdi), %r12
        movq (JB_R13)(%rdi), %r13
        movq (JB_R14)(%rdi), %r14
        movq (JB_R15)(%rdi), %r15
        /* Set return value */
        test %esi, %esi
        mov $01, %eax
        cmove %eax, %esi
        mov %esi, %eax
        movq (JB_PC)(%rdi), %rdx
        movq (JB_RSP)(%rdi), %rsp
        /* Jump to saved PC */
        jmpq *%rdx
        .size _co_longjmp, .-_co_longjmp

coro.d:

version( X86 ) {
    alias void*[6] regbuf;
} else version( X86_64 ) {
    alias void*[8] regbuf;
}
import std.stdio;
import std.c.stdlib;

extern(C) {
    int setreg(ref regbuf);
    void regjmp(ref regbuf, int);
}

enum {
    STK_DEFAULT_SIZE = 64 * 1024
}

struct Context {
    regbuf env;
    void* stk;
}

class Fiber {
private:
    Context ctx;
    regbuf env;
public:
    this() {
        ctx.stk = calloc(1, STK_DEFAULT_SIZE);
        if(setreg(ctx.env)) {
            run();
        }
        ctx.env[0] = ctx.stk + STK_DEFAULT_SIZE;
    }
    void run() {
        writeln("hello");
        yield();
        writeln("world");
        yield();
    }
    void call() {
        if(!setreg(env)) {
            regjmp(ctx.env, 1);
        }
    }

    void yield() {
        if(!setreg(ctx.env)) {
            regjmp(env, 1);
        }
    }
}

void main() {
    Fiber fb = new Fiber();
    fb.call();
    writeln("step1 done");
    fb.call();
    writeln("step2 done");
}

The executable file compiled by dmd or ldc -g/-O can work properly, but with ldc, it will throw segmentfault.

And I have used objdump -d to get the assembly code of exe file, and I found the problem may be inside the following area:

  401380:   74 0e                   je     401390 <_D4coro5Fiber6__ctorMFZC4coro5Fiber+0x60>
  401382:   48 8b 44 24 10          mov    0x10(%rsp),%rax
  401387:   48 8b 08                mov    (%rax),%rcx

%rax = 0, how is it come?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions