summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2012-01-18 11:16:05 +0000
committerAlexander Potapenko <glider@google.com>2012-01-18 11:16:05 +0000
commit4257386879610a05ecc731676b1e140cb40cf749 (patch)
treee6b867c2dbd7edc8adf44001121f0121fc138b39 /compiler-rt
parent75afc7afe8b6f9dbe72a70ca04a47b29a4437a9c (diff)
downloadbcm5719-llvm-4257386879610a05ecc731676b1e140cb40cf749.tar.gz
bcm5719-llvm-4257386879610a05ecc731676b1e140cb40cf749.zip
Implement AsanProcMaps for Mac OS. The code from sysinfo/ is not needed anymore and should be cleaned up.
llvm-svn: 148385
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/asan_internal.h3
-rw-r--r--compiler-rt/lib/asan/asan_linux.cc12
-rw-r--r--compiler-rt/lib/asan/asan_mac.cc91
-rw-r--r--compiler-rt/lib/asan/asan_procmaps.h22
4 files changed, 114 insertions, 14 deletions
diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h
index 8a9b8580a10..54ee47e3aee 100644
--- a/compiler-rt/lib/asan/asan_internal.h
+++ b/compiler-rt/lib/asan/asan_internal.h
@@ -43,7 +43,8 @@
#ifdef __linux__
# define ASAN_USE_SYSINFO 0
#else
-# define ASAN_USE_SYSINFO 1
+// TODO(glider): clean up sysinfo.
+# define ASAN_USE_SYSINFO 0
#endif
#endif
diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc
index 2971290be52..ae45b8287ca 100644
--- a/compiler-rt/lib/asan/asan_linux.cc
+++ b/compiler-rt/lib/asan/asan_linux.cc
@@ -220,17 +220,7 @@ bool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end,
bool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset,
char filename[],
size_t filename_size) {
- AsanProcMaps proc_maps;
- uintptr_t start, end, file_offset;
- while (proc_maps.Next(&start, &end, &file_offset, filename, filename_size)) {
- if (addr >= start && addr < end) {
- *offset = (addr - start) + file_offset;
- return true;
- }
- }
- if (filename_size)
- filename[0] = '\0';
- return false;
+ return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
}
#else // __arm__
diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc
index 0d9c65a0677..80463dd663e 100644
--- a/compiler-rt/lib/asan/asan_mac.cc
+++ b/compiler-rt/lib/asan/asan_mac.cc
@@ -17,11 +17,13 @@
#include "asan_mac.h"
#include "asan_internal.h"
+#include "asan_procmaps.h"
#include "asan_stack.h"
#include "asan_thread.h"
#include "asan_thread_registry.h"
#include <crt_externs.h> // for _NSGetEnviron
+#include <mach-o/dyld.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/ucontext.h>
@@ -145,6 +147,94 @@ int AsanClose(int fd) {
return close(fd);
}
+AsanProcMaps::AsanProcMaps() {
+ Reset();
+}
+
+AsanProcMaps::~AsanProcMaps() {
+}
+
+void AsanProcMaps::Reset() {
+ // Count down from the top.
+ // TODO(glider): as per man 3 dyld, iterating over the headers with
+ // _dyld_image_count is thread-unsafe.
+ current_image_ = _dyld_image_count();
+ current_load_cmd_ = -1;
+}
+
+// Similar code is used in Google Perftools,
+// http://code.google.com/p/google-perftools.
+template<uint32_t kMagic, uint32_t kLCSegment,
+ typename MachHeader, typename SegmentCommand>
+static bool NextExtMachHelper(const mach_header* hdr,
+ int current_image, int current_load_cmd,
+ uintptr_t *start, uintptr_t *end,
+ uintptr_t *offset,
+ char filename[], size_t filename_size) {
+ if (hdr->magic != kMagic)
+ return false;
+ const char* lc = (const char *)hdr + sizeof(MachHeader);
+ // TODO(csilvers): make this not-quadradic (increment and hold state)
+ for (int j = 0; j < current_load_cmd; j++) // advance to *our* load_cmd
+ lc += ((const load_command *)lc)->cmdsize;
+ if (((const load_command *)lc)->cmd == kLCSegment) {
+ const intptr_t dlloff = _dyld_get_image_vmaddr_slide(current_image);
+ const SegmentCommand* sc = (const SegmentCommand *)lc;
+ if (start) *start = sc->vmaddr + dlloff;
+ if (end) *end = sc->vmaddr + sc->vmsize + dlloff;
+ if (offset) *offset = sc->fileoff;
+ if (filename) {
+ real_strncpy(filename, _dyld_get_image_name(current_image),
+ filename_size);
+ }
+ return true;
+ }
+ return false;
+}
+
+bool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end,
+ uintptr_t *offset, char filename[],
+ size_t filename_size) {
+ // We return a separate entry for each segment in the DLL. (TODO(csilvers):
+ // can we do better?) A DLL ("image") has load-commands, some of which
+ // talk about segment boundaries.
+ // cf image_for_address from http://svn.digium.com/view/asterisk/team/oej/minivoicemail/dlfcn.c?revision=53912
+ for (; current_image_ >= 0; current_image_--) {
+ const mach_header* hdr = _dyld_get_image_header(current_image_);
+ if (!hdr) continue;
+ if (current_load_cmd_ < 0) // set up for this image
+ current_load_cmd_ = hdr->ncmds; // again, go from the top down
+
+ // We start with the next load command (we've already looked at this one).
+ for (current_load_cmd_--; current_load_cmd_ >= 0; current_load_cmd_--) {
+#ifdef MH_MAGIC_64
+ if (NextExtMachHelper<MH_MAGIC_64, LC_SEGMENT_64,
+ struct mach_header_64, struct segment_command_64>(
+ hdr, current_image_, current_load_cmd_,
+ start, end, offset, filename, filename_size)) {
+ return true;
+ }
+#endif
+ if (NextExtMachHelper<MH_MAGIC, LC_SEGMENT,
+ struct mach_header, struct segment_command>(
+ hdr, current_image_, current_load_cmd_,
+ start, end, offset, filename, filename_size)) {
+ return true;
+ }
+ }
+ // If we get here, no more load_cmd's in this image talk about
+ // segments. Go on to the next image.
+ }
+ // We didn't find anything.
+ return false;
+}
+
+bool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset,
+ char filename[],
+ size_t filename_size) {
+ return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
+}
+
void AsanThread::SetThreadStackTopAndBottom() {
size_t stacksize = pthread_get_stacksize_np(pthread_self());
void *stackaddr = pthread_get_stackaddr_np(pthread_self());
@@ -154,7 +244,6 @@ void AsanThread::SetThreadStackTopAndBottom() {
CHECK(AddrIsInStack((uintptr_t)&local));
}
-
AsanLock::AsanLock(LinkerInitialized) {
// We assume that OS_SPINLOCK_INIT is zero
}
diff --git a/compiler-rt/lib/asan/asan_procmaps.h b/compiler-rt/lib/asan/asan_procmaps.h
index a713dde0f3a..6c9920ab0f3 100644
--- a/compiler-rt/lib/asan/asan_procmaps.h
+++ b/compiler-rt/lib/asan/asan_procmaps.h
@@ -30,13 +30,33 @@ class AsanProcMaps {
char filename[], size_t filename_size);
~AsanProcMaps();
private:
+ // Default implementation of GetObjectNameAndOffset.
+ // Quite slow, because it iterates through the whole process map for each
+ // lookup.
+ bool IterateForObjectNameAndOffset(uintptr_t addr, uintptr_t *offset,
+ char filename[], size_t filename_size) {
+ AsanProcMaps proc_maps;
+ uintptr_t start, end, file_offset;
+ while (proc_maps.Next(&start, &end, &file_offset,
+ filename, filename_size)) {
+ if (addr >= start && addr < end) {
+ *offset = (addr - start) + file_offset;
+ return true;
+ }
+ }
+ if (filename_size)
+ filename[0] = '\0';
+ return false;
+ }
+
#if defined __linux__
char *proc_self_maps_buff_;
size_t proc_self_maps_buff_mmaped_size_;
size_t proc_self_maps_buff_len_;
char *current_;
#elif defined __APPLE__
-// FIXME: Mac code goes here
+ int current_image_;
+ int current_load_cmd_;
#endif
};
OpenPOWER on IntegriCloud