Commit 1bac7510 authored by Michael Arntzenius's avatar Michael Arntzenius

patch libunwind to not call sigprocmask from _Ux86_64_setcontext

We also modify .gitmodules so that our patches to libunwind/ don't make
git think the tree is dirty.
parent a21b6c7e
[submodule "libunwind"]
path = libunwind
url = git://git.sv.gnu.org/libunwind.git
ignore = all
[submodule "libpypa"]
path = libpypa
url = git://github.com/vinzenz/libpypa.git
......
......@@ -71,15 +71,22 @@ endif()
execute_process(COMMAND cat llvm_revision.txt WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE LLVMREV OUTPUT_STRIP_TRAILING_WHITESPACE)
# llvm and clang patches
# llvm, clang, and libunwind patches
add_custom_target(llvm_gotorev python ${CMAKE_SOURCE_DIR}/tools/git_svn_gotorev.py ${DEPS_DIR}/llvm-trunk ${LLVMREV} llvm_patches WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_custom_target(clang_gotorev python ${CMAKE_SOURCE_DIR}/tools/git_svn_gotorev.py ${DEPS_DIR}/llvm-trunk/tools/clang ${LLVMREV} clang_patches WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_custom_target(llvm_up DEPENDS llvm_gotorev clang_gotorev)
set(LIBUNWIND_PATCHES
${CMAKE_SOURCE_DIR}/libunwind_patches/0001-pyston-add-lots-of-comments.patch
${CMAKE_SOURCE_DIR}/libunwind_patches/0002-pyston-stop-x86_64-setcontext-restoring-uninitialize.patch)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/gitmodules
COMMAND git submodule update --init WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND git submodule update --init
COMMAND python ${CMAKE_SOURCE_DIR}/tools/git_am_automated.py libunwind ${LIBUNWIND_PATCHES}
COMMAND cmake -E touch ${CMAKE_BINARY_DIR}/gitmodules
DEPENDS ${CMAKE_SOURCE_DIR}/.gitmodules)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
DEPENDS ${CMAKE_SOURCE_DIR}/.gitmodules
DEPENDS ${LIBUNWIND_PATCHES})
add_custom_target(gitsubmodules DEPENDS ${CMAKE_BINARY_DIR}/gitmodules)
# llvm
......
From e1d7c78d95e4b73a311f10149d0a54547d307d5d Mon Sep 17 00:00:00 2001
From: Kevin Modzelewski <kmod@dropbox.com>
Date: Tue, 22 Apr 2014 15:50:40 -0700
Subject: [PATCH] Change the RBP-validation heuristic to allow size-0 call frames
---
include/libunwind.h | 3 +++
src/x86_64/Gstep.c | 2 +-
2 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/include/libunwind.h b/include/libunwind.h
index d11c823..d9a5f03 100644
--- a/include/libunwind.h
+++ b/include/libunwind.h
@@ -30,3 +30,6 @@
# include "libunwind-x86_64.h"
#endif /* UNW_REMOTE_ONLY */
+
+#define LIBUNWIND_PYSTON_PATCH_VERSION 0x01
+
diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c
index 9fa0967..809d60b 100644
--- a/src/x86_64/Gstep.c
+++ b/src/x86_64/Gstep.c
@@ -173,7 +173,7 @@ unw_step (unw_cursor_t *cursor)
anything about new RBP (rbp1) since it may not be a frame
pointer in the frame above. Just check we get the value. */
if (ret < 0
- || rbp <= c->dwarf.cfa
+ || rbp < c->dwarf.cfa
|| (rbp - c->dwarf.cfa) > 0x4000)
{
rip_loc = DWARF_NULL_LOC;
--
1.7.4.1
From 851b35ec5f1e27273fcf271e94364ced31baa2b5 Mon Sep 17 00:00:00 2001
From: Michael Arntzenius <daekharel@gmail.com>
Date: Mon, 18 May 2015 17:47:38 -0700
Subject: [PATCH 1/2] pyston: add lots of comments
---
src/dwarf/Gparser.c | 3 +++
src/mi/Gdyn-extract.c | 3 ++-
src/mi/Gget_proc_name.c | 3 +++
src/x86_64/Gstep.c | 2 +-
4 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c
index fefd809..a5dd943 100644
--- a/src/dwarf/Gparser.c
+++ b/src/dwarf/Gparser.c
@@ -429,6 +429,7 @@ fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
memset (&c->pi, 0, sizeof (c->pi));
/* check dynamic info first --- it overrides everything else */
+ /* TODO rntz: this might be slow when there are lots of jitted functions */
ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
c->as_arg);
if (ret == -UNW_ENOINFO)
@@ -543,6 +544,7 @@ get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
lock_acquire (&cache->lock, *saved_maskp);
}
+ /* XXX rntz: this looks dangerous. why does it need to be atomic? */
if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
{
flush_rs_cache (cache);
@@ -921,6 +923,7 @@ dwarf_create_state_record (struct dwarf_cursor *c, dwarf_state_record_t *sr)
HIDDEN int
dwarf_make_proc_info (struct dwarf_cursor *c)
{
+ /* TODO rntz: why is this #if 0'd? does the cache not work? check upstream. */
#if 0
if (c->as->caching_policy == UNW_CACHE_NONE
|| get_cached_proc_info (c) < 0)
diff --git a/src/mi/Gdyn-extract.c b/src/mi/Gdyn-extract.c
index 5258839..12ba31f 100644
--- a/src/mi/Gdyn-extract.c
+++ b/src/mi/Gdyn-extract.c
@@ -33,7 +33,8 @@ unwi_extract_dynamic_proc_info (unw_addr_space_t as, unw_word_t ip,
pi->start_ip = di->start_ip;
pi->end_ip = di->end_ip;
pi->gp = di->gp;
- pi->format = di->format;
+ pi->format = di->format; /* XXX rntz: is this wrong? */
+ /* This is the point at which we can end up knowing we'll return a non-UNW_INFO_FORMAT_DYNAMIC unwind_info field. */
switch (di->format)
{
case UNW_INFO_FORMAT_DYNAMIC:
diff --git a/src/mi/Gget_proc_name.c b/src/mi/Gget_proc_name.c
index 7251c59..485346c 100644
--- a/src/mi/Gget_proc_name.c
+++ b/src/mi/Gget_proc_name.c
@@ -55,9 +55,12 @@ get_proc_name (unw_addr_space_t as, unw_word_t ip,
buf[0] = '\0'; /* always return a valid string, even if it's empty */
+ /* FIXME rntz: this ends up copying a dwarf_cie_info pi.unwind_info,
+ * and then reading it back as an unw_dyn_info_t! */
ret = unwi_find_dynamic_proc_info (as, ip, &pi, 1, arg);
if (ret == 0)
{
+ assert(pi.format == UNW_INFO_FORMAT_DYNAMIC); /* FIXME rntz: handle this being false. */
unw_dyn_info_t *di = pi.unwind_info;
if (offp)
diff --git a/src/x86_64/Gstep.c b/src/x86_64/Gstep.c
index 809d60b..e4312af 100644
--- a/src/x86_64/Gstep.c
+++ b/src/x86_64/Gstep.c
@@ -158,7 +158,7 @@ unw_step (unw_cursor_t *cursor)
}
else
{
- unw_word_t rbp1 = 0;
+ unw_word_t rbp1 = 0; /* might want to put an assert here to check for guessing */
rbp_loc = DWARF_LOC(rbp, 0);
rsp_loc = DWARF_NULL_LOC;
rip_loc = DWARF_LOC (rbp + 8, 0);
--
2.1.0
From 3faf9111fa09e26209eb01091a8ad61c28ae6197 Mon Sep 17 00:00:00 2001
From: Michael Arntzenius <daekharel@gmail.com>
Date: Tue, 19 May 2015 14:11:27 -0700
Subject: [PATCH 2/2] pyston: stop x86_64 setcontext() restoring
(uninitialized) signal mask
---
src/x86_64/setcontext.S | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/src/x86_64/setcontext.S b/src/x86_64/setcontext.S
index 1af8b67..7bee005 100644
--- a/src/x86_64/setcontext.S
+++ b/src/x86_64/setcontext.S
@@ -47,6 +47,14 @@ _Ux86_64_setcontext:
#if defined __linux__
/* restore signal mask
sigprocmask(SIG_SETMASK, ucp->uc_sigmask, NULL, sizeof(sigset_t)) */
+
+ /* PYSTON CHANGE: for some reason, libunwind restores the signal mask
+ * in _Ux86_64_setcontext() even though _Ux86_64_getcontext doesn't
+ * initialize it! This sets our signal mask to random stack garbage,
+ * so I've commented it out. - rntz
+ */
+
+ /*
push %rdi
mov $__NR_rt_sigprocmask, %rax
lea UC_SIGMASK(%rdi), %rsi
@@ -55,21 +63,29 @@ _Ux86_64_setcontext:
mov $SIGSET_BYTE_SIZE, %r10
syscall
pop %rdi
+ */
/* restore fp state */
mov UC_MCONTEXT_FPREGS_PTR(%rdi),%r8
fldenv (%r8)
ldmxcsr FPREGS_OFFSET_MXCSR(%r8)
#elif defined __FreeBSD__
+ /* PYSTON CHANGE */
+#error Pyston doesn't support FreeBSD yet.
/* restore signal mask */
+ /* PYSTON CHANGE: Commented out for same reason as the linux code
+ * above, but I haven't tested this one. Use at your own risk. - rntz
+ */
+ /*
pushq %rdi
xorl %edx,%edx
leaq UC_SIGMASK(%rdi),%rsi
- movl $3,%edi/* SIG_SETMASK */
+ movl $3,%edi/\* SIG_SETMASK *\/
movl $SYS_sigprocmask,%eax
movq %rcx,%r10
syscall
popq %rdi
+ */
/* restore fp state */
cmpq $UC_MCONTEXT_FPOWNED_FPU,UC_MCONTEXT_OWNEDFP(%rdi)
--
2.1.0
import os, os.path
import subprocess
import sys
def main():
repo = sys.argv[1]
patches = sys.argv[2:]
gitfile = os.path.join(repo, '.git')
assert os.path.isdir(repo), "Expected to find repo at %s" % (repo,)
assert os.path.exists(gitfile), "Expected %s to exist" % (gitfile,)
for fn in patches:
assert os.path.exists(fn), "Expected a patch file/dir at %s" % (fn,)
os.chdir(repo)
code = subprocess.call(["git", "am", "--"] + patches)
if not code:
sys.exit(0)
# git am errored. recover by unconditionally aborting.
print >>sys.stderr, "----- Running `git am --abort' -----"
subprocess.check_call(["git", "am", "--abort"])
sys.exit(1)
if __name__ == '__main__':
main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment