OSDN Git Service

08bb3cf3be157b3a98055f751d4f3ed412f0433f
[android-x86/external-llvm.git] / lib / Fuzzer / FuzzerUtilWindows.cpp
1 //===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // Misc utils implementation for Windows.
10 //===----------------------------------------------------------------------===//
11 #include "FuzzerDefs.h"
12 #if LIBFUZZER_WINDOWS
13 #include "FuzzerIO.h"
14 #include "FuzzerInternal.h"
15 #include <cassert>
16 #include <chrono>
17 #include <cstring>
18 #include <errno.h>
19 #include <iomanip>
20 #include <signal.h>
21 #include <sstream>
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <windows.h>
25 #include <Psapi.h>
26
27 namespace fuzzer {
28
29 static const FuzzingOptions* HandlerOpt = nullptr;
30
31 static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) {
32   switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
33     case EXCEPTION_ACCESS_VIOLATION:
34     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
35     case EXCEPTION_STACK_OVERFLOW:
36       if (HandlerOpt->HandleSegv)
37         Fuzzer::StaticCrashSignalCallback();
38       break;
39     case EXCEPTION_DATATYPE_MISALIGNMENT:
40     case EXCEPTION_IN_PAGE_ERROR:
41       if (HandlerOpt->HandleBus)
42         Fuzzer::StaticCrashSignalCallback();
43       break;
44     case EXCEPTION_ILLEGAL_INSTRUCTION:
45     case EXCEPTION_PRIV_INSTRUCTION:
46       if (HandlerOpt->HandleIll)
47         Fuzzer::StaticCrashSignalCallback();
48       break;
49     case EXCEPTION_FLT_DENORMAL_OPERAND:
50     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
51     case EXCEPTION_FLT_INEXACT_RESULT:
52     case EXCEPTION_FLT_INVALID_OPERATION:
53     case EXCEPTION_FLT_OVERFLOW:
54     case EXCEPTION_FLT_STACK_CHECK:
55     case EXCEPTION_FLT_UNDERFLOW:
56     case EXCEPTION_INT_DIVIDE_BY_ZERO:
57     case EXCEPTION_INT_OVERFLOW:
58       if (HandlerOpt->HandleFpe)
59         Fuzzer::StaticCrashSignalCallback();
60       break;
61     // TODO: handle (Options.HandleXfsz)
62   }
63   return EXCEPTION_CONTINUE_SEARCH;
64 }
65
66 BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
67   switch (dwCtrlType) {
68     case CTRL_C_EVENT:
69       if (HandlerOpt->HandleInt)
70         Fuzzer::StaticInterruptCallback();
71       return TRUE;
72     case CTRL_BREAK_EVENT:
73       if (HandlerOpt->HandleTerm)
74         Fuzzer::StaticInterruptCallback();
75       return TRUE;
76   }
77   return FALSE;
78 }
79
80 void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
81   Fuzzer::StaticAlarmCallback();
82 }
83
84 class TimerQ {
85   HANDLE TimerQueue;
86  public:
87   TimerQ() : TimerQueue(NULL) {};
88   ~TimerQ() {
89     if (TimerQueue)
90       DeleteTimerQueueEx(TimerQueue, NULL);
91   };
92   void SetTimer(int Seconds) {
93     if (!TimerQueue) {
94       TimerQueue = CreateTimerQueue();
95       if (!TimerQueue) {
96         Printf("libFuzzer: CreateTimerQueue failed.\n");
97         exit(1);
98       }
99     }
100     HANDLE Timer;
101     if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
102         Seconds*1000, Seconds*1000, 0)) {
103       Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
104       exit(1);
105     }
106   };
107 };
108
109 static TimerQ Timer;
110
111 static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
112
113 void SetSignalHandler(const FuzzingOptions& Options) {
114   HandlerOpt = &Options;
115
116   if (Options.UnitTimeoutSec > 0)
117     Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
118
119   if (Options.HandleInt || Options.HandleTerm)
120     if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
121       DWORD LastError = GetLastError();
122       Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
123         LastError);
124       exit(1);
125     }
126
127   if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
128       Options.HandleFpe)
129     SetUnhandledExceptionFilter(ExceptionHandler);
130
131   if (Options.HandleAbrt)
132     if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
133       Printf("libFuzzer: signal failed with %d\n", errno);
134       exit(1);
135     }
136 }
137
138 void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
139
140 unsigned long GetPid() { return GetCurrentProcessId(); }
141
142 size_t GetPeakRSSMb() {
143   PROCESS_MEMORY_COUNTERS info;
144   if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
145     return 0;
146   return info.PeakWorkingSetSize >> 20;
147 }
148
149 FILE *OpenProcessPipe(const char *Command, const char *Mode) {
150   return _popen(Command, Mode);
151 }
152
153 int ExecuteCommand(const std::string &Command) {
154   return system(Command.c_str());
155 }
156
157 const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
158                          size_t PattLen) {
159   // TODO: make this implementation more efficient.
160   const char *Cdata = (const char *)Data;
161   const char *Cpatt = (const char *)Patt;
162
163   if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
164     return NULL;
165
166   if (PattLen == 1)
167     return memchr(Data, *Cpatt, DataLen);
168
169   const char *End = Cdata + DataLen - PattLen + 1;
170
171   for (const char *It = Cdata; It < End; ++It)
172     if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
173       return It;
174
175   return NULL;
176 }
177
178 std::string DisassembleCmd(const std::string &FileName) {
179   if (ExecuteCommand("dumpbin /summary > nul") == 0)
180     return "dumpbin /disasm " + FileName;
181   Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n");
182   exit(1);
183 }
184
185 std::string SearchRegexCmd(const std::string &Regex) {
186   return "findstr /r \"" + Regex + "\"";
187 }
188
189 } // namespace fuzzer
190
191 #endif // LIBFUZZER_WINDOWS