[libc-commits] [libc] [libc][i386] setjmp/longjmp (PR #112437)

Nick Desaulniers via libc-commits libc-commits at lists.llvm.org
Wed Oct 16 09:29:52 PDT 2024


https://github.com/nickdesaulniers updated https://github.com/llvm/llvm-project/pull/112437

>From 1d9d3d408ab24edfb58e2019e59c26a7b9aca9d2 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Thu, 3 Oct 2024 09:24:24 -0700
Subject: [PATCH 1/7] [libc][i386] setjmp/longjmp

Link: #93709
---
 libc/include/llvm-libc-types/jmp_buf.h |  7 ++++++
 libc/src/setjmp/longjmp.h              |  1 +
 libc/src/setjmp/x86_64/longjmp.cpp     | 33 ++++++++++++++++++++++++--
 libc/src/setjmp/x86_64/setjmp.cpp      | 31 +++++++++++++++++++++++-
 4 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/libc/include/llvm-libc-types/jmp_buf.h b/libc/include/llvm-libc-types/jmp_buf.h
index 60e033c6c65a95..f246e6491cf554 100644
--- a/libc/include/llvm-libc-types/jmp_buf.h
+++ b/libc/include/llvm-libc-types/jmp_buf.h
@@ -19,6 +19,13 @@ typedef struct {
   __UINT64_TYPE__ r15;
   __UINTPTR_TYPE__ rsp;
   __UINTPTR_TYPE__ rip;
+#elif defined(__i386__)
+  long ebx;
+  long esi;
+  long edi;
+  long ebp;
+  long esp;
+  long eip;
 #elif defined(__riscv)
   /* Program counter.  */
   long int __pc;
diff --git a/libc/src/setjmp/longjmp.h b/libc/src/setjmp/longjmp.h
index 7cb12b3392ae16..e8d6985f44ee4d 100644
--- a/libc/src/setjmp/longjmp.h
+++ b/libc/src/setjmp/longjmp.h
@@ -14,6 +14,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
+[[noreturn]]
 void longjmp(jmp_buf buf, int val);
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index d4b55565cb2187..f27e5f055d6f99 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -6,16 +6,44 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/setjmp/longjmp.h"
+#include "include/llvm-libc-macros/offsetof-macro.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
+#include "src/setjmp/longjmp.h"
 
-#if !defined(LIBC_TARGET_ARCH_IS_X86_64)
+#if !defined(LIBC_TARGET_ARCH_IS_X86)
 #error "Invalid file include"
 #endif
 
 namespace LIBC_NAMESPACE_DECL {
 
+#ifdef __i386__
+[[noreturn]]
+LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int val)) {
+  asm(R"(
+      mov 4(%%esp), %%edx
+
+      mov %c[ebx](%%edx), %%ebx
+      mov %c[esi](%%edx), %%esi
+      mov %c[edi](%%edx), %%edi
+      mov %c[ebp](%%edx), %%ebp
+      mov %c[esp](%%edx), %%esp
+
+      jmp *%c[eip](%%edx)
+      )"
+      ::
+      [ebx] "i"(offsetof(__jmp_buf, ebx)),
+      [esi] "i"(offsetof(__jmp_buf, esi)),
+      [edi] "i"(offsetof(__jmp_buf, edi)),
+      [ebp] "i"(offsetof(__jmp_buf, ebp)),
+      [esp] "i"(offsetof(__jmp_buf, esp)),
+      [eip] "i"(offsetof(__jmp_buf, eip)),
+      [val] "a"(val == 0 ? 1 : val) :
+      "edx");
+  __builtin_unreachable();
+}
+#else
+[[noreturn]]
 LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
   register __UINT64_TYPE__ rbx __asm__("rbx");
   register __UINT64_TYPE__ rbp __asm__("rbp");
@@ -41,5 +69,6 @@ LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
   LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r"(rsp) : "m"(buf->rsp) :);
   LIBC_INLINE_ASM("jmp *%0\n\t" : : "m"(buf->rip));
 }
+#endif
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/setjmp/x86_64/setjmp.cpp b/libc/src/setjmp/x86_64/setjmp.cpp
index f6e82642edd7da..90532c5654b33b 100644
--- a/libc/src/setjmp/x86_64/setjmp.cpp
+++ b/libc/src/setjmp/x86_64/setjmp.cpp
@@ -11,12 +11,40 @@
 #include "src/__support/macros/config.h"
 #include "src/setjmp/setjmp_impl.h"
 
