[asan] move {linux,mac}-specific code from asan_thread.cc to asan_{linux,mac}.cc; also add asan_procmaps.h which I forgot to add on previous commit.

llvm-svn: 147586
This commit is contained in:
Kostya Serebryany 2012-01-05 01:07:27 +00:00
parent 6feb3d6650
commit 78d87d3b4b
4 changed files with 103 additions and 58 deletions

View File

@ -16,11 +16,15 @@
#include "asan_interceptors.h" #include "asan_interceptors.h"
#include "asan_internal.h" #include "asan_internal.h"
#include "asan_procmaps.h" #include "asan_procmaps.h"
#include "asan_thread.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
@ -150,6 +154,54 @@ bool AsanProcMaps::Next(uint64_t *start, uint64_t *end,
return true; return true;
} }
void AsanThread::SetThreadStackTopAndBottom() {
if (tid() == 0) {
// This is the main thread. Libpthread may not be initialized yet.
struct rlimit rl;
CHECK(getrlimit(RLIMIT_STACK, &rl) == 0);
// Find the mapping that contains a stack variable.
AsanProcMaps proc_maps;
uint64_t start, end, offset;
uint64_t prev_end = 0;
while (proc_maps.Next(&start, &end, &offset, NULL, 0)) {
if ((uintptr_t)&rl < end)
break;
prev_end = end;
}
CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end);
// Get stacksize from rlimit, but clip it so that it does not overlap
// with other mappings.
size_t stacksize = rl.rlim_cur;
if (stacksize > end - prev_end)
stacksize = end - prev_end;
if (stacksize > kMaxThreadStackSize)
stacksize = kMaxThreadStackSize;
stack_top_ = end;
stack_bottom_ = end - stacksize;
CHECK(AddrIsInStack((uintptr_t)&rl));
return;
}
pthread_attr_t attr;
CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
size_t stacksize = 0;
void *stackaddr = NULL;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
stack_top_ = (uintptr_t)stackaddr + stacksize;
stack_bottom_ = (uintptr_t)stackaddr;
// When running with unlimited stack size, we still want to set some limit.
// The unlimited stack size is caused by 'ulimit -s unlimited'.
// Also, for some reason, GNU make spawns subrocesses with unlimited stack.
if (stacksize > kMaxThreadStackSize) {
stack_bottom_ = stack_top_ - kMaxThreadStackSize;
}
CHECK(AddrIsInStack((uintptr_t)&attr));
}
} // namespace __asan } // namespace __asan
#endif // __linux__ #endif // __linux__

View File

@ -22,6 +22,7 @@
#include "asan_thread_registry.h" #include "asan_thread_registry.h"
#include <sys/mman.h> #include <sys/mman.h>
#include <pthread.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -103,6 +104,15 @@ int AsanClose(int fd) {
return close(fd); return close(fd);
} }
void AsanThread::SetThreadStackTopAndBottom() {
size_t stacksize = pthread_get_stacksize_np(pthread_self());
void *stackaddr = pthread_get_stackaddr_np(pthread_self());
stack_top_ = (uintptr_t)stackaddr;
stack_bottom_ = stack_top_ - stacksize;
int local;
CHECK(AddrIsInStack((uintptr_t)&local));
}
// Support for the following functions from libdispatch on Mac OS: // Support for the following functions from libdispatch on Mac OS:
// dispatch_async_f() // dispatch_async_f()
// dispatch_async() // dispatch_async()

View File

@ -0,0 +1,41 @@
//===-- asan_process.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a part of AddressSanitizer, an address sanity checker.
//
// Information about the process mappings.
//===----------------------------------------------------------------------===//
#ifndef ASAN_PROCMAPS_H
#define ASAN_PROCMAPS_H
#include "asan_internal.h"
namespace __asan {
class AsanProcMaps {
public:
AsanProcMaps();
bool Next(uint64_t *start, uint64_t *end, uint64_t *offset,
char filename[], size_t filename_size);
void Reset();
~AsanProcMaps();
private:
#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
#endif
};
} // namespace __asan
#endif // ASAN_PROCMAPS_H

View File

@ -18,8 +18,6 @@
#include "asan_thread_registry.h" #include "asan_thread_registry.h"
#include "asan_mapping.h" #include "asan_mapping.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <pthread.h> #include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -114,60 +112,4 @@ const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) {
return "UNKNOWN"; return "UNKNOWN";
} }
void AsanThread::SetThreadStackTopAndBottom() {
#ifdef __APPLE__
size_t stacksize = pthread_get_stacksize_np(pthread_self());
void *stackaddr = pthread_get_stackaddr_np(pthread_self());
stack_top_ = (uintptr_t)stackaddr;
stack_bottom_ = stack_top_ - stacksize;
int local;
CHECK(AddrIsInStack((uintptr_t)&local));
#else
if (tid() == 0) {
// This is the main thread. Libpthread may not be initialized yet.
struct rlimit rl;
CHECK(getrlimit(RLIMIT_STACK, &rl) == 0);
// Find the mapping that contains a stack variable.
AsanProcMaps proc_maps;
uint64_t start, end, offset;
uint64_t prev_end = 0;
while (proc_maps.Next(&start, &end, &offset, NULL, 0)) {
if ((uintptr_t)&rl < end)
break;
prev_end = end;
}
CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end);
// Get stacksize from rlimit, but clip it so that it does not overlap
// with other mappings.
size_t stacksize = rl.rlim_cur;
if (stacksize > end - prev_end)
stacksize = end - prev_end;
if (stacksize > kMaxThreadStackSize)
stacksize = kMaxThreadStackSize;
stack_top_ = end;
stack_bottom_ = end - stacksize;
CHECK(AddrIsInStack((uintptr_t)&rl));
return;
}
pthread_attr_t attr;
CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
size_t stacksize = 0;
void *stackaddr = NULL;
pthread_attr_getstack(&attr, &stackaddr, &stacksize);
pthread_attr_destroy(&attr);
stack_top_ = (uintptr_t)stackaddr + stacksize;
stack_bottom_ = (uintptr_t)stackaddr;
// When running with unlimited stack size, we still want to set some limit.
// The unlimited stack size is caused by 'ulimit -s unlimited'.
// Also, for some reason, GNU make spawns subrocesses with unlimited stack.
if (stacksize > kMaxThreadStackSize) {
stack_bottom_ = stack_top_ - kMaxThreadStackSize;
}
CHECK(AddrIsInStack((uintptr_t)&attr));
#endif
}
} // namespace __asan } // namespace __asan