[lld] 0f24ffc - [lld/mac] Don't fold UNWIND_X86_64_MODE_STACK_IND unwind entries
Nico Weber via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 27 03:49:45 PDT 2021
Author: Nico Weber
Date: 2021-06-27T06:49:32-04:00
New Revision: 0f24ffcdfa9bb2b6380cedbb24f16d4ab9920dd7
URL: https://github.com/llvm/llvm-project/commit/0f24ffcdfa9bb2b6380cedbb24f16d4ab9920dd7
DIFF: https://github.com/llvm/llvm-project/commit/0f24ffcdfa9bb2b6380cedbb24f16d4ab9920dd7.diff
LOG: [lld/mac] Don't fold UNWIND_X86_64_MODE_STACK_IND unwind entries
libunwind uses unwind info to find the function address belonging
to the current instruction pointer. libunwind/src/CompactUnwinder.hpp's
step functions read functionStart for UNWIND_X86_64_MODE_STACK_IND
(and for nothing else), so these encodings need a dedicated entry
per function, so that the runtime can get the stacksize off the
`subq` instrunction in the function's prologue.
This matches ld64.
(CompactUnwinder.hpp from https://opensource.apple.com/source/libunwind/
also reads functionStart in a few more cases if `SUPPORT_OLD_BINARIES` is set,
but it defaults to 0, and ld64 seems to not worry about these additional
cases.)
Related upstream bug: https://crbug.com/1220175
Differential Revision: https://reviews.llvm.org/D104978
Added:
lld/test/MachO/compact-unwind-stack-ind.s
Modified:
lld/MachO/UnwindInfoSection.cpp
Removed:
################################################################################
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 8ad71c04f866d..6e9f4ff92aa27 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -316,6 +316,31 @@ static void addEntriesForFunctionsWithoutUnwindInfo(
markNoUnwindInfo(d);
}
+static bool canFoldEncoding(compact_unwind_encoding_t encoding) {
+ // From compact_unwind_encoding.h:
+ // UNWIND_X86_64_MODE_STACK_IND:
+ // A "frameless" (RBP not used as frame pointer) function large constant
+ // stack size. This case is like the previous, except the stack size is too
+ // large to encode in the compact unwind encoding. Instead it requires that
+ // the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
+ // encoding contains the offset to the nnnnnnnn value in the function in
+ // UNWIND_X86_64_FRAMELESS_STACK_SIZE.
+ // Since this means the unwinder has to look at the `subq` in the function
+ // of the unwind info's unwind address, two functions that have identical
+ // unwind info can't be folded if it's using this encoding since both
+ // entries need unique addresses.
+ static_assert(UNWIND_X86_64_MODE_MASK == UNWIND_X86_MODE_MASK, "");
+ static_assert(UNWIND_X86_64_MODE_STACK_IND == UNWIND_X86_MODE_STACK_IND, "");
+ if ((target->cpuType == CPU_TYPE_X86_64 || target->cpuType == CPU_TYPE_X86) &&
+ (encoding & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_STACK_IND) {
+ // FIXME: Consider passing in the two function addresses and getting
+ // their two stack sizes off the `subq` and only returning false if they're
+ // actually
diff erent.
+ return false;
+ }
+ return true;
+}
+
// Scan the __LD,__compact_unwind entries and compute the space needs of
// __TEXT,__unwind_info and __TEXT,__eh_frame
template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
@@ -377,7 +402,8 @@ template <class Ptr> void UnwindInfoSectionImpl<Ptr>::finalize() {
while (++foldEnd < cuPtrVector.end() &&
(*foldBegin)->encoding == (*foldEnd)->encoding &&
(*foldBegin)->personality == (*foldEnd)->personality &&
- (*foldBegin)->lsda == (*foldEnd)->lsda)
+ (*foldBegin)->lsda == (*foldEnd)->lsda &&
+ canFoldEncoding((*foldEnd)->encoding))
;
*foldWrite++ = *foldBegin;
foldBegin = foldEnd;
diff --git a/lld/test/MachO/compact-unwind-stack-ind.s b/lld/test/MachO/compact-unwind-stack-ind.s
new file mode 100644
index 0000000000000..13d5e929d2dbf
--- /dev/null
+++ b/lld/test/MachO/compact-unwind-stack-ind.s
@@ -0,0 +1,54 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %s -o %t.o
+# RUN: %lld -arch x86_64 -dylib %t.o -o %t.dylib
+# RUN: llvm-objdump --macho --syms --unwind-info %t.dylib | FileCheck %s
+
+## Both _f and _g have the same compact unwind encoding,
+## but
diff erent stack sizes. So their compact unwindings
+## can't be merged.
+# CHECK: SYMBOL TABLE:
+# CHECK: [[#%x,F:]] g F __TEXT,__text _f
+# CHECK: [[#%x,G:]] g F __TEXT,__text _g
+# CHECK: Number of common encodings in array: 0x1
+# CHECK: Common encodings: (count = 1)
+# CHECK: encoding[0]: 0x03032000
+# CHECK: Second level indices:
+# CHECK: Second level index[0]:
+# CHECK: [0]: function offset=0x[[#%.8x,F]], encoding[0]=0x03032000
+# CHECK: [1]: function offset=0x[[#%.8x,G]], encoding[0]=0x03032000
+
+## Based on compiling
+## int f() {
+## char alloca[3260] = { 0 };
+## return alloca[0];
+## }
+##
+## int g() {
+## char alloca[2560] = { 0 };
+## return alloca[0];
+## }
+## with `-fomit-frame-pointer -fno-stack-protector -S`.
+.section __TEXT,__text,regular,pure_instructions
+.build_version macos, 10, 15 sdk_version 10, 15, 6
+
+.globl _f
+.p2align 4, 0x90
+_f:
+ .cfi_startproc
+ subq $3272, %rsp
+ .cfi_def_cfa_offset 3280
+ addq $3272, %rsp
+ retq
+ .cfi_endproc
+
+.globl _g
+.p2align 4, 0x90
+_g:
+ .cfi_startproc
+ subq $2568, %rsp
+ .cfi_def_cfa_offset 2576
+ addq $2568, %rsp
+ retq
+ .cfi_endproc
+
+.subsections_via_symbols
More information about the llvm-commits
mailing list