[libc-commits] [libc] [libc] add checksum for jmpbuf (PR #101110)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Tue Jul 30 10:48:05 PDT 2024


================
@@ -7,39 +7,63 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/setjmp/longjmp.h"
+#include "include/llvm-libc-types/jmp_buf.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
+#include "src/setjmp/checksum.h"
 
 #if !defined(LIBC_TARGET_ARCH_IS_X86_64)
 #error "Invalid file include"
 #endif
 
 namespace LIBC_NAMESPACE_DECL {
 
+[[gnu::naked]]
 LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
-  register __UINT64_TYPE__ rbx __asm__("rbx");
-  register __UINT64_TYPE__ rbp __asm__("rbp");
-  register __UINT64_TYPE__ r12 __asm__("r12");
-  register __UINT64_TYPE__ r13 __asm__("r13");
-  register __UINT64_TYPE__ r14 __asm__("r14");
-  register __UINT64_TYPE__ r15 __asm__("r15");
-  register __UINT64_TYPE__ rsp __asm__("rsp");
-  register __UINT64_TYPE__ rax __asm__("rax");
-
-  // ABI requires that the return value should be stored in rax. So, we store
-  // |val| in rax. Note that this has to happen before we restore the registers
-  // from values in |buf|. Otherwise, once rsp and rbp are updated, we cannot
-  // read |val|.
-  val = val == 0 ? 1 : val;
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rax) : "m"(val) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rbx) : "m"(buf->rbx) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rbp) : "m"(buf->rbp) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r12) : "m"(buf->r12) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r13) : "m"(buf->r13) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r14) : "m"(buf->r14) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(r15) : "m"(buf->r15) :);
-  LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rsp) : "m"(buf->rsp) :);
-  LIBC_INLINE_ASM("jmp *%0\n\t" : : "m"(buf->rip));
+  asm(R"(
+   pushq %%rbp
+   pushq %%rbx
+   mov  %%rdi, %%rbp
+   mov  %%esi, %%ebx
+   subq $8, %%rsp
+   call %P0
+   addq $8, %%rsp
+   mov  %%ebx, %%esi
+   mov  %%rbp, %%rdi
+   popq %%rbx
+   popq %%rbp
+ )" ::"i"(jmpbuf::verify)
+      : "rax", "rcx", "rdx", "r8", "r9", "r10", "r11");
+
+  register __UINT64_TYPE__ rcx __asm__("rcx");
+  // Load cookie
+  asm("mov %1, %0\n\t" : "=r"(rcx) : "m"(jmpbuf::register_mangle_cookie));
+
+  // load registers from buffer
+  // do not pass any invalid values into registers
+#define RECOVER(REG)                                                           \
+  asm("mov %c[" #REG "](%%rdi), %%rdx\n\t"                                     \
+      "xor %%rdx, %%rcx\n\t"                                                   \
+      "mov %%rdx, %%" #REG "\n\t" ::[REG] "i"(offsetof(__jmp_buf, REG))        \
+      : "rdx");
----------------
SchrodingerZhu wrote:

You are right. It should be an output register.

https://github.com/llvm/llvm-project/pull/101110


More information about the libc-commits mailing list