summaryrefslogtreecommitdiff
path: root/lib/msan/msan_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/msan/msan_linux.cc')
-rw-r--r--lib/msan/msan_linux.cc58
1 files changed, 41 insertions, 17 deletions
diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc
index 2203980c638d9..367dc904d05df 100644
--- a/lib/msan/msan_linux.cc
+++ b/lib/msan/msan_linux.cc
@@ -12,10 +12,14 @@
// Linux-specific code.
//===----------------------------------------------------------------------===//
-#ifdef __linux__
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_LINUX
#include "msan.h"
+#include <algorithm>
+#include <elf.h>
+#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
@@ -72,22 +76,6 @@ bool InitShadow(bool prot1, bool prot2, bool map_shadow, bool init_origins) {
return true;
}
-static void MsanTrap(int, siginfo_t *siginfo, void *context) {
- ucontext_t *ucontext = (ucontext_t*)context;
- uptr pc = ucontext->uc_mcontext.gregs[REG_RIP];
- uptr bp = ucontext->uc_mcontext.gregs[REG_RBP];
- PrintWarning(pc + 1 /*1 will be subtracted in StackTrace::Print */, bp);
- ucontext->uc_mcontext.gregs[REG_RIP] += 2;
-}
-
-void InstallTrapHandler() {
- struct sigaction sigact;
- internal_memset(&sigact, 0, sizeof(sigact));
- sigact.sa_sigaction = MsanTrap;
- sigact.sa_flags = SA_SIGINFO;
- CHECK_EQ(0, sigaction(SIGILL, &sigact, 0));
-}
-
void MsanDie() {
_exit(flags()->exit_code);
}
@@ -103,6 +91,42 @@ static void MsanAtExit(void) {
void InstallAtExitHandler() {
atexit(MsanAtExit);
}
+
+void UnpoisonMappedDSO(link_map *map) {
+ typedef ElfW(Phdr) Elf_Phdr;
+ typedef ElfW(Ehdr) Elf_Ehdr;
+ char *base = (char *)map->l_addr;
+ Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
+ char *phdrs = base + ehdr->e_phoff;
+ char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize;
+
+ // Find the segment with the minimum base so we can "relocate" the p_vaddr
+ // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC
+ // objects have a non-zero base.
+ uptr preferred_base = ~0ULL;
+ for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
+ Elf_Phdr *phdr = (Elf_Phdr *)iter;
+ if (phdr->p_type == PT_LOAD)
+ preferred_base = std::min(preferred_base, (uptr)phdr->p_vaddr);
+ }
+
+ // Compute the delta from the real base to get a relocation delta.
+ sptr delta = (uptr)base - preferred_base;
+ // Now we can figure out what the loader really mapped.
+ for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) {
+ Elf_Phdr *phdr = (Elf_Phdr *)iter;
+ if (phdr->p_type == PT_LOAD) {
+ uptr seg_start = phdr->p_vaddr + delta;
+ uptr seg_end = seg_start + phdr->p_memsz;
+ // None of these values are aligned. We consider the ragged edges of the
+ // load command as defined, since they are mapped from the file.
+ seg_start = RoundDownTo(seg_start, GetPageSizeCached());
+ seg_end = RoundUpTo(seg_end, GetPageSizeCached());
+ __msan_unpoison((void *)seg_start, seg_end - seg_start);
+ }
+ }
}
+} // namespace __msan
+
#endif // __linux__