Skip to content

Commit c98a544

Browse files
use naked attribute to implement setjmp
1 parent 882efcc commit c98a544

File tree

2 files changed

+25
-32
lines changed

2 files changed

+25
-32
lines changed

libc/src/setjmp/x86_64/CMakeLists.txt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,8 @@ add_entrypoint_object(
88
libc.include.setjmp
99
COMPILE_OPTIONS
1010
-O3
11-
-fno-omit-frame-pointer
12-
# TODO: Remove once one of these lands:
13-
# https://github.com/llvm/llvm-project/pull/87837
14-
# https://github.com/llvm/llvm-project/pull/88054
15-
# https://github.com/llvm/llvm-project/pull/88157
16-
-ftrivial-auto-var-init=uninitialized
11+
-fomit-frame-pointer
12+
-momit-leaf-frame-pointer
1713
)
1814

1915
add_entrypoint_object(

libc/src/setjmp/x86_64/setjmp.cpp

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "include/llvm-libc-macros/offsetof-macro.h"
910
#include "src/__support/common.h"
1011
#include "src/setjmp/setjmp_impl.h"
1112

@@ -15,33 +16,29 @@
1516

1617
namespace LIBC_NAMESPACE {
1718

19+
__attribute__((naked))
1820
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
19-
asm("mov %%rbx, %[rbx]\n\t"
20-
"mov %%r12, %[r12]\n\t"
21-
"mov %%r13, %[r13]\n\t"
22-
"mov %%r14, %[r14]\n\t"
23-
"mov %%r15, %[r15]"
24-
: [rbx] "=m"(buf->rbx), [r12] "=m"(buf->r12), [r13] "=m"(buf->r13),
25-
[r14] "=m"(buf->r14), [r15] "=m"(buf->r15));
26-
27-
// We want the rbp of the caller, which is what __builtin_frame_address(1)
28-
// should return. But, compilers generate a warning that calling
29-
// __builtin_frame_address with non-zero argument is unsafe. So, we use
30-
// the knowledge of the x86_64 ABI to fetch the callers rbp. As per the ABI,
31-
// the rbp of the caller is pushed on to the stack and then new top is saved
32-
// in this function's rbp. So, we fetch it from location at which this
33-
// functions's rbp is pointing.
34-
buf->rbp = *reinterpret_cast<__UINTPTR_TYPE__ *>(__builtin_frame_address(0));
35-
36-
// The callers stack address is exactly 2 pointer widths ahead of the current
37-
// frame pointer - between the current frame pointer and the rsp of the caller
38-
// are the return address (pushed by the x86_64 call instruction) and the
39-
// previous stack pointer as required by the x86_64 ABI.
40-
// The stack pointer is ahead because the stack grows down on x86_64.
41-
buf->rsp = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_frame_address(0)) +
42-
sizeof(__UINTPTR_TYPE__) * 2;
43-
buf->rip = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_return_address(0));
44-
return 0;
21+
asm("mov %%rbx, %c[rbx](%%rdi)\n\t"
22+
"mov %%rbp, %c[rbp](%%rdi)\n\t"
23+
"mov %%r12, %c[r12](%%rdi)\n\t"
24+
"mov %%r13, %c[r13](%%rdi)\n\t"
25+
"mov %%r14, %c[r14](%%rdi)\n\t"
26+
"mov %%r15, %c[r15](%%rdi)\n\t"
27+
28+
"lea 8(%%rsp), %%rax\n\t"
29+
"mov %%rax, %c[rsp](%%rdi)\n\t"
30+
31+
"mov %[read_rip], %c[rip](%%rdi)\n\t"
32+
33+
"xorl %%eax, %%eax\n\t"
34+
"retq"
35+
::
36+
[rbx] "i"(offsetof(__jmp_buf, rbx)), [r12] "i"(offsetof(__jmp_buf, r12)),
37+
[r13] "i"(offsetof(__jmp_buf, r13)), [r14] "i"(offsetof(__jmp_buf, r14)),
38+
[r15] "i"(offsetof(__jmp_buf, r15)), [rbp] "i"(offsetof(__jmp_buf, rbp)),
39+
[rsp] "i"(offsetof(__jmp_buf, rsp)), [rip] "i"(offsetof(__jmp_buf, rip)),
40+
[read_rip] "r" (reinterpret_cast<__UINTPTR_TYPE__>(__builtin_return_address(0)))
41+
: "rax");
4542
}
4643

4744
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)