summaryrefslogtreecommitdiff
path: root/lib/esan
diff options
context:
space:
mode:
authorDerek Bruening <bruening@google.com>2016-06-13 21:50:00 +0000
committerDerek Bruening <bruening@google.com>2016-06-13 21:50:00 +0000
commit2a8f0a92c347dbc714cab40a5c61cf336fa0be18 (patch)
treebd6fb5ac0bc518fa102a32c37d87dfb4ddc05819 /lib/esan
parent97a35f8a8e9741e9157c0afdbb48a9db99d8a718 (diff)
[sanitizer][esan] Add internal_sigaction_syscall
Summary: Adds a version of sigaction that uses a raw system call, to avoid circular dependencies and support calling sigaction prior to setting up interceptors. The new sigaction relies on an assembly sigreturn routine for its restorer, which is Linux x86_64-only for now. Uses the new sigaction to initialize the working set tool's shadow fault handler prior to libc interceptor being set up. This is required to support instrumentation invoked during interceptor setup, which happens with an instrumented tcmalloc or other allocator compiled with esan. Adds a test that emulates an instrumented allocator. Reviewers: aizatsky Subscribers: vitalybuka, tberghammer, zhaoqin, danalbert, kcc, srhines, eugenis, llvm-commits, kubabrecka Differential Revision: http://reviews.llvm.org/D21083 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@272591 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/esan')
-rw-r--r--lib/esan/esan.cpp3
-rw-r--r--lib/esan/esan_interceptors.cpp6
-rw-r--r--lib/esan/working_set.cpp5
-rw-r--r--lib/esan/working_set.h1
4 files changed, 14 insertions, 1 deletions
diff --git a/lib/esan/esan.cpp b/lib/esan/esan.cpp
index e7399e219..e6d6aff31 100644
--- a/lib/esan/esan.cpp
+++ b/lib/esan/esan.cpp
@@ -197,6 +197,9 @@ void initializeLibrary(ToolType Tool) {
}
initializeShadow();
+ if (__esan_which_tool == ESAN_WorkingSet)
+ initializeShadowWorkingSet();
+
initializeInterceptors();
if (__esan_which_tool == ESAN_CacheFrag) {
diff --git a/lib/esan/esan_interceptors.cpp b/lib/esan/esan_interceptors.cpp
index 5d4edb51d..7aefeb664 100644
--- a/lib/esan/esan_interceptors.cpp
+++ b/lib/esan/esan_interceptors.cpp
@@ -17,6 +17,7 @@
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
using namespace __esan; // NOLINT
@@ -397,6 +398,11 @@ INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
// This is required to properly use internal_sigaction.
namespace __sanitizer {
int real_sigaction(int signum, const void *act, void *oldact) {
+ if (REAL(sigaction) == nullptr) {
+ // With an instrumented allocator, this is called during interceptor init
+ // and we need a raw syscall solution.
+ return internal_sigaction_syscall(signum, act, oldact);
+ }
return REAL(sigaction)(signum, (const struct sigaction *)act,
(struct sigaction *)oldact);
}
diff --git a/lib/esan/working_set.cpp b/lib/esan/working_set.cpp
index 9e7520f49..622fd29e8 100644
--- a/lib/esan/working_set.cpp
+++ b/lib/esan/working_set.cpp
@@ -182,10 +182,13 @@ static void takeSample(void *Arg) {
}
}
-void initializeWorkingSet() {
+// Initialization that must be done before any instrumented code is executed.
+void initializeShadowWorkingSet() {
CHECK(getFlags()->cache_line_size == CacheLineSize);
registerMemoryFaultHandler();
+}
+void initializeWorkingSet() {
if (getFlags()->record_snapshots) {
for (u32 i = 0; i < NumFreq; ++i)
SizePerFreq[i].initialize(CircularBufferSizes[i]);
diff --git a/lib/esan/working_set.h b/lib/esan/working_set.h
index 3750a480a..034dfe6d9 100644
--- a/lib/esan/working_set.h
+++ b/lib/esan/working_set.h
@@ -21,6 +21,7 @@
namespace __esan {
void initializeWorkingSet();
+void initializeShadowWorkingSet();
int finalizeWorkingSet();
void processRangeAccessWorkingSet(uptr PC, uptr Addr, SIZE_T Size,
bool IsWrite);