0

I would like to write a small thunk which will call an underlying function and then compare the value of rsp before and after the call. Critically, this code shouldn't clobber any registers.

The obvious implementation is to simply push rsp before the call, and then compare after. The problem is that push rsp itself subtracts 8 from the stack, so you should actually compare the saved value of rsp with the value after the call plus 8.

Here's one way to do it:

foo_thunk:
push rsp              ; save the value of rsp
call foo              ; call the underlying function
add rsp, 8            ; adjust rsp by 8, popping the saved value
cmp rsp, [rsp - 8]    
jne bad_rsp           ; bad foo!
ret

The problem is this accesses a value [rsp - 8] which is above rsp - i.e., not on the stack but the nebulous region above the stack. This should be where you have a red-zone, but it isn't when you don't.

What are the alternatives? Performance and code-size is important.

4

3 回答 3

0

我从原始问题中假设您想在出现错误时将 rsp调整为 8 ,然后再分支到 bad_rsp,您可以使用

foo_thunk:
    sub rsp, 8
    mov [rsp], rsp
    call foo
    cmp rsp, [rsp]
    lea rsp, [rsp+8]
    jne bad_rsp
    ret

(当然,一旦你确定 rsp 没有被保留,可能就没有必要对其进行调整,但我认为这种方法足够有用,值得一提。)

于 2017-10-24T23:46:18.950 回答
0

我想一个简单的解决方案就是使用submov调整堆栈,而不是push

foo_thunk:
sub rsp, 8            ; 16 to maintain alignment
mov [rsp], rsp        ; save the value of rsp
call foo              ; call the underlying function
cmp rsp, [rsp]    
jne bad_rsp           ; bad foo!
add rsp, 8            ; pop the stack
ret 

当然,如果被调用者foo弄乱了堆栈指针,它可能根本不会返回到调用 thunk,所以这个检查的用处有限。最好在被调用者之前作为检查ret

原来的调用者在堆栈上放了任何参数,你真的搞砸了。把支票放进去callee也解决了这个问题。

于 2017-10-24T22:33:44.220 回答
-2

自模替代方案,仅检查以下 32b 部分rsp

foo_thunk:
mov [cs:check_esp_part+2],esp
call foo              ; call the underlying function
check_esp_part:
cmp esp,0x12345678
jne bad_rsp           ; bad foo!
ret 
于 2017-10-24T22:51:25.327 回答