aboutsummaryrefslogtreecommitdiff
path: root/libsanitizer/sanitizer_common/sanitizer_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libsanitizer/sanitizer_common/sanitizer_win.cc')
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_win.cc184
1 files changed, 157 insertions, 27 deletions
diff --git a/libsanitizer/sanitizer_common/sanitizer_win.cc b/libsanitizer/sanitizer_common/sanitizer_win.cc
index 6952655..0a5fe81 100644
--- a/libsanitizer/sanitizer_common/sanitizer_win.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_win.cc
@@ -9,7 +9,10 @@
// run-time libraries and implements windows-specific functions from
// sanitizer_libc.h.
//===----------------------------------------------------------------------===//
-#ifdef _WIN32
+
+#include "sanitizer_platform.h"
+#if SANITIZER_WINDOWS
+
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#include <stdlib.h>
@@ -18,11 +21,14 @@
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
-#include "sanitizer_placement_new.h"
#include "sanitizer_mutex.h"
+#include "sanitizer_placement_new.h"
+#include "sanitizer_stacktrace.h"
namespace __sanitizer {
+#include "sanitizer_syscall_generic.inc"
+
// --------------------- sanitizer_common.h
uptr GetPageSize() {
return 1U << 14; // FIXME: is this configurable?
@@ -32,18 +38,30 @@ uptr GetMmapGranularity() {
return 1U << 16; // FIXME: is this configurable?
}
+uptr GetMaxVirtualAddress() {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return (uptr)si.lpMaximumApplicationAddress;
+}
+
bool FileExists(const char *filename) {
UNIMPLEMENTED();
}
-int GetPid() {
+uptr internal_getpid() {
return GetProcessId(GetCurrentProcess());
}
-uptr GetThreadSelf() {
+// In contrast to POSIX, on Windows GetCurrentThreadId()
+// returns a system-unique identifier.
+uptr GetTid() {
return GetCurrentThreadId();
}
+uptr GetThreadSelf() {
+ return GetTid();
+}
+
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom) {
CHECK(stack_top);
@@ -109,19 +127,38 @@ void *MapFileToMemory(const char *file_name, uptr *buff_size) {
UNIMPLEMENTED();
}
-const char *GetEnv(const char *name) {
- static char env_buffer[32767] = {};
+static const int kMaxEnvNameLength = 128;
+static const DWORD kMaxEnvValueLength = 32767;
- // Note: this implementation stores the result in a static buffer so we only
- // allow it to be called just once.
- static bool called_once = false;
- if (called_once)
- UNIMPLEMENTED();
- called_once = true;
+namespace {
+
+struct EnvVariable {
+ char name[kMaxEnvNameLength];
+ char value[kMaxEnvValueLength];
+};
- DWORD rv = GetEnvironmentVariableA(name, env_buffer, sizeof(env_buffer));
- if (rv > 0 && rv < sizeof(env_buffer))
- return env_buffer;
+} // namespace
+
+static const int kEnvVariables = 5;
+static EnvVariable env_vars[kEnvVariables];
+static int num_env_vars;
+
+const char *GetEnv(const char *name) {
+ // Note: this implementation caches the values of the environment variables
+ // and limits their quantity.
+ for (int i = 0; i < num_env_vars; i++) {
+ if (0 == internal_strcmp(name, env_vars[i].name))
+ return env_vars[i].value;
+ }
+ CHECK_LT(num_env_vars, kEnvVariables);
+ DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
+ kMaxEnvValueLength);
+ if (rv > 0 && rv < kMaxEnvValueLength) {
+ CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
+ internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
+ num_env_vars++;
+ return env_vars[num_env_vars - 1].value;
+ }
return 0;
}
@@ -157,6 +194,11 @@ void SetStackSizeLimitInBytes(uptr limit) {
UNIMPLEMENTED();
}
+char *FindPathToBinary(const char *name) {
+ // Nothing here for now.
+ return 0;
+}
+
void SleepForSeconds(int seconds) {
Sleep(seconds * 1000);
}
@@ -165,11 +207,20 @@ void SleepForMillis(int millis) {
Sleep(millis);
}
+u64 NanoTime() {
+ return 0;
+}
+
void Abort() {
abort();
_exit(-1); // abort is not NORETURN on Windows.
}
+uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
+ string_predicate_t filter) {
+ UNIMPLEMENTED();
+};
+
#ifndef SANITIZER_GO
int Atexit(void (*function)(void)) {
return atexit(function);
@@ -177,16 +228,16 @@ int Atexit(void (*function)(void)) {
#endif
// ------------------ sanitizer_libc.h
-void *internal_mmap(void *addr, uptr length, int prot, int flags,
- int fd, u64 offset) {
+uptr internal_mmap(void *addr, uptr length, int prot, int flags,
+ int fd, u64 offset) {
UNIMPLEMENTED();
}
-int internal_munmap(void *addr, uptr length) {
+uptr internal_munmap(void *addr, uptr length) {
UNIMPLEMENTED();
}
-int internal_close(fd_t fd) {
+uptr internal_close(fd_t fd) {
UNIMPLEMENTED();
}
@@ -194,15 +245,15 @@ int internal_isatty(fd_t fd) {
return _isatty(fd);
}
-fd_t internal_open(const char *filename, int flags) {
+uptr internal_open(const char *filename, int flags) {
UNIMPLEMENTED();
}
-fd_t internal_open(const char *filename, int flags, u32 mode) {
+uptr internal_open(const char *filename, int flags, u32 mode) {
UNIMPLEMENTED();
}
-fd_t OpenFile(const char *filename, bool write) {
+uptr OpenFile(const char *filename, bool write) {
UNIMPLEMENTED();
}
@@ -222,15 +273,15 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) {
return ret;
}
-int internal_stat(const char *path, void *buf) {
+uptr internal_stat(const char *path, void *buf) {
UNIMPLEMENTED();
}
-int internal_lstat(const char *path, void *buf) {
+uptr internal_lstat(const char *path, void *buf) {
UNIMPLEMENTED();
}
-int internal_fstat(fd_t fd, void *buf) {
+uptr internal_fstat(fd_t fd, void *buf) {
UNIMPLEMENTED();
}
@@ -238,7 +289,7 @@ uptr internal_filesize(fd_t fd) {
UNIMPLEMENTED();
}
-int internal_dup2(int oldfd, int newfd) {
+uptr internal_dup2(int oldfd, int newfd) {
UNIMPLEMENTED();
}
@@ -246,7 +297,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
UNIMPLEMENTED();
}
-int internal_sched_yield() {
+uptr internal_sched_yield() {
Sleep(0);
return 0;
}
@@ -268,6 +319,12 @@ BlockingMutex::BlockingMutex(LinkerInitialized li) {
owner_ = LOCK_READY;
}
+BlockingMutex::BlockingMutex() {
+ CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
+ InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
+ owner_ = LOCK_READY;
+}
+
void BlockingMutex::Lock() {
if (owner_ == LOCK_UNINITIALIZED) {
// FIXME: hm, global BlockingMutex objects are not initialized?!?
@@ -289,6 +346,79 @@ void BlockingMutex::Unlock() {
LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
}
+void BlockingMutex::CheckLocked() {
+ CHECK_EQ(owner_, GetThreadSelf());
+}
+
+uptr GetTlsSize() {
+ return 0;
+}
+
+void InitTlsSize() {
+}
+
+void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
+ uptr *tls_addr, uptr *tls_size) {
+#ifdef SANITIZER_GO
+ *stk_addr = 0;
+ *stk_size = 0;
+ *tls_addr = 0;
+ *tls_size = 0;
+#else
+ uptr stack_top, stack_bottom;
+ GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
+ *stk_addr = stack_bottom;
+ *stk_size = stack_top - stack_bottom;
+ *tls_addr = 0;
+ *tls_size = 0;
+#endif
+}
+
+void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
+ uptr stack_top, uptr stack_bottom, bool fast) {
+ (void)fast;
+ (void)stack_top;
+ (void)stack_bottom;
+ stack->max_size = max_s;
+ void *tmp[kStackTraceMax];
+
+ // FIXME: CaptureStackBackTrace might be too slow for us.
+ // FIXME: Compare with StackWalk64.
+ // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
+ uptr cs_ret = CaptureStackBackTrace(1, stack->max_size, tmp, 0);
+ uptr offset = 0;
+ // Skip the RTL frames by searching for the PC in the stacktrace.
+ // FIXME: this doesn't work well for the malloc/free stacks yet.
+ for (uptr i = 0; i < cs_ret; i++) {
+ if (pc != (uptr)tmp[i])
+ continue;
+ offset = i;
+ break;
+ }
+
+ stack->size = cs_ret - offset;
+ for (uptr i = 0; i < stack->size; i++)
+ stack->trace[i] = (uptr)tmp[i + offset];
+}
+
+void MaybeOpenReportFile() {
+ // Windows doesn't have native fork, and we don't support Cygwin or other
+ // environments that try to fake it, so the initial report_fd will always be
+ // correct.
+}
+
+void RawWrite(const char *buffer) {
+ static const char *kRawWriteError =
+ "RawWrite can't output requested buffer!\n";
+ uptr length = (uptr)internal_strlen(buffer);
+ if (length != internal_write(report_fd, buffer, length)) {
+ // stderr may be closed, but we may be able to print to the debugger
+ // instead. This is the case when launching a program from Visual Studio,
+ // and the following routine should write to its console.
+ OutputDebugStringA(buffer);
+ }
+}
+
} // namespace __sanitizer
#endif // _WIN32