OLD | NEW |
| (Empty) |
1 #include <conio.h> | |
2 #include <time.h> | |
3 | |
4 #include "debugger/core/debug_api.h" | |
5 #include "debugger/core/debug_execution_engine.h" | |
6 #include "debugger/core/debuggee_process.h" | |
7 #include "debugger/core/debuggee_thread.h" | |
8 #include "debug_continue_policy.h" | |
9 #include "debugger/core/debug_logger.h" | |
10 #include "debugger/base/debug_utils.h" | |
11 #include "debugger/base/debug_blob.h" | |
12 #include "debugger/base/debug_command_line.h" | |
13 | |
14 #include "debugger/base/debug_utils.h" | |
15 #include "debug_debug_event2.h" | |
16 | |
17 #pragma warning(disable : 4996) | |
18 | |
19 bool FindNexeThread(debug::ExecutionEngine& dbg_core, int* pid, int* tid); | |
20 | |
21 void* BlobToCBuff(const debug::Blob& blob) { | |
22 SIZE_T num = blob.size(); | |
23 char* buff = static_cast<char*>(malloc(num)); | |
24 if (NULL != buff) { | |
25 for (size_t i = 0; i < num; i++) | |
26 buff[i] = blob[i]; | |
27 } | |
28 return buff; | |
29 } | |
30 | |
31 namespace { | |
32 const char* GetDebugeeStateName(debug::DebuggeeProcess::State st) { | |
33 switch (st) { | |
34 case debug::DebuggeeProcess::kRunning: return "RUNNING"; | |
35 case debug::DebuggeeProcess::kHalted: return "kHalted"; | |
36 case debug::DebuggeeProcess::kDead: return "DEAD"; | |
37 } | |
38 return "N/A"; | |
39 } | |
40 } // namespace | |
41 | |
42 class MyExecutionEngine : public debug::ExecutionEngine { | |
43 public: | |
44 MyExecutionEngine(debug::DebugAPI* debug_api) : debug::ExecutionEngine(debug_a
pi) {} | |
45 | |
46 protected: | |
47 virtual int OnDebugEvent(const DEBUG_EVENT& debug_event); | |
48 }; | |
49 | |
50 bool print_all_deb_events = true; | |
51 | |
52 int main(int argc, char* argv[]) { | |
53 //debug::Logger log; | |
54 debug::TextFileLogger log; | |
55 log.Open("debug_log.txt"); | |
56 log.EnableStdout(true); | |
57 debug::Logger::SetGlobalLogger(&log); | |
58 debug::DebugAPI debug_api; | |
59 | |
60 MyExecutionEngine dbg_core(&debug_api); | |
61 debug::StandardContinuePolicy continue_policy; | |
62 | |
63 // test only! it works! | |
64 // HMODULE hLib = ::LoadLibrary("D:\\chromuim_648_12\\src\\build\\Debug\\nacl64
.exe"); | |
65 // FARPROC fp = ::GetProcAddress(hLib, "SetNumberOfExtensions"); | |
66 | |
67 #ifdef _WIN64 | |
68 // const char* cmd = "D:\\chromuim_648_12\\src\\build\\Debug\\chrome.exe"; // -
-no-sandbox"; | |
69 // const char* work_dir = NULL; //"D:\\chromuim_648_12\\src\\build\\Debug"; | |
70 #else | |
71 // const char* cmd = "C:\\work\\chromuim_648_12\\src\\build\\Debug\\chrome.exe"
; | |
72 // const char* work_dir = NULL; //"C:\\work\\chromuim_648_12\\src\\build\\Debug
"; | |
73 #endif | |
74 | |
75 debug::CommandLine cmd(argc - 1, argv + 1); | |
76 std::string cmd_line = cmd.ToString(); | |
77 | |
78 bool start_res = dbg_core.StartProcess(cmd_line.c_str(), NULL); | |
79 if (!start_res) { | |
80 printf("Can't start [%s] in [%s].\n", cmd_line.c_str(), NULL); | |
81 } else { | |
82 DBG_LOG("TR51.00", "msg='Debug session started'"); | |
83 DBG_LOG("TR51.01", "msg='Process started' cmd='%s'", cmd_line.c_str()); | |
84 | |
85 // int current_process = 0; | |
86 // int current_thread = 0; | |
87 do { | |
88 int pid = 0; | |
89 bool dbg_event = dbg_core.WaitForDebugEventAndDispatchIt(0, &pid); | |
90 debug::IDebuggeeProcess* halted_process = dbg_core.GetProcess(pid); | |
91 | |
92 if (NULL != halted_process) { | |
93 debug::DecisionToContinue dtc; | |
94 continue_policy.MakeContinueDecision(dbg_core.debug_event(), | |
95 halted_process->GetHaltedThread(), | |
96 &dtc); | |
97 //dtc.halt_debuggee_ = true; | |
98 int nacl_event_id = dbg_core.debug_event().nacl_debug_event_code(); | |
99 if (debug::DebugEvent::kNotNaClDebugEvent != nacl_event_id) { | |
100 DBG_LOG("TR51.02", "DebugEvent::nacl_debug_event_code_ = %d", nacl_eve
nt_id); | |
101 } | |
102 | |
103 DBG_LOG("TR51.03", "msg=DecisionToContinue continue=%s pass_exception=%s
", | |
104 dtc.IsHaltDecision() ? "no" : "yes", | |
105 dtc.pass_exception_to_debuggee() ? "yes" : "no"); | |
106 | |
107 #ifdef Z00 | |
108 if (0 && (dbg_core.debug_event().windows_debug_event().dwDebugEventCode
== EXCEPTION_DEBUG_EVENT)) { | |
109 if (dbg_core.debug_event().windows_debug_event().u.Exception.Exception
Record.ExceptionCode == EXCEPTION_BREAKPOINT) { | |
110 dtc.halt_debuggee_ = true; | |
111 dtc.decision_strength_ = debug::DecisionToContinue::kStrongDecision; | |
112 printf("Breakpoint hit\n"); | |
113 } | |
114 } | |
115 | |
116 if (dbg_core.debug_event().windows_debug_event().dwDebugEventCode == EXI
T_THREAD_DEBUG_EVENT) { | |
117 dtc.halt_debuggee_ = true; | |
118 dtc.decision_strength_ = debug::DecisionToContinue::kStrongDecision; | |
119 printf("Thread exiting\n"); | |
120 } | |
121 #endif | |
122 if (!dtc.IsHaltDecision()) { | |
123 if (dtc.pass_exception_to_debuggee()) | |
124 halted_process->ContinueAndPassExceptionToDebuggee(); | |
125 else | |
126 halted_process->Continue(); | |
127 halted_process = NULL; | |
128 } | |
129 } | |
130 | |
131 if (NULL == halted_process) { | |
132 if (!_kbhit()) | |
133 continue; | |
134 | |
135 char cmd[100] = {0}; | |
136 printf(">"); | |
137 gets(cmd); | |
138 DBG_LOG("TR51.04", "user_command='%s'", cmd); | |
139 if (0 == strcmp(cmd, "quit")) { | |
140 dbg_core.Stop(300); | |
141 break; | |
142 } | |
143 | |
144 if (0 == strncmp(cmd, "break", 5)) { | |
145 int pid = sscanf(cmd + strlen("break"), "%d", &pid); | |
146 debug::IDebuggeeProcess* proc = dbg_core.GetProcess(pid); | |
147 if (NULL != proc) | |
148 proc->Break(); | |
149 } else if (0 == strncmp(cmd, "e-", 2)) { | |
150 print_all_deb_events = false; | |
151 } | |
152 } else { | |
153 debug::DebuggeeThread* thread = halted_process->GetHaltedThread(); | |
154 int tid = 0; | |
155 if (NULL != thread) | |
156 tid = thread->id(); | |
157 | |
158 while(true) { | |
159 printf("%d:%d>", halted_process->id(), tid); | |
160 char cmd[100] = {0}; | |
161 gets(cmd); | |
162 DBG_LOG("TR51.05", "user_command='%s'", cmd); | |
163 if (0 == strcmp(cmd, "quit")) { | |
164 dbg_core.Stop(300); | |
165 break; | |
166 } else if (0 == strncmp(cmd, "e-", 2)) { | |
167 print_all_deb_events = false; | |
168 } else if (0 == strncmp(cmd, "attach", 6)) { | |
169 int id = 0; | |
170 int sn = sscanf(cmd + 7, "%d", &id); | |
171 dbg_core.AttachToProcess(id); | |
172 } else if (0 == strncmp(cmd, "detach", 6)) { | |
173 dbg_core.DetachAll(); | |
174 } else if (0 == strncmp(cmd, "br ", strlen("br "))) { | |
175 void* addr = 0; | |
176 int sn = sscanf(cmd + strlen("br "), "%p", &addr); | |
177 if ((NULL != halted_process) && (sn != 0)) | |
178 halted_process->SetBreakpoint(addr); | |
179 continue; | |
180 } else if (0 == strncmp(cmd, "rmbr ", strlen("rmbr "))) { | |
181 void* addr = 0; | |
182 int sn = sscanf(cmd + strlen("rmbr "), "%p", &addr); | |
183 if ((NULL != halted_process) && (sn != 0)) | |
184 halted_process->RemoveBreakpoint(addr); | |
185 continue; | |
186 } else if (0 == strcmp(cmd, "info threads")) { | |
187 std::deque<int> processes; | |
188 dbg_core.GetProcessIds(&processes); | |
189 for (size_t p = 0; p < processes.size(); p++) { | |
190 int pid = processes[p]; | |
191 debug::DebuggeeProcess* proc = static_cast<debug::DebuggeeProcess*
>(dbg_core.GetProcess(pid)); | |
192 if (proc == halted_process) | |
193 printf("process * %d", pid); | |
194 else | |
195 printf("process %d", pid); | |
196 printf(" %d-bits", debug::Utils::GetProcessorWordSizeInBits(proc->
handle())); | |
197 | |
198 if (NULL != proc) { | |
199 debug::DebuggeeProcess::State st = proc->state(); | |
200 printf(" %s ", (debug::DebuggeeProcess::kHalted == st) ? "Halted
" : GetDebugeeStateName(st)); | |
201 std::string name; | |
202 std::string cmd; | |
203 debug::Utils::GetProcessName(proc->id(), &name); | |
204 debug::Utils::GetProcessCmdLine(proc->handle(), &cmd); | |
205 printf(" exe=[%s] cmd_line=[%s]\n", name.c_str(), cmd.c_str()); | |
206 } else { | |
207 printf("\n"); | |
208 } | |
209 if (NULL != proc) { | |
210 std::deque<int> threads; | |
211 proc->GetThreadIds(&threads); | |
212 for (size_t i = 0; i < threads.size(); i++) { | |
213 int id = threads[i]; | |
214 debug::DebuggeeThread* thr = proc->GetThread(id); | |
215 bool current = (thr == thread); | |
216 const char* status = thr->GetStateName(thr->state()); | |
217 const char* is_nexe = thr->IsNaClAppThread() ? "[I'm nexe thre
ad]" : ""; | |
218 printf(" %s%d ""ip=%p %s %s\n", | |
219 current ? "*" : " ", | |
220 id, | |
221 (void*)thr->GetIP(), status, is_nexe); | |
222 } | |
223 } | |
224 } | |
225 continue; | |
226 } else if (0 == strcmp(cmd, "c")) { | |
227 if (NULL != halted_process) | |
228 halted_process->Continue(); | |
229 break; | |
230 } else if (0 == strncmp(cmd, "ct", 2)) { | |
231 if (NULL != thread) { | |
232 CONTEXT ct; | |
233 thread->GetContext(&ct); | |
234 } | |
235 } else if (0 == strncmp(cmd, "m", 1)) { | |
236 void* addr = 0; | |
237 int sz = 0; | |
238 sscanf(cmd + 2, "%p %d", &addr, &sz); | |
239 char data[2000]; | |
240 if (NULL != halted_process) { | |
241 halted_process->ReadMemory(addr, sz, data); | |
242 debug::Blob blob(data, sz); | |
243 std::string str = blob.ToHexString(false); | |
244 printf("[%s]\n", str.c_str()); | |
245 } | |
246 continue; | |
247 } else if (0 == strncmp(cmd, "M", 1)) { | |
248 long long addr = 0; | |
249 sscanf(cmd + 2, "%llx", &addr); | |
250 char* p = strchr(cmd, ' '); | |
251 p = strchr(p + 1, ' '); | |
252 debug::Blob blob; | |
253 blob.LoadFromHexString(std::string(p)); | |
254 if (NULL != halted_process) { | |
255 void* data = BlobToCBuff(blob); | |
256 halted_process->WriteMemory((const void*)addr, blob.size(), data); | |
257 free(data); | |
258 } | |
259 continue; | |
260 } else if (0 == strcmp(cmd, "s")) { | |
261 if (NULL != halted_process) | |
262 halted_process->SingleStep(); | |
263 } else if (0 == strcmp(cmd, "ip")) { | |
264 if (NULL != thread) { | |
265 void* ip = thread->GetIP(); | |
266 printf("%p\n", ip); | |
267 } | |
268 continue; | |
269 } else if (0 == strcmp(cmd, "ip++")) { | |
270 if (NULL != thread) { | |
271 char* ip = static_cast<char*>(thread->GetIP()); | |
272 thread->SetIP(ip++); | |
273 printf("%p\n", ip); | |
274 } | |
275 continue; | |
276 } | |
277 } | |
278 } | |
279 } while(true); | |
280 } | |
281 | |
282 printf("Done. Ready to exit..."); | |
283 getchar(); | |
284 return 0; | |
285 } | |
286 | |
287 unsigned char* my_strstr(unsigned char* str, size_t str_length, unsigned char* s
ubstr, size_t substr_length) { | |
288 for (size_t i = 0; i < str_length; i++ ) { | |
289 unsigned char* p = str + i; | |
290 size_t str_length_now = str_length - i; | |
291 if (str_length_now < substr_length) | |
292 return NULL; | |
293 | |
294 if (memcmp(p, substr, substr_length) == 0) | |
295 return p; | |
296 } | |
297 return 0; | |
298 } | |
299 | |
300 bool FindNexeThread(debug::ExecutionEngine& dbg_core, int* pid, int* tid) { | |
301 std::deque<int> processes; | |
302 dbg_core.GetProcessIds(&processes); | |
303 for (size_t p = 0; p < processes.size(); p++) { | |
304 debug::IDebuggeeProcess* proc = dbg_core.GetProcess(processes[p]); | |
305 if (NULL != proc) { | |
306 std::deque<int> threads; | |
307 proc->GetThreadIds(&threads); | |
308 for (size_t i = 0; i < threads.size(); i++) { | |
309 debug::DebuggeeThread* thr = proc->GetThread(threads[i]); | |
310 if (thr && thr->IsNaClAppThread()) { | |
311 *pid = processes[p]; | |
312 *tid = threads[i]; | |
313 return false; | |
314 } | |
315 } | |
316 } | |
317 } | |
318 return false; | |
319 } | |
320 | |
321 int MyExecutionEngine::OnDebugEvent(const DEBUG_EVENT& debug_event) { | |
322 if (print_all_deb_events) { | |
323 std::string text; | |
324 debug::DEBUG_EVENT_ToJSON(debug_event, &text); | |
325 DBG_LOG("TR51.06", "debug_event=%s", text.c_str()); | |
326 | |
327 if (CREATE_PROCESS_DEBUG_EVENT == debug_event.dwDebugEventCode) { | |
328 std::string cmd_line; | |
329 debug::Utils::GetProcessCmdLine(debug_event.u.CreateProcessInfo.hProcess,
&cmd_line); | |
330 DBG_LOG("TR51.09", "cmd_line='%s'", cmd_line.c_str()); | |
331 } else if (LOAD_DLL_DEBUG_EVENT == debug_event.dwDebugEventCode) { | |
332 debug::DebuggeeProcess* proc = static_cast<debug::DebuggeeProcess*>(GetPro
cess(debug_event.dwProcessId)); | |
333 if (proc) { | |
334 std::string path; | |
335 bool r = debug::Utils::ReadUnucodeStr(proc->handle(), debug_event.u.Load
Dll.lpImageName, &path); | |
336 DBG_LOG("TR51.10", "LOAD_DLL='%s'", path.c_str()); | |
337 } | |
338 } | |
339 } | |
340 | |
341 debug::IDebuggeeProcess* proc = GetProcess(debug_event.dwProcessId); | |
342 if (proc) { | |
343 debug::DebuggeeThread* thread = proc->GetThread(debug_event.dwThreadId); | |
344 if (thread) { | |
345 void* ip = thread->GetIP(); | |
346 DBG_LOG("TR51.07", "debug_event_ip' ip=0x%p pid=%d tid=%d", | |
347 ip, | |
348 debug_event.dwProcessId, | |
349 debug_event.dwThreadId); | |
350 } | |
351 } | |
352 | |
353 int pid = ExecutionEngine::OnDebugEvent(debug_event); | |
354 | |
355 proc = GetProcess(debug_event.dwProcessId); | |
356 if (proc) { | |
357 DBG_LOG("TR51.08", "debug_event_end WoW=%s pid=%d tid=%d", | |
358 proc->IsWoW() ? "yes" : "no", | |
359 debug_event.dwProcessId, | |
360 debug_event.dwThreadId); | |
361 } | |
362 return pid; | |
363 } | |
364 | |
OLD | NEW |