混合汇编和C:重新分配RSP寄存器会导致分段错误

时间:2017-11-22 04:16:31

标签: c gcc assembly x86-64 inline-assembly

我试图为子功能重新分配堆栈。我试图通过混合程序集和Linux,x86_64架构上的C实现它。

以下是我计划的方式: 1.通过mmap系统调用获取一段内存。 2.将映射的内存传递给asm func,然后将其分配给RSP寄存器并跳转到该函数。

C函数:

typedef struct Context
{
    uint64_t    rbx;    // 0
    uint64_t    rsp;    // 8
    uint64_t    rbp;    // 16
    uint64_t    r12;    // 24
    uint64_t    r13;    // 32
    uint64_t    r14;    // 40
    uint64_t    r15;    // 48
    uint64_t    rip;    // 56
    uint64_t    break_point;    // 64
} Context_st;

main_func()
{
    ...
    Context_st contexts[1];
    Context_st mainContexts;

    // inittialize main stack and the function's stack. This should make the func return to main function, which is this one.
    _init_contexts(contexts);

    // This should backup main function's context and jump to another function with customized stack
    _run_contexts(&mainContexts, contexts);

    printf("Successfully returned\n");       // This could not be executed.

    ...
}

static void _init_contexts(Context_st pContexts[1])
{
    int mmapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
    const size_t STACK_SIZE = 512;

    asm_init_context(&(pContexts[0]));
    pContexts[0].rip = (uint64_t)_some_func;
    pContexts[0].break_point = (uint64_t)_func_to_go;
    pContexts[0].rsp = (uint64_t)mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, mmapFlags, -1, 0);
    pContexts[0].rsp += STACK_SIZE;

    return;
}

static void _run_contexts(Context_st *pMainCtx, Context_st *pSubCtx)
{
    asm_save_main_and_go(pMainCtx, pSubCtx);
    return;
}

和汇编函数:

#################################################
##
    .text
    .align 4
    .globl asm_init_context
    .type asm_init_context, @function
asm_init_context:
    movq %rbx, (%rdi)
    movq %rsp, 8(%rdi)
    movq %rbp, 16(%rdi)
    movq %r12, 24(%rdi)
    movq %r13, 32(%rdi)
    movq %r14, 40(%rdi)
    movq %r15, 48(%rdi)
    retq

#################################################
##
    .text
    .align 4
    .globl asm_save_main_and_go
    .type asm_save_main_and_go, @function
asm_save_main_and_go:

    movq %rbx, (%rdi)
    movq %rsp, 8(%rdi)
    movq %rbp, 16(%rdi)
    movq %r12, 24(%rdi)
    movq %r13, 32(%rdi)
    movq %r14, 40(%rdi)
    movq %r15, 48(%rdi)

    movl %esi, %eax
    movq (%rsi), %rbx
    movq 8(%rsi), %rsp      # This is the code which causes SIGSEGV
    movq 16(%rsi), %rbp
    movq 24(%rsi), %r12
    movq 32(%rsi), %r13
    movq 40(%rsi), %r14
    movq 48(%rsi), %r15
    movq 56(%rsi), %rdx
    push %rdx
    jmp 64(%rsi)

我已经标记了导致SIGSEGV的asm代码。如果我将其注释掉,程序可能会正确运行并返回shell。但我不知道为什么。

我做错了吗?或者如果还需要做些什么来使mmapped内存部分能够将RSP注册为自定义堆栈空间?

先谢谢你们!

11月22日更新:

非常奇怪:当我切换到另一台虚拟机时,成功调用了_func_to_go()。虽然返回后还有另一个分段错误,但由于错误堆栈,可能会出现问题......

如果我复制问题,我会不断更新。但我希望这仍然是“WorksForMe”。

特别感谢@AjayBrahmakshatriya@Ped7g。您的讨论指出了我的一些错误,我已在项目here中更正或纠正了这些错误。 : - )

0 个答案:

没有答案