我剛剛瀏覽了 Linux 內核源代碼樹并閱讀了檔案tools/include/nolibc/nolibc.h。
我syscall在這個檔案中看到了使用%r8,%r9并%r10在 clobber 串列中。
還有一條評論說:
rcx 和 r8..r11 可能會被破壞,其他則保留。
據我所知,syscall只有則會覆寫%rax,%rcx并且%r11(和記憶體)。
有沒有syscall那個 clobbers的真實體子%r8,%r9以及%r10?
uj5u.com熱心網友回復:
只有int 0x8064 位模式下的32 位系統呼叫(例如 via )和 R11 一起在這些暫存器上執行。(如果您在 64 位代碼中使用 32 位 int 0x80 Linux ABI,會發生什么?)。
syscall正確保存/恢復包括 R8、R9 和 R10 在內的所有 reg,因此使用它的用戶空間可以假設它們保留它們的值,除了 RAX 回傳值。(內核的系統呼叫入口點甚至保存了 RCX 和 R11,但此時它們已經被syscall指令本身用原始 RIP 和屏蔽前的 RFLAGS 值覆寫了。)
那些帶有 R11 的暫存器是在函式呼叫約定中被呼叫破壞的非遺留暫存器,因此內核中 C 函式的編譯器生成的代碼自然會保留 R12-R15,即使 asm 入口點沒有保存他們。
目前,64 位int 0x80入口點只是0在行程狀態結構中推送呼叫破壞的 R8-R11 暫存器,它將在回傳用戶空間之前從中恢復,而不是原始暫存器值。也許早些時候有資訊泄漏,在內核代碼回傳后它們沒有受到影響?
uj5u.com熱心網友回復:
根據 x86-64 ABI 關于系統呼叫部分 A.2 AMD64 Linux 內核約定,A.2.1 呼叫約定 [1]:
用戶級應用程式作為整數暫存器用于使序列
%rdi,%rsi,%rdx,%rcx,%r8和%r9。內核介面的用途%rdi,%rsi,%rdx,%r10,%r8和%r9。系統呼叫是通過
syscall指令完成的。內核銷毀暫存器%rcx和%r11.的編號
syscall必須在 register 中傳遞%rax。系統呼叫僅限于六個引數,沒有引數直接在堆疊上傳遞。
從
syscall, 暫存器回傳%rax包含系統呼叫的結果。-4095 和 -1 之間范圍內的值表示錯誤,它是 -errno。只有類 INTEGER 或類 MEMORY 的值被傳遞給內核。
從(2),(5)和(6),我們可以得出結論,Linux的系統呼叫x86-64的則會覆寫%rax,%rcx和%r11(和"memory")。
鏈接:https : //gitlab.com/x86-psABI/x86-64-ABI/-/wikis/x86-64-psABI [1]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/313718.html
