From 3a6a2d1185ef5f53f625cb74bc6aee473fa2c201 Mon Sep 17 00:00:00 2001 From: Francois-Xavier Coudert Date: Wed, 4 May 2022 19:01:07 +0200 Subject: [PATCH] Resurrect libunwind patches Fixes #44499 --- deps/patches/llvm-libunwind-force-dwarf.patch | 179 +++++++++++++++++ .../llvm-libunwind-prologue-epilogue.patch | 183 ++++++++++++++++++ 2 files changed, 362 insertions(+) create mode 100644 deps/patches/llvm-libunwind-force-dwarf.patch create mode 100644 deps/patches/llvm-libunwind-prologue-epilogue.patch diff --git a/deps/patches/llvm-libunwind-force-dwarf.patch b/deps/patches/llvm-libunwind-force-dwarf.patch new file mode 100644 index 00000000000000..2f4d31acb8a4a6 --- /dev/null +++ b/deps/patches/llvm-libunwind-force-dwarf.patch @@ -0,0 +1,179 @@ +An updated version of this libosxunwind commit: + +Author: Keno Fischer +Date: Tue Aug 27 15:01:22 2013 -0400 + + Add option to step with DWARF + +--- +diff -pur a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h +--- a/libunwind/include/libunwind.h 2021-06-28 18:23:38.000000000 +0200 ++++ b/libunwind/include/libunwind.h 2022-05-04 18:44:24.000000000 +0200 +@@ -108,6 +108,7 @@ extern "C" { + + extern int unw_getcontext(unw_context_t *) LIBUNWIND_AVAIL; + extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; ++extern int unw_init_local_dwarf(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; + extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; + extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; + extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; +Only in b/libunwind/include: libunwind.h.orig +diff -pur a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp +--- a/libunwind/src/UnwindCursor.hpp 2021-06-28 18:23:38.000000000 +0200 ++++ b/libunwind/src/UnwindCursor.hpp 2022-05-04 18:45:11.000000000 +0200 +@@ -437,6 +437,9 @@ public: + virtual bool isSignalFrame() { + _LIBUNWIND_ABORT("isSignalFrame not implemented"); + } ++ virtual void setForceDWARF(bool) { ++ _LIBUNWIND_ABORT("setForceDWARF not implemented"); ++ } + virtual bool getFunctionName(char *, size_t, unw_word_t *) { + _LIBUNWIND_ABORT("getFunctionName not implemented"); + } +@@ -894,6 +897,7 @@ public: + virtual void getInfo(unw_proc_info_t *); + virtual void jumpto(); + virtual bool isSignalFrame(); ++ virtual void setForceDWARF(bool force); + virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); + virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); + virtual const char *getRegisterName(int num); +@@ -963,7 +967,7 @@ private: + const UnwindInfoSections §s); + int stepWithCompactEncoding() { + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +- if ( compactSaysUseDwarf() ) ++ if ( _forceDwarf || compactSaysUseDwarf() ) + return stepWithDwarfFDE(); + #endif + R dummy; +@@ -1198,6 +1202,7 @@ private: + unw_proc_info_t _info; + bool _unwindInfoMissing; + bool _isSignalFrame; ++ bool _forceDwarf; + #if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) + bool _isSigReturn = false; + #endif +@@ -1207,7 +1212,7 @@ private: + template + UnwindCursor::UnwindCursor(unw_context_t *context, A &as) + : _addressSpace(as), _registers(context), _unwindInfoMissing(false), +- _isSignalFrame(false) { ++ _isSignalFrame(false), _forceDwarf(false) { + static_assert((check_fit, unw_cursor_t>::does_fit), + "UnwindCursor<> does not fit in unw_cursor_t"); + static_assert((alignof(UnwindCursor) <= alignof(unw_cursor_t)), +@@ -1217,7 +1222,8 @@ UnwindCursor::UnwindCursor(unw_con + + template + UnwindCursor::UnwindCursor(A &as, void *) +- : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { ++ : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false), ++ _forceDwarf(false) { + memset(&_info, 0, sizeof(_info)); + // FIXME + // fill in _registers from thread arg +@@ -1273,6 +1279,10 @@ template bool U + return _isSignalFrame; + } + ++template void UnwindCursor::setForceDWARF(bool force) { ++ _forceDwarf = force; ++} ++ + #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) + + #if defined(_LIBUNWIND_ARM_EHABI) +@@ -1941,7 +1951,13 @@ void UnwindCursor::setInfoBasedOnI + // record that we have no unwind info. + if (_info.format == 0) + _unwindInfoMissing = true; ++ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) ++ if (!(_forceDwarf || compactSaysUseDwarf(&dwarfOffset))) ++ return; ++ #else + return; ++ #endif ++ + } + } + #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) +diff -pur a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp +--- a/libunwind/src/libunwind.cpp 2021-06-28 18:23:38.000000000 +0200 ++++ b/libunwind/src/libunwind.cpp 2022-05-04 18:44:24.000000000 +0200 +@@ -71,6 +71,7 @@ _LIBUNWIND_HIDDEN int __unw_init_local(u + new (reinterpret_cast *>(cursor)) + UnwindCursor( + context, LocalAddressSpace::sThisAddressSpace); ++ static_assert(sizeof(unw_cursor_t) >= sizeof(UnwindCursor), "libunwind header outdated"); + #undef REGISTER_KIND + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + co->setInfoBasedOnIPRegister(); +@@ -79,6 +80,54 @@ _LIBUNWIND_HIDDEN int __unw_init_local(u + } + _LIBUNWIND_WEAK_ALIAS(__unw_init_local, unw_init_local) + ++_LIBUNWIND_HIDDEN int __unw_init_local_dwarf(unw_cursor_t *cursor, ++ unw_context_t *context) { ++ _LIBUNWIND_TRACE_API("__unw_init_local_dwarf(cursor=%p, context=%p)", ++ static_cast(cursor), ++ static_cast(context)); ++#if defined(__i386__) ++# define REGISTER_KIND Registers_x86 ++#elif defined(__x86_64__) ++# define REGISTER_KIND Registers_x86_64 ++#elif defined(__powerpc64__) ++# define REGISTER_KIND Registers_ppc64 ++#elif defined(__ppc__) ++# define REGISTER_KIND Registers_ppc ++#elif defined(__aarch64__) ++# define REGISTER_KIND Registers_arm64 ++#elif defined(__arm__) ++# define REGISTER_KIND Registers_arm ++#elif defined(__or1k__) ++# define REGISTER_KIND Registers_or1k ++#elif defined(__hexagon__) ++# define REGISTER_KIND Registers_hexagon ++#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 ++# define REGISTER_KIND Registers_mips_o32 ++#elif defined(__mips64) ++# define REGISTER_KIND Registers_mips_newabi ++#elif defined(__mips__) ++# warning The MIPS architecture is not supported with this ABI and environment! ++#elif defined(__sparc__) ++# define REGISTER_KIND Registers_sparc ++#elif defined(__riscv) && __riscv_xlen == 64 ++# define REGISTER_KIND Registers_riscv ++#else ++# error Architecture not supported ++#endif ++ // Use "placement new" to allocate UnwindCursor in the cursor buffer. ++ new (reinterpret_cast *>(cursor)) ++ UnwindCursor( ++ context, LocalAddressSpace::sThisAddressSpace); ++ static_assert(sizeof(unw_cursor_t) >= sizeof(UnwindCursor), "libunwind header outdated"); ++#undef REGISTER_KIND ++ AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; ++ co->setForceDWARF(true); ++ co->setInfoBasedOnIPRegister(); ++ ++ return UNW_ESUCCESS; ++} ++_LIBUNWIND_WEAK_ALIAS(__unw_init_local_dwarf, unw_init_local_dwarf) ++ + /// Get value of specified register at cursor position in stack frame. + _LIBUNWIND_HIDDEN int __unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, + unw_word_t *value) { +diff -pur a/libunwind/src/libunwind_ext.h b/libunwind/src/libunwind_ext.h +--- a/libunwind/src/libunwind_ext.h 2021-06-28 18:23:38.000000000 +0200 ++++ b/libunwind/src/libunwind_ext.h 2022-05-04 18:44:24.000000000 +0200 +@@ -25,6 +25,7 @@ extern "C" { + + extern int __unw_getcontext(unw_context_t *); + extern int __unw_init_local(unw_cursor_t *, unw_context_t *); ++extern int __unw_init_local_dwarf(unw_cursor_t *, unw_context_t *); + extern int __unw_step(unw_cursor_t *); + extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *); + extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *); diff --git a/deps/patches/llvm-libunwind-prologue-epilogue.patch b/deps/patches/llvm-libunwind-prologue-epilogue.patch new file mode 100644 index 00000000000000..7dadca728f9cf4 --- /dev/null +++ b/deps/patches/llvm-libunwind-prologue-epilogue.patch @@ -0,0 +1,183 @@ +An updated version of this libosxunwind commit: + +commit ca57a5b60de4cd1daa42ed2e5d1d4aa3e96a09d1 +Author: Keno Fischer +Date: Mon Aug 26 15:28:08 2013 -0400 + + Add support for unwinding during prologue/epilogue + +--- +diff --git a/libunwind/src/CompactUnwinder.hpp b/libunwind/src/CompactUnwinder.hpp +index 1c3175dff50a..78a658ccbc27 100644 +--- a/libunwind/src/CompactUnwinder.hpp ++++ b/libunwind/src/CompactUnwinder.hpp +@@ -310,6 +310,50 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( + uint32_t savedRegistersLocations = + EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + ++ // If we have not stored EBP yet ++ if (functionStart == registers.getIP()) { ++ uint64_t rsp = registers.getSP(); ++ // old esp is ebp less return address ++ registers.setSP(rsp+8); ++ // pop return address into eip ++ registers.setIP(addressSpace.get64(rsp)); ++ ++ return UNW_STEP_SUCCESS; ++ } else if (functionStart + 1 == registers.getIP()) { ++ uint64_t rsp = registers.getSP(); ++ // old esp is ebp less return address ++ registers.setSP(rsp + 16); ++ // pop return address into eip ++ registers.setIP(addressSpace.get64(rsp + 8)); ++ ++ return UNW_STEP_SUCCESS; ++ } ++ ++ // If we're about to return, we've already popped the base pointer ++ uint8_t b = addressSpace.get8(registers.getIP()); ++ ++ // This is a hack to detect VZEROUPPER but in between popq rbp and ret ++ // It's not pretty but it works ++ if (b == 0xC5) { ++ if ((b = addressSpace.get8(registers.getIP() + 1)) == 0xF8 && ++ (b = addressSpace.get8(registers.getIP() + 2)) == 0x77) ++ b = addressSpace.get8(registers.getIP() + 3); ++ else ++ goto skip_ret; ++ } ++ ++ if (b == 0xC3 || b == 0xCB || b == 0xC2 || b == 0xCA) { ++ uint64_t rbp = registers.getSP(); ++ // old esp is ebp less return address ++ registers.setSP(rbp + 16); ++ // pop return address into eip ++ registers.setIP(addressSpace.get64(rbp + 8)); ++ ++ return UNW_STEP_SUCCESS; ++ } ++ ++ skip_ret: ++ + uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset; + for (int i = 0; i < 5; ++i) { + switch (savedRegistersLocations & 0x7) { +@@ -430,6 +474,118 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( + } + } + } ++ ++ // Note that the order of these registers is so that ++ // registersSaved[0] is the one that will be pushed onto the stack last. ++ // Thus, if we want to walk this from the top, we need to go in reverse. ++ assert(regCount <= 6); ++ ++ // check whether we are still in the prologue ++ uint64_t curAddr = functionStart; ++ if (regCount > 0) { ++ for (int8_t i = (int8_t)(regCount) - 1; i >= 0; --i) { ++ if (registers.getIP() == curAddr) { ++ // None of the registers have been modified yet, so we don't need to reload them ++ framelessUnwind(addressSpace, registers.getSP() + 8 * (regCount - (uint64_t)(i + 1)), registers); ++ return UNW_STEP_SUCCESS; ++ } else { ++ assert(curAddr < registers.getIP()); ++ } ++ ++ ++ // pushq %rbp and pushq %rbx is 1 byte. Everything else 2 ++ if ((UNWIND_X86_64_REG_RBP == registersSaved[i]) || ++ (UNWIND_X86_64_REG_RBX == registersSaved[i])) ++ curAddr += 1; ++ else ++ curAddr += 2; ++ } ++ } ++ if (registers.getIP() == curAddr) { ++ // None of the registers have been modified yet, so we don't need to reload them ++ framelessUnwind(addressSpace, registers.getSP() + 8*regCount, registers); ++ return UNW_STEP_SUCCESS; ++ } else { ++ assert(curAddr < registers.getIP()); ++ } ++ ++ ++ // And now for the epilogue ++ { ++ uint8_t i = 0; ++ uint64_t p = registers.getIP(); ++ uint8_t b = 0; ++ ++ while (true) { ++ b = addressSpace.get8(p++); ++ // This is a hack to detect VZEROUPPER but in between the popq's and ret ++ // It's not pretty but it works ++ if (b == 0xC5) { ++ if ((b = addressSpace.get8(p++)) == 0xF8 && (b = addressSpace.get8(p++)) == 0x77) ++ b = addressSpace.get8(p++); ++ else ++ break; ++ } ++ // popq %rbx popq %rbp ++ if (b == 0x5B || b == 0x5D) { ++ i++; ++ } else if (b == 0x41) { ++ b = addressSpace.get8(p++); ++ if (b == 0x5C || b == 0x5D || b == 0x5E || b == 0x5F) ++ i++; ++ else ++ break; ++ } else if (b == 0xC3 || b == 0xCB || b == 0xC2 || b == 0xCA) { ++ // i pop's haven't happened yet ++ uint64_t savedRegisters = registers.getSP() + 8 * i; ++ if (regCount > 0) { ++ for (int8_t j = (int8_t)(regCount) - 1; j >= (int8_t)(regCount) - i; --j) { ++ uint64_t addr = savedRegisters - 8 * (regCount - (uint64_t)(j)); ++ switch (registersSaved[j]) { ++ case UNWIND_X86_64_REG_RBX: ++ registers.setRBX(addressSpace.get64(addr)); ++ break; ++ case UNWIND_X86_64_REG_R12: ++ registers.setR12(addressSpace.get64(addr)); ++ break; ++ case UNWIND_X86_64_REG_R13: ++ registers.setR13(addressSpace.get64(addr)); ++ break; ++ case UNWIND_X86_64_REG_R14: ++ registers.setR14(addressSpace.get64(addr)); ++ break; ++ case UNWIND_X86_64_REG_R15: ++ registers.setR15(addressSpace.get64(addr)); ++ break; ++ case UNWIND_X86_64_REG_RBP: ++ registers.setRBP(addressSpace.get64(addr)); ++ break; ++ default: ++ _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " ++ "function starting at 0x%llX", ++ encoding, functionStart); ++ _LIBUNWIND_ABORT("invalid compact unwind encoding"); ++ } ++ } ++ } ++ framelessUnwind(addressSpace, savedRegisters, registers); ++ return UNW_STEP_SUCCESS; ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* ++ 0x10fe2733a: 5b popq %rbx ++ 0x10fe2733b: 41 5c popq %r12 ++ 0x10fe2733d: 41 5d popq %r13 ++ 0x10fe2733f: 41 5e popq %r14 ++ 0x10fe27341: 41 5f popq %r15 ++ 0x10fe27343: 5d popq %rbp ++ */ ++ ++ + uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount; + for (uint32_t i = 0; i < regCount; ++i) { + switch (registersSaved[i]) {