Skip to content

Commit 66f968c

Browse files
[libc][setjmp] fix setjmp test via naked fn attr (#88054)
This would consistently fail for me locally, to the point where I could not run ninja libc-unit-tests without ninja libc_setjmp_unittests failing. Turns out that since I enabled -ftrivial-auto-var-init=pattern in commit 1d5c16d ("[libc] default enable -ftrivial-auto-var-init=pattern (#78776)") this has been a problem. Our x86_64 setjmp definition disabled -Wuninitialized, so we wound up clobbering these registers and instead backing up 0xAAAAAAAAAAAAAAAA rather than the actual register value. Use `naked` function attribute to avoid function prolog/epilog.
1 parent e511026 commit 66f968c

File tree

2 files changed

+24
-42
lines changed

2 files changed

+24
-42
lines changed

libc/src/setjmp/x86_64/CMakeLists.txt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ add_entrypoint_object(
88
libc.hdr.types.jmp_buf
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
1711
)
1812

1913
add_entrypoint_object(

libc/src/setjmp/x86_64/setjmp.cpp

Lines changed: 24 additions & 36 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/__support/macros/config.h"
1112
#include "src/setjmp/setjmp_impl.h"
@@ -16,42 +17,29 @@
1617

1718
namespace LIBC_NAMESPACE_DECL {
1819

19-
LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) {
20-
register __UINT64_TYPE__ rbx __asm__("rbx");
21-
register __UINT64_TYPE__ r12 __asm__("r12");
22-
register __UINT64_TYPE__ r13 __asm__("r13");
23-
register __UINT64_TYPE__ r14 __asm__("r14");
24-
register __UINT64_TYPE__ r15 __asm__("r15");
25-
26-
// We want to store the register values as is. So, we will suppress the
27-
// compiler warnings about the uninitialized variables declared above.
28-
#pragma GCC diagnostic push
29-
#pragma GCC diagnostic ignored "-Wuninitialized"
30-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->rbx) : "r"(rbx) :);
31-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r12) : "r"(r12) :);
32-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r13) : "r"(r13) :);
33-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r14) : "r"(r14) :);
34-
LIBC_INLINE_ASM("mov %1, %0\n\t" : "=m"(buf->r15) : "r"(r15) :);
35-
#pragma GCC diagnostic pop
36-
37-
// We want the rbp of the caller, which is what __builtin_frame_address(1)
38-
// should return. But, compilers generate a warning that calling
39-
// __builtin_frame_address with non-zero argument is unsafe. So, we use
40-
// the knowledge of the x86_64 ABI to fetch the callers rbp. As per the ABI,
41-
// the rbp of the caller is pushed on to the stack and then new top is saved
42-
// in this function's rbp. So, we fetch it from location at which this
43-
// functions's rbp is pointing.
44-
buf->rbp = *reinterpret_cast<__UINTPTR_TYPE__ *>(__builtin_frame_address(0));
45-
46-
// The callers stack address is exactly 2 pointer widths ahead of the current
47-
// frame pointer - between the current frame pointer and the rsp of the caller
48-
// are the return address (pushed by the x86_64 call instruction) and the
49-
// previous stack pointer as required by the x86_64 ABI.
50-
// The stack pointer is ahead because the stack grows down on x86_64.
51-
buf->rsp = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_frame_address(0)) +
52-
sizeof(__UINTPTR_TYPE__) * 2;
53-
buf->rip = reinterpret_cast<__UINTPTR_TYPE__>(__builtin_return_address(0));
54-
return 0;
20+
[[gnu::naked]]
21+
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
22+
asm(R"(
23+
mov %%rbx, %c[rbx](%%rdi)
24+
mov %%rbp, %c[rbp](%%rdi)
25+
mov %%r12, %c[r12](%%rdi)
26+
mov %%r13, %c[r13](%%rdi)
27+
mov %%r14, %c[r14](%%rdi)
28+
mov %%r15, %c[r15](%%rdi)
29+
30+
lea 8(%%rsp), %%rax
31+
mov %%rax, %c[rsp](%%rdi)
32+
33+
mov (%%rsp), %%rax
34+
mov %%rax, %c[rip](%%rdi)
35+
36+
xorl %%eax, %%eax
37+
retq)" ::[rbx] "i"(offsetof(__jmp_buf, rbx)),
38+
[rbp] "i"(offsetof(__jmp_buf, rbp)), [r12] "i"(offsetof(__jmp_buf, r12)),
39+
[r13] "i"(offsetof(__jmp_buf, r13)), [r14] "i"(offsetof(__jmp_buf, r14)),
40+
[r15] "i"(offsetof(__jmp_buf, r15)), [rsp] "i"(offsetof(__jmp_buf, rsp)),
41+
[rip] "i"(offsetof(__jmp_buf, rip))
42+
: "rax");
5543
}
5644

5745
} // namespace LIBC_NAMESPACE_DECL

0 commit comments

Comments
 (0)