diff options
Diffstat (limited to 'lib/msan/msan_linux.cc')
-rw-r--r-- | lib/msan/msan_linux.cc | 58 |
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__ |