-#if !defined(LIBC_TARGET_ARCH_IS_X86_64)
+#if !defined(LIBC_TARGET_ARCH_IS_X86)
 #error "Invalid file include"
 #endif
 
 namespace LIBC_NAMESPACE_DECL {
 
+#ifdef __i386__
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
+  asm(R"(
+      mov 4(%%esp), %%eax
+
+      mov %%ebx, %c[ebx](%%eax)
+      mov %%esi, %c[esi](%%eax)
+      mov %%edi, %c[edi](%%eax)
+      mov %%ebp, %c[ebp](%%eax)
+
+      lea 4(%%esp), %%ecx
+      mov %%ecx, %c[esp](%%eax)
+
+      mov (%%esp), %%ecx
+      mov %%ecx, %c[eip](%%eax)
+
+      xorl %%eax, %%eax
+      retl)" ::
+      [ebx] "i"(offsetof(__jmp_buf, ebx)),
+      [esi] "i"(offsetof(__jmp_buf, esi)),
+      [edi] "i"(offsetof(__jmp_buf, edi)),
+      [ebp] "i"(offsetof(__jmp_buf, ebp)),
+      [esp] "i"(offsetof(__jmp_buf, esp)),
+      [eip] "i"(offsetof(__jmp_buf, eip))
+      : "eax", "ecx");
+}
+#else
 [[gnu::naked]]
 LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
   asm(R"(
@@ -41,5 +69,6 @@ LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
       [rip] "i"(offsetof(__jmp_buf, rip))
       : "rax");
 }
+#endif
 
 } // namespace LIBC_NAMESPACE_DECL

>From 28d030ebff4728cd068dce0e25056b7cef8d08e4 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Tue, 15 Oct 2024 14:06:04 -0700
Subject: [PATCH 2/7] use buf

---
 libc/src/setjmp/x86_64/longjmp.cpp | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index f27e5f055d6f99..d0145e5f4fe9fd 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -19,17 +19,15 @@ namespace LIBC_NAMESPACE_DECL {
 
 #ifdef __i386__
 [[noreturn]]
-LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int val)) {
+LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
   asm(R"(
-      mov 4(%%esp), %%edx
-
-      mov %c[ebx](%%edx), %%ebx
-      mov %c[esi](%%edx), %%esi
-      mov %c[edi](%%edx), %%edi
-      mov %c[ebp](%%edx), %%ebp
-      mov %c[esp](%%edx), %%esp
+      mov %c[ebx](%[buf]), %%ebx
+      mov %c[esi](%[buf]), %%esi
+      mov %c[edi](%[buf]), %%edi
+      mov %c[ebp](%[buf]), %%ebp
+      mov %c[esp](%[buf]), %%esp
 
-      jmp *%c[eip](%%edx)
+      jmp *%c[eip](%[buf])
       )"
       ::
       [ebx] "i"(offsetof(__jmp_buf, ebx)),
@@ -38,6 +36,7 @@ LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int val)) {
       [ebp] "i"(offsetof(__jmp_buf, ebp)),
       [esp] "i"(offsetof(__jmp_buf, esp)),
       [eip] "i"(offsetof(__jmp_buf, eip)),
+      [buf] "r"(buf),
       [val] "a"(val == 0 ? 1 : val) :
       "edx");
   __builtin_unreachable();

>From 5716c9e74be72843a6fdc12ffca03d927b7f6750 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Tue, 15 Oct 2024 14:06:14 -0700
Subject: [PATCH 3/7] reformat

---
 libc/src/setjmp/x86_64/longjmp.cpp | 19 +++++++------------
 libc/src/setjmp/x86_64/setjmp.cpp  |  9 +++------
 2 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index d0145e5f4fe9fd..817672c038bbeb 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -6,10 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/setjmp/longjmp.h"
 #include "include/llvm-libc-macros/offsetof-macro.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
-#include "src/setjmp/longjmp.h"
 
 #if !defined(LIBC_TARGET_ARCH_IS_X86)
 #error "Invalid file include"
@@ -28,17 +28,12 @@ LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
       mov %c[esp](%[buf]), %%esp
 
       jmp *%c[eip](%[buf])
