OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 #include <fcntl.h> | |
5 #include <malloc.h> | |
6 #include <pthread.h> | |
7 #include <signal.h> | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <termios.h> | |
12 #include <unistd.h> | |
13 | |
14 #include <deque> | |
15 #include <string> | |
16 | |
17 #include "debug_api_linux.h" | |
18 #include "debug_blob.h" | |
19 | |
20 void* atoptr(const char* str) { | |
21 void* ptr = 0; | |
22 sscanf(str, "%p", &ptr); // NOLINT | |
23 return ptr; | |
24 } | |
25 | |
26 int kbhit() { | |
27 termios oldt; | |
28 tcgetattr(STDIN_FILENO, &oldt); | |
29 termios newt = oldt; | |
30 newt.c_lflag &= ~(ICANON | ECHO); | |
31 tcsetattr(STDIN_FILENO, TCSANOW, &newt); | |
32 int oldf = fcntl(STDIN_FILENO, F_GETFL, 0); | |
33 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); | |
34 | |
35 int ch = getchar(); | |
36 | |
37 tcsetattr(STDIN_FILENO, TCSANOW, &oldt); | |
38 fcntl(STDIN_FILENO, F_SETFL, oldf); | |
39 | |
40 if (EOF != ch) { | |
41 ungetc(ch, stdin); | |
42 return 1; | |
43 } | |
44 return 0; | |
45 } | |
46 | |
47 extern void Split(const char* str_in, | |
48 const char* delimiters, | |
49 std::deque<std::string>* out); | |
50 | |
51 void printList(const std::deque<std::string>& list) { | |
52 printf("list {\n"); | |
53 size_t num = list.size(); | |
54 for (size_t i = 0; i < num; i++) | |
55 printf("[%s]\n", list[i].c_str()); | |
56 printf("}\n"); | |
57 } | |
58 | |
59 | |
60 int main(int argc, char *argv[]) { | |
61 debug::DebugApi deb_api; | |
62 pid_t child_pid = 0; | |
63 | |
64 #define CHROMEEE | |
65 #ifdef CHROMEEE | |
66 // const char* cmd_line = "/usr/local/google/garianov/chrome/src/out/Debug/chro
me --no-sandbox --allow-sandbox-debugging --disable-seccomp-sandbox"; | |
67 const char* cmd_line = "/usr/local/google/garianov/chrome/src/out/Debug/chrome
--incognito http://localhost:5103/hello_world_c/hello_world_c.html"; | |
68 printf("Starting [%s]\npress any key...", cmd_line); | |
69 getchar(); | |
70 bool sp_res = deb_api.StartProcess( | |
71 cmd_line, | |
72 true, | |
73 &child_pid); | |
74 #else | |
75 bool sp_res = deb_api.StartProcess( | |
76 "/home/garianov/projects/debugger/a.out", | |
77 true, | |
78 &child_pid); | |
79 #endif | |
80 | |
81 bool show_events = false; //true; //aaa | |
82 int nacl_pid = 0; | |
83 bool animate = false; | |
84 FILE* file = fopen("anim.txt", "wt"); | |
85 | |
86 #ifdef CHROMEEE | |
87 static bool iterative = false; | |
88 #else | |
89 static bool iterative = true; | |
90 #endif | |
91 | |
92 while (true) { | |
93 if (kbhit()) { | |
94 char buff[100] = { 0 }; | |
95 fgets(buff, sizeof(buff) -1, stdin); | |
96 | |
97 std::deque<std::string> words; | |
98 Split(buff, " \t", &words); | |
99 printList(words); | |
100 if ((words[0] == "break") && (words.size() >= 2)) { | |
101 int pid = atoi(words[1].c_str()); | |
102 bool res = deb_api.DebugBreak(pid); | |
103 if (!res) | |
104 printf("Error\n"); | |
105 continue; | |
106 } else if (words[0] == "e-") { | |
107 printf("show_events = false\n"); | |
108 show_events = false; | |
109 continue; | |
110 } else if (words[0] == "q") { | |
111 break; | |
112 } | |
113 } | |
114 | |
115 debug::DebugEvent de; | |
116 if (deb_api.WaitForDebugEvent(&de)) { | |
117 //beg - test only | |
118 //iterative = true; | |
119 //nacl_pid = de.process_id_; | |
120 //end - test only | |
121 | |
122 if (debug::DebugEvent::OUTPUT_DEBUG_STRING == de.event_code_) { | |
123 iterative = true; | |
124 nacl_pid = de.process_id_; | |
125 printf("Got OUTPUT_DEBUG_STRING: "); | |
126 std::string string; | |
127 if (deb_api.ReadDebugString(&de, &string)) | |
128 printf("[%s]", string.c_str()); | |
129 printf("\n"); | |
130 // deb_api.ContinueDebugEvent(de.process_id_); | |
131 // do_continue = true; | |
132 } else if (de.signal_no_ == SIGTRAP) { | |
133 // Checking for possible OUTPUT_DEBUG_STRING event | |
134 char* rax = 0; | |
135 deb_api.GetRax(de.process_id_, &rax); | |
136 | |
137 const char* key = "{7AA7C9CF-89EC-4ed3-8DAD-6DC84302AB11}"; | |
138 size_t key_len = strlen(key); | |
139 | |
140 size_t rd = 0; | |
141 char buff[1024] = {0, 0}; | |
142 deb_api.ReadProcessMemory(de.process_id_, rax, buff, sizeof(buff), &rd); | |
143 if (rd > 0) { | |
144 buff[sizeof(buff) - 1] = 0; | |
145 debug::Blob bb(buff, rd); | |
146 printf("OUTPUT_DEBUG_STRING=[%s]\n", bb.ToString().c_str()); | |
147 } | |
148 | |
149 if ((memcmp(key, buff, key_len) ==0)) { | |
150 iterative = true; | |
151 nacl_pid = de.process_id_; | |
152 printf("%s\n", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%Gotcha!=>=>=>=>=>=>=>
=>=>=>=>=>=>=>=>=>"); | |
153 } | |
154 } | |
155 | |
156 | |
157 if (show_events || (nacl_pid == de.process_id_)) | |
158 //|| (debug::DebugEvent::SINGLE_STEP_TRAP == de.event_code_)) | |
159 // int ppid = get_ppid(); | |
160 // printf() | |
161 de.Print(); | |
162 | |
163 if (animate && (nacl_pid == de.process_id_) && | |
164 (debug::DebugEvent::SINGLE_STEP_TRAP == de.event_code_)) { | |
165 printf("debug::DebugEvent::SINGLE_STEP_TRAP == de.event_code_\n"); | |
166 fprintf(file, "%p\n", de.ip_); | |
167 fflush(file); | |
168 // deb_api.EnableSingleStep(de.process_id_, false); | |
169 deb_api.SingleStep(nacl_pid); | |
170 continue; | |
171 } | |
172 | |
173 while (true) { | |
174 char buff[100] = { 0 }; | |
175 | |
176 // test only: beg | |
177 // if (iterative) { // && (nacl_pid == de.process_id_)) { | |
178 #ifdef CHROMEEE | |
179 if (iterative && (nacl_pid == de.process_id_)) { | |
180 #else | |
181 if (iterative) { | |
182 #endif | |
183 printf("\n[%d]>", de.process_id_); | |
184 fflush(stdout); | |
185 fgets(buff, sizeof(buff) -1, stdin); | |
186 } else { | |
187 snprintf(buff, sizeof(buff), "c"); | |
188 } | |
189 // test only: end | |
190 | |
191 static bool first = true; | |
192 if (first) { | |
193 first = false; | |
194 deb_api.SetupProc(de.process_id_); | |
195 } | |
196 | |
197 std::deque<std::string> words; | |
198 Split(buff, " \t", &words); | |
199 // printList(words); | |
200 if (words.size() < 1) | |
201 continue; | |
202 if (words[0] == "c") { | |
203 int signo = de.signal_no_; | |
204 if ((signo == SIGTRAP) || (debug::DebugEvent::OUTPUT_DEBUG_STRING == d
e.event_code_)) // don't pass it to debugee | |
205 signo = 0; | |
206 // printf("ContinueDebugEvent line %d\n", __LINE__); | |
207 deb_api.ContinueDebugEvent(de.process_id_, signo); | |
208 break; | |
209 } else if (words[0] == "a") { | |
210 animate = true; | |
211 deb_api.SingleStep(nacl_pid); | |
212 break; | |
213 } else if (words[0] == "e-") { | |
214 // printf("show_events = false\n"); | |
215 show_events = false; | |
216 continue; | |
217 } else if (words[0] == "ss") { | |
218 deb_api.SetupProc(de.process_id_); | |
219 continue; | |
220 } else if (words[0] == "ce") { | |
221 // deb_api.EnableSingleStep(de.process_id_, false); | |
222 // printf("ContinueDebugEvent line %d\n", __LINE__); | |
223 deb_api.ContinueDebugEvent(de.process_id_, de.signal_no_); | |
224 break; | |
225 } else if (words[0] == "cn") { | |
226 // deb_api.EnableSingleStep(de.process_id_, false); | |
227 // printf("ContinueDebugEvent line %d\n", __LINE__); | |
228 deb_api.ContinueDebugEvent(de.process_id_, 0); | |
229 break; | |
230 } else if (words[0] == "si") { | |
231 /// deb_api.EnableSingleStep(de.process_id_, true); | |
232 /// deb_api.ContinueDebugEvent(de.process_id_, 0); | |
233 printf("si %d\n", de.process_id_); | |
234 deb_api.SingleStep(de.process_id_); | |
235 break; | |
236 } else if (words[0] == "cb") { | |
237 // continue and break immediately | |
238 // deb_api.EnableSingleStep(de.process_id_, false); | |
239 // printf("ContinueDebugEvent line %d\n", __LINE__); | |
240 deb_api.ContinueDebugEvent(de.process_id_, 0); | |
241 bool res = deb_api.DebugBreak(de.process_id_); | |
242 if (!res) | |
243 printf("Error\n"); | |
244 break; | |
245 } else if ((words[0] == "m") && (words.size() >= 3)) { | |
246 void* addr = atoptr(words[1].c_str()); | |
247 int len = atoi(words[2].c_str()); | |
248 size_t rd = 0; | |
249 char buff[1024]; | |
250 printf("ReadingMem pid=%d addr=%p len=%d ...", de.process_id_, addr, l
en); | |
251 bool res = deb_api.ReadProcessMemory(de.process_id_, | |
252 addr, | |
253 buff, | |
254 len, | |
255 &rd); | |
256 printf("%d\n", (int)rd); | |
257 if (res) { | |
258 debug::Blob blob(buff, rd); | |
259 std::string str = blob.ToHexString(false); | |
260 printf("[%s]\n", str.c_str()); | |
261 } else { | |
262 printf("Error\n"); | |
263 } | |
264 } else if ((words[0] == "M") && (words.size() >= 3)) { | |
265 void* addr = atoptr(words[1].c_str()); | |
266 debug::Blob blob; | |
267 blob.LoadFromHexString(words[2]); | |
268 | |
269 void* data = blob.ToCBuffer(); | |
270 debug::Blob blob2(data, blob.Size()); | |
271 std::string str = blob2.ToHexString(false); | |
272 printf("recv[%s]\n", str.c_str()); | |
273 | |
274 if (NULL != data) { | |
275 size_t wr = 0; | |
276 bool res = deb_api.WriteProcessMemory(de.process_id_, | |
277 addr, | |
278 data, | |
279 blob.Size(), | |
280 &wr); | |
281 if (!res) | |
282 printf("Error\n"); | |
283 free(data); | |
284 } | |
285 } else if (words[0] == "g") { | |
286 user_regs_struct context; | |
287 memset(&context, 0xcc, sizeof(context)); | |
288 bool res = deb_api.ReadThreadContext(de.process_id_, &context); | |
289 debug::Blob blob(&context, sizeof(context)); | |
290 std::string str = blob.ToHexString(false); | |
291 printf("%s:[%s]\n", res ? "Ok" : "Err", str.c_str()); | |
292 deb_api.PrintThreadContext(context); | |
293 } else if (words[0] == "G") { | |
294 user_regs_struct context; | |
295 memset(&context, 0xcc, sizeof(context)); | |
296 bool res = deb_api.ReadThreadContext(de.process_id_, &context); | |
297 debug::Blob blob(&context, sizeof(context)); | |
298 std::string str = blob.ToHexString(false); | |
299 printf("%s:[%s]\n", res ? "Ok" : "Err", str.c_str()); | |
300 deb_api.PrintThreadContext(context); | |
301 | |
302 res = deb_api.WriteThreadContext(de.process_id_, &context); | |
303 printf("WriteThreadContext -> %s\n", res ? "Ok" : "Err"); | |
304 } else if (words[0] == "ip") { | |
305 char* ip = 0; | |
306 deb_api.GetIp(de.process_id_, &ip); | |
307 printf("IP = %p\n", ip); | |
308 } else if (words[0] == "ip--") { | |
309 char* ip = 0; | |
310 if (deb_api.GetIp(de.process_id_, &ip)) { | |
311 ip--; | |
312 deb_api.SetIp(de.process_id_, ip); | |
313 deb_api.GetIp(de.process_id_, &ip); | |
314 printf("IP = %p\n", ip); | |
315 } | |
316 } else if (words[0] == "ip++") { | |
317 char* ip = 0; | |
318 if (deb_api.GetIp(de.process_id_, &ip)) { | |
319 ip++; | |
320 deb_api.SetIp(de.process_id_, ip); | |
321 deb_api.GetIp(de.process_id_, &ip); | |
322 printf("IP = %p\n", ip); | |
323 } | |
324 } else if ((words[0] == "break") && (words.size() >= 2)) { | |
325 int pid = atoi(words[2].c_str()); | |
326 bool res = deb_api.DebugBreak(pid); | |
327 if (!res) | |
328 printf("Error\n"); | |
329 } | |
330 } | |
331 } | |
332 } | |
333 printf("Exiting..."); | |
334 return 1; | |
335 } | |
OLD | NEW |