我正在研究一些代码,这些代码要求我手动操作代码段的上下文然后切换到它,而不是使用makecontext。由于断言失败,我的测试程序失败了,所以我尝试使用GDB来确定结果并查看该部分失败的原因,但是,当我使用GDB v7.4.1运行它时,由于null而导致段错误在早期代码部分的地址。
上下文切换的结果如下:程序的指令指针指向函数的开头,该函数接收两个参数,指向另一个函数的指针和一些参数。 (该函数将参数传递给函数指针,然后将上下文切换回来)。
我隔离了引起此问题的代码区域,这是围绕该代码的代码的结果。
245 setcontext(runQueue->front->currContext);
(gdb) print runQueue->front->currContext->uc_mcontext.gregs[REG_RIP]
$1 = 420391
(gdb) print runQueue->front->currContext->uc_mcontext.gregs[REG_RSP]
$2 = 1077936128
(gdb) print runQueue->front->currContext->uc_mcontext.gregs[REG_RDI]
$3 = 4199321
(gdb) print runQueue->front->currContext->uc_mcontext.gregs[REG_RSI]
$4 = 10
这就在上下文切换之前。我检查了寄存器以验证程序切换到的上下文的值是否正确,并且它们是预期的(REG_RIP:4203091 == 0x402253,REG_RSP:1077936128 == 0x40400000,REG_RDI:4199321 == 0x401399,以及REG_RSI :0xa == 10)
进入上下文切换并在上下文中更改后,结果如下:
thread_func(function=0, arg=0x0) at thread.c:51
51 {
(gdb) info registers rip
rip 0x402253 0x402253 <thread_func>
(gdb) info registers rsp
rsp 0x40400000 0x40400000
(gdb) info registers rdi
rdi 0x401399 4199321
(gdb) info registers rsi
rsi 0xa 10
寄存器的值保持不变,但GDB没有正确传递参数,程序尝试使用0值,程序段错误用于访问空指针。
有没有办法解决这个问题或解决这个问题?
答案 0 :(得分:2)
寄存器的值不变,但GDB没有正确传递参数,程序尝试使用0值,程序分段错误用于访问空指针。
您对所发生事件的解释极不可能是错误的。
特别是,您声称NULL解除引用似乎主要基于此:
thread_func(function=0, arg=0x0) at thread.c:51
其中function和arg的值应分别为0x401399
和0xa
。
但是,您的功能有一个序言,并且您已经在之前停止了该序言已执行。 GDB向您显示当前包含在内存位置的值,将包含prolog之后的参数,但您还没有将它们存储在那里。尝试stepi
过去的序言(过去的说明mov %rsi,-0x20(%rbp)
),您会发现function
和arg
神奇地获得了正确的值。
如果你的程序后来崩溃了一个NULL指针取消引用,那就是因为别的事情而发生了。
P.S。在设置%rsp
时,您违反了ABI要求:x86_84要求在每个函数内%rsp
为16字节对齐。这意味着 on entry 到任何函数%rsp&0xF == 8
(你有%rsp&0xF == 0
)。这可能会导致以后崩溃,特别是如果您使用任何SSE2指令。
您可以通过将%rsp
设置为mmap_addr+8
,或将thread.c
与-mstackrealign
一起编译来解决此问题。