-      )"
-      ::
-      [ebx] "i"(offsetof(__jmp_buf, ebx)),
-      [esi] "i"(offsetof(__jmp_buf, esi)),
-      [edi] "i"(offsetof(__jmp_buf, edi)),
-      [ebp] "i"(offsetof(__jmp_buf, ebp)),
-      [esp] "i"(offsetof(__jmp_buf, esp)),
-      [eip] "i"(offsetof(__jmp_buf, eip)),
-      [buf] "r"(buf),
-      [val] "a"(val == 0 ? 1 : val) :
-      "edx");
+      )" ::[ebx] "i"(offsetof(__jmp_buf, ebx)),
+      [esi] "i"(offsetof(__jmp_buf, esi)), [edi] "i"(offsetof(__jmp_buf, edi)),
+      [ebp] "i"(offsetof(__jmp_buf, ebp)), [esp] "i"(offsetof(__jmp_buf, esp)),
+      [eip] "i"(offsetof(__jmp_buf, eip)), [buf] "r"(buf),
+      [val] "a"(val == 0 ? 1 : val)
+      : "edx");
   __builtin_unreachable();
 }
 #else
diff --git a/libc/src/setjmp/x86_64/setjmp.cpp b/libc/src/setjmp/x86_64/setjmp.cpp
index 90532c5654b33b..5ac10fa87b39a3 100644
--- a/libc/src/setjmp/x86_64/setjmp.cpp
+++ b/libc/src/setjmp/x86_64/setjmp.cpp
@@ -35,12 +35,9 @@ LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
       mov %%ecx, %c[eip](%%eax)
 
       xorl %%eax, %%eax
-      retl)" ::
-      [ebx] "i"(offsetof(__jmp_buf, ebx)),
-      [esi] "i"(offsetof(__jmp_buf, esi)),
-      [edi] "i"(offsetof(__jmp_buf, edi)),
-      [ebp] "i"(offsetof(__jmp_buf, ebp)),
-      [esp] "i"(offsetof(__jmp_buf, esp)),
+      retl)" ::[ebx] "i"(offsetof(__jmp_buf, ebx)),
+      [esi] "i"(offsetof(__jmp_buf, esi)), [edi] "i"(offsetof(__jmp_buf, edi)),
+      [ebp] "i"(offsetof(__jmp_buf, ebp)), [esp] "i"(offsetof(__jmp_buf, esp)),
       [eip] "i"(offsetof(__jmp_buf, eip))
       : "eax", "ecx");
 }

>From c161dc1b85a8fd96d21fca6f01cfcabc9aed52da Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Tue, 15 Oct 2024 14:07:19 -0700
Subject: [PATCH 4/7] remove clobber

---
 libc/src/setjmp/x86_64/longjmp.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index 817672c038bbeb..f99322881d06b8 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -32,8 +32,7 @@ LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
       [esi] "i"(offsetof(__jmp_buf, esi)), [edi] "i"(offsetof(__jmp_buf, edi)),
       [ebp] "i"(offsetof(__jmp_buf, ebp)), [esp] "i"(offsetof(__jmp_buf, esp)),
       [eip] "i"(offsetof(__jmp_buf, eip)), [buf] "r"(buf),
-      [val] "a"(val == 0 ? 1 : val)
-      : "edx");
+      [val] "a"(val == 0 ? 1 : val));
   __builtin_unreachable();
 }
 #else

>From 0c5fbc76bb8f64c47589b778d39fdd78a816d0ba Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Tue, 15 Oct 2024 14:20:04 -0700
Subject: [PATCH 5/7] simplify

