Skip to content

Commit

Permalink
Fix misunwind during Profile test under rr
Browse files Browse the repository at this point in the history
Libunwind improperly aliases RSP and CFA, which are separate concepts.
Fix that.
  • Loading branch information
Keno committed Feb 8, 2021
1 parent 8e61551 commit eb88673
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 25 deletions.
1 change: 1 addition & 0 deletions deps/Versions.make
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ SUITESPARSE_JLL_NAME := SuiteSparse
# unwind
UNWIND_VER := 1.3.2
UNWIND_JLL_NAME := LibUnwind
UNWIND_JLL_VER := 1.3.2+2

# zlib
ZLIB_VER := 1.2.11
Expand Down
48 changes: 24 additions & 24 deletions deps/checksums/unwind
Original file line number Diff line number Diff line change
@@ -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+2.aarch64-linux-gnu.tar.gz/md5/804a433df152371cacdbbd8776d75223
LibUnwind.v1.3.2+2.aarch64-linux-gnu.tar.gz/sha512/b97e1b9270b7f613403575cfda55534e52187d25d1e6002d560851db52acdbacebf705134850b01913386f83d91d790c2e76ee5cd5ce5b777272e38e6a5eed25
LibUnwind.v1.3.2+2.aarch64-linux-musl.tar.gz/md5/dc0ff07c672fe213854d3d9ccd997b90
LibUnwind.v1.3.2+2.aarch64-linux-musl.tar.gz/sha512/18944e1806ad655a726d93ccc572459bf1b848c1504b41d22c664394ad3d499cec3665a9df2535631ad5bef95ecdf535ee32fd517c9d8016ff69de2ffe6276b4
LibUnwind.v1.3.2+2.armv6l-linux-gnueabihf.tar.gz/md5/d30985089d00d61a61250f6edeb4aaaa
LibUnwind.v1.3.2+2.armv6l-linux-gnueabihf.tar.gz/sha512/78e53257b69a8e3356b946ad5ab6f806e9b7354347e3727b077f79738342f88ebb6c8b52a6a44a07ccd8f6bd3e3757612434212a8ebcea0ec4d316feeff2ee3c
LibUnwind.v1.3.2+2.armv6l-linux-musleabihf.tar.gz/md5/9907df61070067241f1b3a118ecbc239
LibUnwind.v1.3.2+2.armv6l-linux-musleabihf.tar.gz/sha512/2488c6122df3cc74fb144e802f87c5e995bd77161e95b875e0f3bf94d26a8f7a0877ebb1ca53e227d0992c7ce9e5933b7d4f8dcf4c361fbe12d144f99bbe77b9
LibUnwind.v1.3.2+2.armv7l-linux-gnueabihf.tar.gz/md5/f14f43d80f0b455925c18074295b96ba
LibUnwind.v1.3.2+2.armv7l-linux-gnueabihf.tar.gz/sha512/f39458d5e1bcef84d9cc071d4752638511d9b700738b8c87ea17e5cbc494b55f074696ee5fbed0f598042992a6532541bf3f100c36047d93bf5950358311dccf
LibUnwind.v1.3.2+2.armv7l-linux-musleabihf.tar.gz/md5/24c9c13973ee564f0773400f3352a37a
LibUnwind.v1.3.2+2.armv7l-linux-musleabihf.tar.gz/sha512/7089f0df60a15485f1a00b538281c21bcec8cba34da895eb886af810957b84d522e180ca90a025c921783feffbf52509736a3ca7d4668e9aaa2fbf711987b8d6
LibUnwind.v1.3.2+2.i686-linux-gnu.tar.gz/md5/c70a410cfecb9a055230752c6544d9a6
LibUnwind.v1.3.2+2.i686-linux-gnu.tar.gz/sha512/d78946e60a25d9a5ce3d1700b4d50f8267b445e805cd612521f26fd3019f63252686e4f43565b5c38181af3111d68a7388632acde643537df9f74b1ce45904ed
LibUnwind.v1.3.2+2.i686-linux-musl.tar.gz/md5/4e497d70a2e3278390e0e4b2ce14a02c
LibUnwind.v1.3.2+2.i686-linux-musl.tar.gz/sha512/2d792c0253f32f2eb64e4baf524c9389b5fcc22c578ec8ad091e288a14dee307adf4d25060775b1e3a075f19728b5981a22483dbf9a86ecba13b5f4c719fdc91
LibUnwind.v1.3.2+2.powerpc64le-linux-gnu.tar.gz/md5/8dcd7d7ebd88b9c13e6a0586d9c1d6d0
LibUnwind.v1.3.2+2.powerpc64le-linux-gnu.tar.gz/sha512/93be4f73777d5b4dcf48e433e2b4d23448f68ea0460cd16254321606164f545cc74b07cb9ed693cc942520383da971a3bfefbd3d654e13c48d200c4421ce8957
LibUnwind.v1.3.2+2.x86_64-linux-gnu.tar.gz/md5/a61cf0ba67ecca5c3c4347152bea4c03
LibUnwind.v1.3.2+2.x86_64-linux-gnu.tar.gz/sha512/3515e475b1a7777f566a0241bd6e5612b2e5fe64c2d6843993a928fd8fa3d69faa6fe36026dc5709662f2839863edc550a9d6fbd7e1c1fcd0be232b31b9f61da
LibUnwind.v1.3.2+2.x86_64-linux-musl.tar.gz/md5/2914de22bda4d78f233bed4f7515c050
LibUnwind.v1.3.2+2.x86_64-linux-musl.tar.gz/sha512/359a55667f93c87952bf8f3a94352325955484db8ede0b4cf14194b325ecf7c79eed8bc79861d4bd46028f4f98e76870cdfa68bfa50f19aeadd896b0d806e6bd
LibUnwind.v1.3.2+2.x86_64-unknown-freebsd.tar.gz/md5/c488f94027d99993ad496180ea49c5a6
LibUnwind.v1.3.2+2.x86_64-unknown-freebsd.tar.gz/sha512/5525009d97c5aaf08b1fb5416747a765f3c9f2218912fbb388bc00f632c948f43cd4e323670b612b60d7a04fd8d5de442b4ef8c28acc1da757f8973d9739a4fc
144 changes: 144 additions & 0 deletions deps/patches/libunwind-rsp-cfa.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
commit 9f618be34ca7f632fcbbc3bbc370b89786534109
Author: Keno Fischer <keno@juliacomputing.com>
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/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..a68d2433 100644
--- a/src/x86/Gstep.c
+++ b/src/x86/Gstep.c
@@ -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);
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/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..963c60c2 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);
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",
6 changes: 5 additions & 1 deletion deps/unwind.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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)" --enable-shared --disable-minidebuginfo --disable-tests
Expand Down

0 comments on commit eb88673

Please sign in to comment.