sanitizer_win.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. //===-- sanitizer_win.cc --------------------------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is shared between AddressSanitizer and ThreadSanitizer
  9. // run-time libraries and implements windows-specific functions from
  10. // sanitizer_libc.h.
  11. //===----------------------------------------------------------------------===//
  12. #include "sanitizer_platform.h"
  13. #if SANITIZER_WINDOWS
  14. #define WIN32_LEAN_AND_MEAN
  15. #define NOGDI
  16. #include <windows.h>
  17. #include <dbghelp.h>
  18. #include <io.h>
  19. #include <stdlib.h>
  20. #include "sanitizer_common.h"
  21. #include "sanitizer_libc.h"
  22. #include "sanitizer_mutex.h"
  23. #include "sanitizer_placement_new.h"
  24. #include "sanitizer_stacktrace.h"
  25. namespace __sanitizer {
  26. #include "sanitizer_syscall_generic.inc"
  27. // --------------------- sanitizer_common.h
  28. uptr GetPageSize() {
  29. return 1U << 14; // FIXME: is this configurable?
  30. }
  31. uptr GetMmapGranularity() {
  32. return 1U << 16; // FIXME: is this configurable?
  33. }
  34. uptr GetMaxVirtualAddress() {
  35. SYSTEM_INFO si;
  36. GetSystemInfo(&si);
  37. return (uptr)si.lpMaximumApplicationAddress;
  38. }
  39. bool FileExists(const char *filename) {
  40. UNIMPLEMENTED();
  41. }
  42. uptr internal_getpid() {
  43. return GetProcessId(GetCurrentProcess());
  44. }
  45. // In contrast to POSIX, on Windows GetCurrentThreadId()
  46. // returns a system-unique identifier.
  47. uptr GetTid() {
  48. return GetCurrentThreadId();
  49. }
  50. uptr GetThreadSelf() {
  51. return GetTid();
  52. }
  53. #if !SANITIZER_GO
  54. void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
  55. uptr *stack_bottom) {
  56. CHECK(stack_top);
  57. CHECK(stack_bottom);
  58. MEMORY_BASIC_INFORMATION mbi;
  59. CHECK_NE(VirtualQuery(&mbi /* on stack */, &mbi, sizeof(mbi)), 0);
  60. // FIXME: is it possible for the stack to not be a single allocation?
  61. // Are these values what ASan expects to get (reserved, not committed;
  62. // including stack guard page) ?
  63. *stack_top = (uptr)mbi.BaseAddress + mbi.RegionSize;
  64. *stack_bottom = (uptr)mbi.AllocationBase;
  65. }
  66. #endif // #if !SANITIZER_GO
  67. void *MmapOrDie(uptr size, const char *mem_type) {
  68. void *rv = VirtualAlloc(0, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  69. if (rv == 0) {
  70. Report("ERROR: %s failed to "
  71. "allocate 0x%zx (%zd) bytes of %s (error code: %d)\n",
  72. SanitizerToolName, size, size, mem_type, GetLastError());
  73. CHECK("unable to mmap" && 0);
  74. }
  75. return rv;
  76. }
  77. void UnmapOrDie(void *addr, uptr size) {
  78. if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) {
  79. Report("ERROR: %s failed to "
  80. "deallocate 0x%zx (%zd) bytes at address %p (error code: %d)\n",
  81. SanitizerToolName, size, size, addr, GetLastError());
  82. CHECK("unable to unmap" && 0);
  83. }
  84. }
  85. void *MmapFixedNoReserve(uptr fixed_addr, uptr size) {
  86. // FIXME: is this really "NoReserve"? On Win32 this does not matter much,
  87. // but on Win64 it does.
  88. void *p = VirtualAlloc((LPVOID)fixed_addr, size,
  89. MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
  90. if (p == 0)
  91. Report("ERROR: %s failed to "
  92. "allocate %p (%zd) bytes at %p (error code: %d)\n",
  93. SanitizerToolName, size, size, fixed_addr, GetLastError());
  94. return p;
  95. }
  96. void *MmapFixedOrDie(uptr fixed_addr, uptr size) {
  97. return MmapFixedNoReserve(fixed_addr, size);
  98. }
  99. void *MmapNoReserveOrDie(uptr size, const char *mem_type) {
  100. // FIXME: make this really NoReserve?
  101. return MmapOrDie(size, mem_type);
  102. }
  103. void *Mprotect(uptr fixed_addr, uptr size) {
  104. return VirtualAlloc((LPVOID)fixed_addr, size,
  105. MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS);
  106. }
  107. void FlushUnneededShadowMemory(uptr addr, uptr size) {
  108. // This is almost useless on 32-bits.
  109. // FIXME: add madvice-analog when we move to 64-bits.
  110. }
  111. bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
  112. // FIXME: shall we do anything here on Windows?
  113. return true;
  114. }
  115. void *MapFileToMemory(const char *file_name, uptr *buff_size) {
  116. UNIMPLEMENTED();
  117. }
  118. void *MapWritableFileToMemory(void *addr, uptr size, uptr fd, uptr offset) {
  119. UNIMPLEMENTED();
  120. }
  121. static const int kMaxEnvNameLength = 128;
  122. static const DWORD kMaxEnvValueLength = 32767;
  123. namespace {
  124. struct EnvVariable {
  125. char name[kMaxEnvNameLength];
  126. char value[kMaxEnvValueLength];
  127. };
  128. } // namespace
  129. static const int kEnvVariables = 5;
  130. static EnvVariable env_vars[kEnvVariables];
  131. static int num_env_vars;
  132. const char *GetEnv(const char *name) {
  133. // Note: this implementation caches the values of the environment variables
  134. // and limits their quantity.
  135. for (int i = 0; i < num_env_vars; i++) {
  136. if (0 == internal_strcmp(name, env_vars[i].name))
  137. return env_vars[i].value;
  138. }
  139. CHECK_LT(num_env_vars, kEnvVariables);
  140. DWORD rv = GetEnvironmentVariableA(name, env_vars[num_env_vars].value,
  141. kMaxEnvValueLength);
  142. if (rv > 0 && rv < kMaxEnvValueLength) {
  143. CHECK_LT(internal_strlen(name), kMaxEnvNameLength);
  144. internal_strncpy(env_vars[num_env_vars].name, name, kMaxEnvNameLength);
  145. num_env_vars++;
  146. return env_vars[num_env_vars - 1].value;
  147. }
  148. return 0;
  149. }
  150. const char *GetPwd() {
  151. UNIMPLEMENTED();
  152. }
  153. u32 GetUid() {
  154. UNIMPLEMENTED();
  155. }
  156. void DumpProcessMap() {
  157. UNIMPLEMENTED();
  158. }
  159. void DisableCoreDumperIfNecessary() {
  160. // Do nothing.
  161. }
  162. void ReExec() {
  163. UNIMPLEMENTED();
  164. }
  165. void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
  166. (void)args;
  167. // Nothing here for now.
  168. }
  169. bool StackSizeIsUnlimited() {
  170. UNIMPLEMENTED();
  171. }
  172. void SetStackSizeLimitInBytes(uptr limit) {
  173. UNIMPLEMENTED();
  174. }
  175. bool AddressSpaceIsUnlimited() {
  176. UNIMPLEMENTED();
  177. }
  178. void SetAddressSpaceUnlimited() {
  179. UNIMPLEMENTED();
  180. }
  181. char *FindPathToBinary(const char *name) {
  182. // Nothing here for now.
  183. return 0;
  184. }
  185. void SleepForSeconds(int seconds) {
  186. Sleep(seconds * 1000);
  187. }
  188. void SleepForMillis(int millis) {
  189. Sleep(millis);
  190. }
  191. u64 NanoTime() {
  192. return 0;
  193. }
  194. void Abort() {
  195. abort();
  196. internal__exit(-1); // abort is not NORETURN on Windows.
  197. }
  198. uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
  199. string_predicate_t filter) {
  200. UNIMPLEMENTED();
  201. };
  202. #ifndef SANITIZER_GO
  203. int Atexit(void (*function)(void)) {
  204. return atexit(function);
  205. }
  206. #endif
  207. // ------------------ sanitizer_libc.h
  208. uptr internal_mmap(void *addr, uptr length, int prot, int flags,
  209. int fd, u64 offset) {
  210. UNIMPLEMENTED();
  211. }
  212. uptr internal_munmap(void *addr, uptr length) {
  213. UNIMPLEMENTED();
  214. }
  215. uptr internal_close(fd_t fd) {
  216. UNIMPLEMENTED();
  217. }
  218. int internal_isatty(fd_t fd) {
  219. return _isatty(fd);
  220. }
  221. uptr internal_open(const char *filename, int flags) {
  222. UNIMPLEMENTED();
  223. }
  224. uptr internal_open(const char *filename, int flags, u32 mode) {
  225. UNIMPLEMENTED();
  226. }
  227. uptr OpenFile(const char *filename, bool write) {
  228. UNIMPLEMENTED();
  229. }
  230. uptr internal_read(fd_t fd, void *buf, uptr count) {
  231. UNIMPLEMENTED();
  232. }
  233. uptr internal_write(fd_t fd, const void *buf, uptr count) {
  234. if (fd != kStderrFd)
  235. UNIMPLEMENTED();
  236. static HANDLE output_stream = 0;
  237. // Abort immediately if we know printing is not possible.
  238. if (output_stream == INVALID_HANDLE_VALUE)
  239. return 0;
  240. // If called for the first time, try to use stderr to output stuff,
  241. // falling back to stdout if anything goes wrong.
  242. bool fallback_to_stdout = false;
  243. if (output_stream == 0) {
  244. output_stream = GetStdHandle(STD_ERROR_HANDLE);
  245. // We don't distinguish "no such handle" from error.
  246. if (output_stream == 0)
  247. output_stream = INVALID_HANDLE_VALUE;
  248. if (output_stream == INVALID_HANDLE_VALUE) {
  249. // Retry with stdout?
  250. output_stream = GetStdHandle(STD_OUTPUT_HANDLE);
  251. if (output_stream == 0)
  252. output_stream = INVALID_HANDLE_VALUE;
  253. if (output_stream == INVALID_HANDLE_VALUE)
  254. return 0;
  255. } else {
  256. // Successfully got an stderr handle. However, if WriteFile() fails,
  257. // we can still try to fallback to stdout.
  258. fallback_to_stdout = true;
  259. }
  260. }
  261. DWORD ret;
  262. if (WriteFile(output_stream, buf, count, &ret, 0))
  263. return ret;
  264. // Re-try with stdout if using a valid stderr handle fails.
  265. if (fallback_to_stdout) {
  266. output_stream = GetStdHandle(STD_OUTPUT_HANDLE);
  267. if (output_stream == 0)
  268. output_stream = INVALID_HANDLE_VALUE;
  269. if (output_stream != INVALID_HANDLE_VALUE)
  270. return internal_write(fd, buf, count);
  271. }
  272. return 0;
  273. }
  274. uptr internal_stat(const char *path, void *buf) {
  275. UNIMPLEMENTED();
  276. }
  277. uptr internal_lstat(const char *path, void *buf) {
  278. UNIMPLEMENTED();
  279. }
  280. uptr internal_fstat(fd_t fd, void *buf) {
  281. UNIMPLEMENTED();
  282. }
  283. uptr internal_filesize(fd_t fd) {
  284. UNIMPLEMENTED();
  285. }
  286. uptr internal_dup2(int oldfd, int newfd) {
  287. UNIMPLEMENTED();
  288. }
  289. uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
  290. UNIMPLEMENTED();
  291. }
  292. uptr internal_sched_yield() {
  293. Sleep(0);
  294. return 0;
  295. }
  296. void internal__exit(int exitcode) {
  297. ExitProcess(exitcode);
  298. }
  299. uptr internal_ftruncate(fd_t fd, uptr size) {
  300. UNIMPLEMENTED();
  301. }
  302. uptr internal_rename(const char *oldpath, const char *newpath) {
  303. UNIMPLEMENTED();
  304. }
  305. // ---------------------- BlockingMutex ---------------- {{{1
  306. const uptr LOCK_UNINITIALIZED = 0;
  307. const uptr LOCK_READY = (uptr)-1;
  308. BlockingMutex::BlockingMutex(LinkerInitialized li) {
  309. // FIXME: see comments in BlockingMutex::Lock() for the details.
  310. CHECK(li == LINKER_INITIALIZED || owner_ == LOCK_UNINITIALIZED);
  311. CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
  312. InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  313. owner_ = LOCK_READY;
  314. }
  315. BlockingMutex::BlockingMutex() {
  316. CHECK(sizeof(CRITICAL_SECTION) <= sizeof(opaque_storage_));
  317. InitializeCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  318. owner_ = LOCK_READY;
  319. }
  320. void BlockingMutex::Lock() {
  321. if (owner_ == LOCK_UNINITIALIZED) {
  322. // FIXME: hm, global BlockingMutex objects are not initialized?!?
  323. // This might be a side effect of the clang+cl+link Frankenbuild...
  324. new(this) BlockingMutex((LinkerInitialized)(LINKER_INITIALIZED + 1));
  325. // FIXME: If it turns out the linker doesn't invoke our
  326. // constructors, we should probably manually Lock/Unlock all the global
  327. // locks while we're starting in one thread to avoid double-init races.
  328. }
  329. EnterCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  330. CHECK_EQ(owner_, LOCK_READY);
  331. owner_ = GetThreadSelf();
  332. }
  333. void BlockingMutex::Unlock() {
  334. CHECK_EQ(owner_, GetThreadSelf());
  335. owner_ = LOCK_READY;
  336. LeaveCriticalSection((LPCRITICAL_SECTION)opaque_storage_);
  337. }
  338. void BlockingMutex::CheckLocked() {
  339. CHECK_EQ(owner_, GetThreadSelf());
  340. }
  341. uptr GetTlsSize() {
  342. return 0;
  343. }
  344. void InitTlsSize() {
  345. }
  346. void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
  347. uptr *tls_addr, uptr *tls_size) {
  348. #ifdef SANITIZER_GO
  349. *stk_addr = 0;
  350. *stk_size = 0;
  351. *tls_addr = 0;
  352. *tls_size = 0;
  353. #else
  354. uptr stack_top, stack_bottom;
  355. GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
  356. *stk_addr = stack_bottom;
  357. *stk_size = stack_top - stack_bottom;
  358. *tls_addr = 0;
  359. *tls_size = 0;
  360. #endif
  361. }
  362. #if !SANITIZER_GO
  363. void BufferedStackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
  364. CHECK_GE(max_depth, 2);
  365. // FIXME: CaptureStackBackTrace might be too slow for us.
  366. // FIXME: Compare with StackWalk64.
  367. // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
  368. size = CaptureStackBackTrace(2, Min(max_depth, kStackTraceMax),
  369. (void**)trace, 0);
  370. if (size == 0)
  371. return;
  372. // Skip the RTL frames by searching for the PC in the stacktrace.
  373. uptr pc_location = LocatePcInTrace(pc);
  374. PopStackFrames(pc_location);
  375. }
  376. void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
  377. uptr max_depth) {
  378. CONTEXT ctx = *(CONTEXT *)context;
  379. STACKFRAME64 stack_frame;
  380. memset(&stack_frame, 0, sizeof(stack_frame));
  381. size = 0;
  382. #if defined(_WIN64)
  383. int machine_type = IMAGE_FILE_MACHINE_AMD64;
  384. stack_frame.AddrPC.Offset = ctx.Rip;
  385. stack_frame.AddrFrame.Offset = ctx.Rbp;
  386. stack_frame.AddrStack.Offset = ctx.Rsp;
  387. #else
  388. int machine_type = IMAGE_FILE_MACHINE_I386;
  389. stack_frame.AddrPC.Offset = ctx.Eip;
  390. stack_frame.AddrFrame.Offset = ctx.Ebp;
  391. stack_frame.AddrStack.Offset = ctx.Esp;
  392. #endif
  393. stack_frame.AddrPC.Mode = AddrModeFlat;
  394. stack_frame.AddrFrame.Mode = AddrModeFlat;
  395. stack_frame.AddrStack.Mode = AddrModeFlat;
  396. while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
  397. &stack_frame, &ctx, NULL, &SymFunctionTableAccess64,
  398. &SymGetModuleBase64, NULL) &&
  399. size < Min(max_depth, kStackTraceMax)) {
  400. trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
  401. }
  402. }
  403. #endif // #if !SANITIZER_GO
  404. void MaybeOpenReportFile() {
  405. // Windows doesn't have native fork, and we don't support Cygwin or other
  406. // environments that try to fake it, so the initial report_fd will always be
  407. // correct.
  408. }
  409. void RawWrite(const char *buffer) {
  410. uptr length = (uptr)internal_strlen(buffer);
  411. if (length != internal_write(report_fd, buffer, length)) {
  412. // stderr may be closed, but we may be able to print to the debugger
  413. // instead. This is the case when launching a program from Visual Studio,
  414. // and the following routine should write to its console.
  415. OutputDebugStringA(buffer);
  416. }
  417. }
  418. void SetAlternateSignalStack() {
  419. // FIXME: Decide what to do on Windows.
  420. }
  421. void UnsetAlternateSignalStack() {
  422. // FIXME: Decide what to do on Windows.
  423. }
  424. void InstallDeadlySignalHandlers(SignalHandlerType handler) {
  425. (void)handler;
  426. // FIXME: Decide what to do on Windows.
  427. }
  428. bool IsDeadlySignal(int signum) {
  429. // FIXME: Decide what to do on Windows.
  430. return false;
  431. }
  432. bool IsAccessibleMemoryRange(uptr beg, uptr size) {
  433. // FIXME: Actually implement this function.
  434. return true;
  435. }
  436. } // namespace __sanitizer
  437. #endif // _WIN32