summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2013-07-29 19:09:49 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2013-07-29 19:09:49 +0000
commit9058c07c955e2fe564eb0d8bfcd15c6eaf9cbf7f (patch)
tree29d35078bf86c5cd3c6651102420c133ef60c2bd /compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
parent52dd808bc361353d51f6f1bc166c3ff2afa00589 (diff)
downloadbcm5719-llvm-9058c07c955e2fe564eb0d8bfcd15c6eaf9cbf7f.tar.gz
bcm5719-llvm-9058c07c955e2fe564eb0d8bfcd15c6eaf9cbf7f.zip
Move UnpoisonMappedDSO to sanitizer_common.
This is so DFSan will be able to use it. Differential Revision: http://llvm-reviews.chandlerc.com/D1206 llvm-svn: 187372
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_linux.cc')
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cc37
1 files changed, 37 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
index bbc41f471bb..4b6373661c7 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
@@ -29,6 +29,7 @@
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
+#include <link.h>
#include <pthread.h>
#include <sched.h>
#include <sys/mman.h>
@@ -638,6 +639,42 @@ bool LibraryNameIs(const char *full_name, const char *base_name) {
return (name[base_name_length] == '-' || name[base_name_length] == '.');
}
+// Call cb for each region mapped by map.
+void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
+ 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 > (uptr)phdr->p_vaddr)
+ 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());
+ cb((void *)seg_start, seg_end - seg_start);
+ }
+ }
+}
+
} // namespace __sanitizer
#endif // SANITIZER_LINUX
OpenPOWER on IntegriCloud