---
 libc/src/setjmp/x86_64/longjmp.cpp | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index f99322881d06b8..12082ed83118fc 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -21,18 +21,16 @@ namespace LIBC_NAMESPACE_DECL {
 [[noreturn]]
 LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
   asm(R"(
-      mov %c[ebx](%[buf]), %%ebx
-      mov %c[esi](%[buf]), %%esi
-      mov %c[edi](%[buf]), %%edi
-      mov %c[ebp](%[buf]), %%ebp
-      mov %c[esp](%[buf]), %%esp
+      mov %[ebx], %%ebx
+      mov %[esi], %%esi
+      mov %[edi], %%edi
+      mov %[ebp], %%ebp
+      mov %[esp], %%esp
 
-      jmp *%c[eip](%[buf])
-      )" ::[ebx] "i"(offsetof(__jmp_buf, ebx)),
-      [esi] "i"(offsetof(__jmp_buf, esi)), [edi] "i"(offsetof(__jmp_buf, edi)),
-      [ebp] "i"(offsetof(__jmp_buf, ebp)), [esp] "i"(offsetof(__jmp_buf, esp)),
-      [eip] "i"(offsetof(__jmp_buf, eip)), [buf] "r"(buf),
-      [val] "a"(val == 0 ? 1 : val));
+      jmp *%[eip]
+      )" ::[ebx] "m"(buf->ebx),
+      [esi] "m"(buf->esi), [edi] "m"(buf->edi), [ebp] "m"(buf->ebp),
+      [esp] "m"(buf->esp), [eip] "m"(buf->eip), [val] "a"(val == 0 ? 1 : val));
   __builtin_unreachable();
 }
 #else

>From c100cf2ef285a34a3be9edd7a0af7541d2e6da0f Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Wed, 16 Oct 2024 09:27:50 -0700
Subject: [PATCH 6/7] use offsetof

---
 libc/src/setjmp/x86_64/longjmp.cpp | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/libc/src/setjmp/x86_64/longjmp.cpp b/libc/src/setjmp/x86_64/longjmp.cpp
index 12082ed83118fc..5ea1db5921c41f 100644
--- a/libc/src/setjmp/x86_64/longjmp.cpp
+++ b/libc/src/setjmp/x86_64/longjmp.cpp
@@ -18,23 +18,27 @@
 namespace LIBC_NAMESPACE_DECL {
 
 #ifdef __i386__
-[[noreturn]]
-LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
+[[gnu::naked]]
+LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf, int)) {
   asm(R"(
-      mov %[ebx], %%ebx
-      mov %[esi], %%esi
-      mov %[edi], %%edi
-      mov %[ebp], %%ebp
-      mov %[esp], %%esp
+      mov 0x4(%%esp), %%ecx
+      mov 0x8(%%esp), %%eax
+      cmpl $0x1, %%eax
+      adcl $0x0, %%eax
+
+      mov %c[ebx](%%ecx), %%ebx
+      mov %c[esi](%%ecx), %%esi
+      mov %c[edi](%%ecx), %%edi
+      mov %c[ebp](%%ecx), %%ebp
+      mov %c[esp](%%ecx), %%esp
 
-      jmp *%[eip]
-      )" ::[ebx] "m"(buf->ebx),
-      [esi] "m"(buf->esi), [edi] "m"(buf->edi), [ebp] "m"(buf->ebp),
-      [esp] "m"(buf->esp), [eip] "m"(buf->eip), [val] "a"(val == 0 ? 1 : val));
-  __builtin_unreachable();
+      jmp *%c[eip](%%ecx)
+      )" ::[ebx] "i"(offsetof(__jmp_buf, ebx)),
+      [esi] "i"(offsetof(__jmp_buf, esi)), [edi] "i"(offsetof(__jmp_buf, edi)),
+      [ebp] "i"(offsetof(__jmp_buf, ebp)), [esp] "i"(offsetof(__jmp_buf, esp)),
+      [eip] "i"(offsetof(__jmp_buf, eip)));
 }
 #else
-[[noreturn]]
 LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
   register __UINT64_TYPE__ rbx __asm__("rbx");
   register __UINT64_TYPE__ rbp __asm__("rbp");

>From d3d2e9ba41a6bd20a38272bd3cbda9f4e9724f69 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <ndesaulniers at google.com>
Date: Wed, 16 Oct 2024 09:29:35 -0700
Subject: [PATCH 7/7] remove noreturn

---
 libc/src/setjmp/longjmp.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/src/setjmp/longjmp.h b/libc/src/setjmp/longjmp.h
index e8d6985f44ee4d..7cb12b3392ae16 100644
--- a/libc/src/setjmp/longjmp.h
+++ b/libc/src/setjmp/longjmp.h
@@ -14,7 +14,6 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-[[noreturn]]
 void longjmp(jmp_buf buf, int val);
 
 } // namespace LIBC_NAMESPACE_DECL



More information about the libc-commits mailing list