From 5dd5da434438c7fb018c2fec345c18ecfd403556 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 9 Feb 2021 08:57:21 -0500 Subject: [PATCH] Fix misunwind during Profile test under rr (#39553) Libunwind improperly aliases RSP and CFA, which are separate concepts. Fix that. (cherry picked from commit bbf7f9733ab25d91d2d966d05454393c17e863e0) --- deps/Versions.make | 1 + deps/checksums/unwind | 48 ++++---- deps/patches/libunwind-rsp-cfa.patch | 177 +++++++++++++++++++++++++++ deps/unwind.mk | 6 +- 4 files changed, 207 insertions(+), 25 deletions(-) create mode 100644 deps/patches/libunwind-rsp-cfa.patch diff --git a/deps/Versions.make b/deps/Versions.make index 4d7d31cfbfb37d..965bbc7332bb44 100644 --- a/deps/Versions.make +++ b/deps/Versions.make @@ -101,6 +101,7 @@ SUITESPARSE_JLL_NAME := SuiteSparse # unwind UNWIND_VER := 1.3.2 UNWIND_JLL_NAME := LibUnwind +UNWIND_JLL_VER := 1.3.2+3 # zlib ZLIB_VER := 1.2.11 diff --git a/deps/checksums/unwind b/deps/checksums/unwind index 1ec7c6189c85ad..545c756d07f9a6 100644 --- a/deps/checksums/unwind +++ b/deps/checksums/unwind @@ -1,26 +1,26 @@ LibOSXUnwind.v0.0.6+1.x86_64-apple-darwin.tar.gz/md5/fd98df2005d13aa16341c5aecba1af70 LibOSXUnwind.v0.0.6+1.x86_64-apple-darwin.tar.gz/sha512/2d2263c3e5f095ad9eba7fea7cb882a19fece8a10486489d0a15b8e81ea0f8626804c4822b8c92a26a608d568c0ff1a4e976ea6d746be47ac1a70891455162a6 -LibUnwind.v1.3.2+0.aarch64-linux-gnu.tar.gz/md5/36281b8ba75cab684c843585dc949b72 -LibUnwind.v1.3.2+0.aarch64-linux-gnu.tar.gz/sha512/7f5224fe3bfd9dd579fa2efb40b65ca785da3f7ddee1bd41e072f7f5be1ce8fa24c2eab71a1233406ce532ba9f900d1f0e288f84631684b3cbc8a0f3a8347e41 -LibUnwind.v1.3.2+0.aarch64-linux-musl.tar.gz/md5/ba21435b80f4f50fbb13cf4653e3fac3 -LibUnwind.v1.3.2+0.aarch64-linux-musl.tar.gz/sha512/25cfe1f1cbfe2b9ee748348e2b0df0fba3607dedbcf88f864e88a15544bfe0781de502157353915b62387abdb467c40e51b08e847f0d2cc096a3d2d13f061559 -LibUnwind.v1.3.2+0.armv6l-linux-gnueabihf.tar.gz/md5/81fc18e166b8de9de171ca202ee43816 -LibUnwind.v1.3.2+0.armv6l-linux-gnueabihf.tar.gz/sha512/e41f0224d79dc5725b327ad7f24eb09aef0fc687842d43eecc8ac60c4dcdc1d2877d45c88015d0e32014f8bef38712f540c27093d135dd0bc7e7eafb6bd64b18 -LibUnwind.v1.3.2+0.armv6l-linux-musleabihf.tar.gz/md5/69da77d1e7124dee0c60d4fc15cf0040 -LibUnwind.v1.3.2+0.armv6l-linux-musleabihf.tar.gz/sha512/a1c6d70971a7375c26ce761039f06a940db140b06028534557f3b608363af0da9d7ef570d5f3b388f84d9649d378293bb6b59d44cf34ebf24f0a260a6824f142 -LibUnwind.v1.3.2+0.armv7l-linux-gnueabihf.tar.gz/md5/b7a6b251f30cd6d1fc890a8be4a19476 -LibUnwind.v1.3.2+0.armv7l-linux-gnueabihf.tar.gz/sha512/d143588edb96b31de4d1347ddc867e5982ccee8a39a35f705114f6fa12aca054f14a05a24ca0850be26c62a92a4c52837e898765b3fa8fa6e5259e45eebbe281 -LibUnwind.v1.3.2+0.armv7l-linux-musleabihf.tar.gz/md5/bdfa9757e7631387cb64f3897e1847fc -LibUnwind.v1.3.2+0.armv7l-linux-musleabihf.tar.gz/sha512/54f8529bb836cddff61e0112294ae3165eb6498b0c881b59047a40e180785f63c01e4ad82bcffb045b783e015c255c7b0e2f8ec43411ff647f860ef25551f540 -LibUnwind.v1.3.2+0.i686-linux-gnu.tar.gz/md5/17b1c29c3387dc3b685e75ce402caad6 -LibUnwind.v1.3.2+0.i686-linux-gnu.tar.gz/sha512/e8551b4771acf7eb31fc5db3423905b17c545aa0895b5e5369c56186841631f188186e585f0384cfca62269e1b2fffe9d9b24274d51e1ccad9bc89c3dbf6072b -LibUnwind.v1.3.2+0.i686-linux-musl.tar.gz/md5/df7e34217c1dc931c88e573179218cf6 -LibUnwind.v1.3.2+0.i686-linux-musl.tar.gz/sha512/995318e65520eae55647b2d1065f5ac5bb15cdf7b4980000b17338c59e1657e408ba711c622b450df96712a5c1c75c85c03d7952a1fd7f0b65712fa9ac6ffbab -LibUnwind.v1.3.2+0.powerpc64le-linux-gnu.tar.gz/md5/775e9c77ff9de48d40b2a2f18e5f081e -LibUnwind.v1.3.2+0.powerpc64le-linux-gnu.tar.gz/sha512/3f4d12ba171227c11ad0e774e003742c1cd69d7e0e8ae571accea561ff930ae6aec119fc8b539caf52960886cde3978912e03d663aa7fb6416978e304767dde8 -LibUnwind.v1.3.2+0.x86_64-linux-gnu.tar.gz/md5/d63ca2bc34d4bc87498d28b47e530f54 -LibUnwind.v1.3.2+0.x86_64-linux-gnu.tar.gz/sha512/2e95d1648414fa9bccf6012a9f6690cf3c209dbb138bf59da76be538793c5caca319eed3b063f18725212844e21bd67157da2aec49ec9424e38664c23dde9f45 -LibUnwind.v1.3.2+0.x86_64-linux-musl.tar.gz/md5/56a9c951e75e38bf5787c928862924cf -LibUnwind.v1.3.2+0.x86_64-linux-musl.tar.gz/sha512/8ea0c4d0e412a3792c6d33fe6dab6ae9f4c4103341842e42a9ae7efcb31c29d977970caa383373c6694d6cd8736ce75c727fa2af8f59bc3eff8d8f93ac0b9c89 -LibUnwind.v1.3.2+0.x86_64-unknown-freebsd.tar.gz/md5/10507e55604be0137c4531b5e35fbafc -LibUnwind.v1.3.2+0.x86_64-unknown-freebsd.tar.gz/sha512/a795c02b48a3b44d6b7df0b07ed31f44c3c1e189b0732a5a41ce6f2eac952da4cc376eefab17c283a20a84aae4c3dc6618e58ca86003390b4ab396d085fa83c4 +LibUnwind.v1.3.2+3.aarch64-linux-gnu.tar.gz/md5/fba1f405a3a7c8bc4f68c17d771100b0 +LibUnwind.v1.3.2+3.aarch64-linux-gnu.tar.gz/sha512/a37d3f9da9a133bb270cc1046c7018579731897fed0ef6ab1fbeb0dde38e7be294a4e2abf41096c7edde617e266f1acc95777b34e22b6a8ced0e27b2228b0ec5 +LibUnwind.v1.3.2+3.aarch64-linux-musl.tar.gz/md5/587de98245251124c0d29b0b478374ec +LibUnwind.v1.3.2+3.aarch64-linux-musl.tar.gz/sha512/9f10eee8e4f5117dfc4689378c93ba16e205aaa89eec5681e0b1e34e7c2d334717b327cae8d5024db6a1f6a2633454cb77b577112a0a03a3282e566705c1a81e +LibUnwind.v1.3.2+3.armv6l-linux-gnueabihf.tar.gz/md5/953bfa931cb8e44d39ae22d7ccab1f22 +LibUnwind.v1.3.2+3.armv6l-linux-gnueabihf.tar.gz/sha512/54ee57c35895cbaed2160d451ca33ac9e8adf157b7f825853f7e92f8304f799f2671f5361dae7d2e7d111a3ab1f749cddb96a2c04b7b8fc7844b1e021dbc443f +LibUnwind.v1.3.2+3.armv6l-linux-musleabihf.tar.gz/md5/5d16fd194ec5a7e46e1e1679072cec0f +LibUnwind.v1.3.2+3.armv6l-linux-musleabihf.tar.gz/sha512/1ae68a77eadaf73de9de266bb3e2f61457faae6b2f971988363d2d1bebf855bdbc55ad848266335a9b3c040308e0bd3e3b66d5b66fe8807e0fb774c22bac928d +LibUnwind.v1.3.2+3.armv7l-linux-gnueabihf.tar.gz/md5/569da138256de02784ba81b01e08a3db +LibUnwind.v1.3.2+3.armv7l-linux-gnueabihf.tar.gz/sha512/264636b57ca49feb005752636671fe1c24264b15d1caca0c0808e89966a7683e7821a56e41b89cde9e32b688cf94647ae61de74f0428b7b1f92be2bed6674114 +LibUnwind.v1.3.2+3.armv7l-linux-musleabihf.tar.gz/md5/c9d2f634a742d71e471dd7ff691bf39d +LibUnwind.v1.3.2+3.armv7l-linux-musleabihf.tar.gz/sha512/01c2085d49390ace5c128507a86d23b99d746cce080cc7b6415e1c75e63082d01b047b2cf98f3f76768fb49423c5524f53d253858d82864f09e8182a86be57ad +LibUnwind.v1.3.2+3.i686-linux-gnu.tar.gz/md5/92e075574e65c735f6202cc49ec51593 +LibUnwind.v1.3.2+3.i686-linux-gnu.tar.gz/sha512/03f9a71b1b1b0752a835201248cdb2d17f076a82b0928e20f45fc2b8db0914128028c0d589ff94a97847265c216420240b2369af83c4a343d3ca37c58fdcf35a +LibUnwind.v1.3.2+3.i686-linux-musl.tar.gz/md5/fa506359a72ffdf2c3713b5724ad4413 +LibUnwind.v1.3.2+3.i686-linux-musl.tar.gz/sha512/0558e871e838e6ce265c73fd7335bd0a486722ce9a710957b2e67731c494c5781a3a37176ba758f74fee37d48ee43acf02aac5092e24230523dd537610b58720 +LibUnwind.v1.3.2+3.powerpc64le-linux-gnu.tar.gz/md5/3f76849a52550e169d6f47ef95ca3d75 +LibUnwind.v1.3.2+3.powerpc64le-linux-gnu.tar.gz/sha512/2f3a119ccf1fffa8460e2350b66bf2303d11d636e649e144750e362d2e08f61d076adda71b5441b4337eaee6fb1e95049aac87de89be1415ca80f1b69c77f310 +LibUnwind.v1.3.2+3.x86_64-linux-gnu.tar.gz/md5/624779c4bc930ae2ba5f6a5d25c73aeb +LibUnwind.v1.3.2+3.x86_64-linux-gnu.tar.gz/sha512/2eb467537e5f2acee7d5b2a5939c712ca96195584c37606d1ff1bcc0683514decefcae042f566633905472c177115c1467c1503bf331d8d7293b3026628bc138 +LibUnwind.v1.3.2+3.x86_64-linux-musl.tar.gz/md5/7ddcbe93c8bdb1edde0ffab23db3ced7 +LibUnwind.v1.3.2+3.x86_64-linux-musl.tar.gz/sha512/06901d074c15c34002957122897b6b9c449f9c64745363f6fe2886c862197cc6848ca17c3d777eac315fd1d8d90fe236a223167b0aa9fd3b625fd80e3db97655 +LibUnwind.v1.3.2+3.x86_64-unknown-freebsd.tar.gz/md5/ca388d44a8ca365b66999e4b4d1853a2 +LibUnwind.v1.3.2+3.x86_64-unknown-freebsd.tar.gz/sha512/dfbe0a6b5835b51ebea181bb996ffc8fcd8b08acf71243e171c59edb655fd65b6ba59291c10af923f75b7cbb2f52b46adf65ebdca3eee172d279ae357a35205c diff --git a/deps/patches/libunwind-rsp-cfa.patch b/deps/patches/libunwind-rsp-cfa.patch new file mode 100644 index 00000000000000..05986b0e7010a1 --- /dev/null +++ b/deps/patches/libunwind-rsp-cfa.patch @@ -0,0 +1,177 @@ +commit 66f68ab50d35bb17a7ae3ac47f17e1ba5913760c +Author: Keno Fischer +Date: Sat Feb 6 18:13:16 2021 -0500 + + x86_64: Stop aliasing RSP and CFA + + RSP and CFA are different concepts. RSP refers to the physical + register, CFA is a virtual register that serves as the base + address for various other saved registers. It is true that + in many frames these are set to alias, however this is not + a requirement. For example, a function that performs a stack + switch would likely change the rsp in the middle of the function, + but would keep the CFA at the original RSP such that saved registers + may be appropriately recovered. + + We are seeing incorrect unwinds in the Julia runtime when running + julia under rr. This is because injects code (with correct CFI) + that performs just such a stack switch [1]. GDB manages to unwind + this correctly, but libunwind incorrectly sets the rsp to the CFA + address, causing a misunwind. + + Tested on x86_64, patches for other architectures are ported, but + not tested. + + [1] https://github.com/rr-debugger/rr/blob/469c22059a4a1798d33a8a224457faf22b2c178c/src/preload/syscall_hook.S#L454 + +diff --git a/include/dwarf.h b/include/dwarf.h +index fab93c61..b845e2eb 100644 +--- a/include/dwarf.h ++++ b/include/dwarf.h +@@ -227,6 +227,7 @@ typedef enum + DWARF_WHERE_REG, /* register saved in another register */ + DWARF_WHERE_EXPR, /* register saved */ + DWARF_WHERE_VAL_EXPR, /* register has computed value */ ++ DWARF_WHERE_CFA, /* register is set to the computed cfa value */ + } + dwarf_where_t; + +@@ -309,7 +310,7 @@ typedef struct dwarf_cursor + void *as_arg; /* argument to address-space callbacks */ + unw_addr_space_t as; /* reference to per-address-space info */ + +- unw_word_t cfa; /* canonical frame address; aka frame-/stack-pointer */ ++ unw_word_t cfa; /* canonical frame address; aka frame-pointer */ + unw_word_t ip; /* instruction pointer */ + unw_word_t args_size; /* size of arguments */ + unw_word_t eh_args[UNW_TDEP_NUM_EH_REGS]; +diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c +index 7d255aee..986c4a89 100644 +--- a/src/dwarf/Gparser.c ++++ b/src/dwarf/Gparser.c +@@ -500,6 +500,8 @@ setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr) + memset (sr, 0, sizeof (*sr)); + for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) + set_reg (sr, i, DWARF_WHERE_SAME, 0); ++ // SP defaults to CFA (but is overridable) ++ set_reg (sr, UNW_TDEP_SP, DWARF_WHERE_CFA, 0); + + struct dwarf_cie_info *dci = c->pi.unwind_info; + sr->rs_current.ret_addr_column = dci->ret_addr_column; +@@ -826,6 +828,10 @@ apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs) + case DWARF_WHERE_SAME: + break; + ++ case DWARF_WHERE_CFA: ++ new_loc[i] = DWARF_VAL_LOC (c, cfa); ++ break; ++ + case DWARF_WHERE_CFAREL: + new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]); + break; +diff --git a/src/x86/Gos-freebsd.c b/src/x86/Gos-freebsd.c +index 7dd01404..1b251d02 100644 +--- a/src/x86/Gos-freebsd.c ++++ b/src/x86/Gos-freebsd.c +@@ -138,6 +138,7 @@ x86_handle_signal_frame (unw_cursor_t *cursor) + c->dwarf.loc[ST0] = DWARF_NULL_LOC; + } else if (c->sigcontext_format == X86_SCF_FREEBSD_SYSCALL) { + c->dwarf.loc[EIP] = DWARF_LOC (c->dwarf.cfa, 0); ++ c->dwarf.loc[ESP] = DWARF_VAL_LOC (c, c->dwarf.cfa + 4); + c->dwarf.loc[EAX] = DWARF_NULL_LOC; + c->dwarf.cfa += 4; + c->dwarf.use_prev_instr = 1; +diff --git a/src/x86/Gregs.c b/src/x86/Gregs.c +index 4a959261..9446d6c6 100644 +--- a/src/x86/Gregs.c ++++ b/src/x86/Gregs.c +@@ -53,7 +53,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + break; + + case UNW_X86_CFA: +- case UNW_X86_ESP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; +@@ -81,6 +80,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + case UNW_X86_ECX: loc = c->dwarf.loc[ECX]; break; + case UNW_X86_EBX: loc = c->dwarf.loc[EBX]; break; + ++ case UNW_X86_ESP: loc = c->dwarf.loc[ESP]; break; + case UNW_X86_EBP: loc = c->dwarf.loc[EBP]; break; + case UNW_X86_ESI: loc = c->dwarf.loc[ESI]; break; + case UNW_X86_EDI: loc = c->dwarf.loc[EDI]; break; +diff --git a/src/x86/Gstep.c b/src/x86/Gstep.c +index 129b739a..061dcbaa 100644 +--- a/src/x86/Gstep.c ++++ b/src/x86/Gstep.c +@@ -47,7 +47,7 @@ unw_step (unw_cursor_t *cursor) + { + /* DWARF failed, let's see if we can follow the frame-chain + or skip over the signal trampoline. */ +- struct dwarf_loc ebp_loc, eip_loc; ++ struct dwarf_loc ebp_loc, eip_loc, esp_loc; + + /* We could get here because of missing/bad unwind information. + Validate all addresses before dereferencing. */ +@@ -77,6 +77,7 @@ unw_step (unw_cursor_t *cursor) + c->dwarf.cfa); + + ebp_loc = DWARF_LOC (c->dwarf.cfa, 0); ++ esp_loc = DWARF_VAL_LOC (c, c->dwarf.cfa + 8); + eip_loc = DWARF_LOC (c->dwarf.cfa + 4, 0); + c->dwarf.cfa += 8; + +@@ -87,6 +88,7 @@ unw_step (unw_cursor_t *cursor) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + c->dwarf.loc[EBP] = ebp_loc; ++ c->dwarf.loc[ESP] = esp_loc; + c->dwarf.loc[EIP] = eip_loc; + c->dwarf.use_prev_instr = 1; + } +diff --git a/src/x86_64/Gos-freebsd.c b/src/x86_64/Gos-freebsd.c +index 883025c8..8bb101ea 100644 +--- a/src/x86_64/Gos-freebsd.c ++++ b/src/x86_64/Gos-freebsd.c +@@ -133,6 +133,7 @@ x86_64_handle_signal_frame (unw_cursor_t *cursor) + c->dwarf.loc[RCX] = c->dwarf.loc[R10]; + /* rsp_loc = DWARF_LOC(c->dwarf.cfa - 8, 0); */ + /* rbp_loc = c->dwarf.loc[RBP]; */ ++ c->dwarf.loc[RSP] = DWARF_VAL_LOC (c, c->dwarf.cfa + 8); + c->dwarf.loc[RIP] = DWARF_LOC (c->dwarf.cfa, 0); + ret = dwarf_get (&c->dwarf, c->dwarf.loc[RIP], &c->dwarf.ip); + Debug (1, "Frame Chain [RIP=0x%Lx] = 0x%Lx\n", +diff --git a/src/x86_64/Gregs.c b/src/x86_64/Gregs.c +index baf8a24f..dff5bcbe 100644 +--- a/src/x86_64/Gregs.c ++++ b/src/x86_64/Gregs.c +@@ -79,7 +79,6 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + break; + + case UNW_X86_64_CFA: +- case UNW_X86_64_RSP: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; +@@ -107,6 +106,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + case UNW_X86_64_RCX: loc = c->dwarf.loc[RCX]; break; + case UNW_X86_64_RBX: loc = c->dwarf.loc[RBX]; break; + ++ case UNW_X86_64_RSP: loc = c->dwarf.loc[RSP]; break; + case UNW_X86_64_RBP: loc = c->dwarf.loc[RBP]; break; + case UNW_X86_64_RSI: loc = c->dwarf.loc[RSI]; break; + case UNW_X86_64_RDI: loc = c->dwarf.loc[RDI]; break; +diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c +index 10498170..5425e3db 100644 +--- a/src/x86_64/Gstep.c ++++ b/src/x86_64/Gstep.c +@@ -160,7 +160,7 @@ unw_step (unw_cursor_t *cursor) + { + unw_word_t rbp1 = 0; + rbp_loc = DWARF_LOC(rbp, 0); +- rsp_loc = DWARF_NULL_LOC; ++ rsp_loc = DWARF_VAL_LOC(c, rbp + 16); + rip_loc = DWARF_LOC (rbp + 8, 0); + ret = dwarf_get (&c->dwarf, rbp_loc, &rbp1); + Debug (1, "[RBP=0x%lx] = 0x%lx (cfa = 0x%lx) -> 0x%lx\n", diff --git a/deps/unwind.mk b/deps/unwind.mk index 351f9b3df745fe..4dec41f58a32b7 100644 --- a/deps/unwind.mk +++ b/deps/unwind.mk @@ -24,7 +24,11 @@ $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-static-arm.patch-applied: $(SRCCAC cd $(SRCCACHE)/libunwind-$(UNWIND_VER) && patch -p1 -f < $(SRCDIR)/patches/libunwind-static-arm.patch echo 1 > $@ -$(BUILDDIR)/libunwind-$(UNWIND_VER)/build-configured: $(SRCCACHE)/libunwind-$(UNWIND_VER)/source-extracted $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-static-arm.patch-applied +$(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-rsp-cfa.patch-applied: $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-static-arm.patch-applied + cd $(SRCCACHE)/libunwind-$(UNWIND_VER) && patch -p1 -f -u < $(SRCDIR)/patches/libunwind-rsp-cfa.patch + echo 1 > $@ + +$(BUILDDIR)/libunwind-$(UNWIND_VER)/build-configured: $(SRCCACHE)/libunwind-$(UNWIND_VER)/source-extracted $(SRCCACHE)/libunwind-$(UNWIND_VER)/libunwind-rsp-cfa.patch-applied mkdir -p $(dir $@) cd $(dir $@) && \ $(dir $<)/configure $(CONFIGURE_COMMON) CPPFLAGS="$(CPPFLAGS) $(LIBUNWIND_CPPFLAGS)" CFLAGS="$(CFLAGS) $(LIBUNWIND_CFLAGS)" --disable-shared --disable-minidebuginfo --disable-tests