Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: experimental/linux_debug_server/debugger/core/debug_api.cc

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "debugger/core/debug_api.h"
5
6 #include <errno.h>
7 #include <memory.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/syscall.h>
12 #include <sys/types.h>
13 #include <sys/user.h>
14 #include <sys/wait.h>
15 #include <unistd.h>
16
17 #include <deque>
18 #include <string>
19
20 typedef int64_t ptrace_result_t;
21
22 void Split(const char* str_in,
23 const char* delimiters,
24 std::deque<std::string>* out) {
25 char c = 0;
26 std::string str;
27 while (0 != (c = *str_in++)) {
28 if (strchr(delimiters, c)) {
29 if (str.size()) {
30 out->push_back(str);
31 str.clear();
32 }
33 } else if ((c != '\r') && (c != '\n')) {
34 str.push_back(c);
35 }
36 }
37 if (str.size())
38 out->push_back(str);
39 }
40
41 std::string GetAppPathOutOfCmdLine(const char* cmd_line) {
42 std::deque<std::string> words;
43 Split(cmd_line, " \t", &words);
44 if (words.size() > 0)
45 return words[0];
46 return cmd_line;
47 }
48
49 std::string GetAppNameOutOfCmdLine(const char* cmd_line) {
50 std::string path = GetAppPathOutOfCmdLine(cmd_line);
51 std::deque<std::string> words;
52 Split(path.c_str(), "/", &words);
53 if (words.size() > 0)
54 return words[words.size() - 1];
55 return cmd_line;
56 }
57
58 namespace {
59 const int kMaxOutputDebugStringSize = 256;
60 const char kNexePrefix[] = "{7AA7C9CF-89EC-4ed3-8DAD-6DC84302AB11}";
61 } // namespace
62
63 namespace debug {
64 bool DebugAPI::PostSignal(pid_t pid, int signo) {
65 return (0 == kill(pid, signo));
66 }
67
68 bool DebugAPI::ReadDebugString(const DebugEvent& de, std::string* string) {
69 if ((SIGTRAP != de.signal_no_) || (PROCESS_STOPPED != de.process_state_))
70 return false;
71
72 user_regs_struct context;
73 if (!ReadThreadContext(de.pid_, &context))
74 return false;
75
76 uint64_t addr = context.rax;
77 char buff[kMaxOutputDebugStringSize];
78 size_t rd = 0;
79 ReadMemory(de.pid_, addr, buff, sizeof(buff) - 1, &rd);
80 if (rd < sizeof(kNexePrefix))
81 return false;
82 if (strncmp(buff, kNexePrefix, sizeof(kNexePrefix) - 1) != 0)
83 return false;
84
85 buff[sizeof(buff) - 1] = 0;
86 *string = &buff[sizeof(kNexePrefix) - 1];
87 printf("DebugString-[%s]\n", string->c_str());
88 return true;
89 }
90
91 bool DebugAPI::ContinueDebugEvent(pid_t pid, int signo) {
92 ptrace_result_t res = ptrace(PTRACE_CONT, pid, 0, reinterpret_cast<void*>(sign o));
93 return (0 == res);
94 }
95
96 bool DebugAPI::StartProcess(const char* cmd_line,
97 bool trace,
98 pid_t* child_pid_out) {
99 std::string path = GetAppPathOutOfCmdLine(cmd_line);
100 std::string app_name = GetAppNameOutOfCmdLine(cmd_line);
101
102 pid_t child_pid = fork();
103 printf("fork -> %d\n", child_pid);
104 if (-1 == child_pid)
105 return false;
106
107 if (0 == child_pid) {
108 // in child
109 if (trace)
110 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
111 int res = execl(path.c_str(), app_name.c_str(), "", NULL);
112
113 // TODO(garianov): how to communicate failure of execl to the debugger
114 // process?
115 // My guess is parent proc/debugger will get SIGTERM signal or TERM debug ev ent...
116 printf("in child: execl -> %d errno=%d\n", res, errno);
117 exit(13);
118 } else {
119 // in parent
120 if (NULL != child_pid_out)
121 *child_pid_out = child_pid;
122 }
123 return true;
124 }
125
126 bool DebugAPI::SetupProc(pid_t pid) {
127 intptr_t mask =
128 PTRACE_O_TRACEFORK |
129 PTRACE_O_TRACEVFORK |
130 PTRACE_O_TRACECLONE ;
131 void* data = reinterpret_cast<void*>(mask);
132 ptrace_result_t res = ptrace(PTRACE_SETOPTIONS, pid, 0, data);
133 if (0 != res) {
134 printf("Error: ptrace(PTRACE_SETOPTIONS(pid=%d) -> %s\n", pid, strerror(errn o));
135 }
136 return (0 != res);
137 }
138
139 bool DebugAPI::DebugBreak(pid_t pid) {
140 return PostSignal(pid, SIGSTOP);
141 }
142
143 bool DebugAPI::SingleStep(pid_t pid) {
144 ptrace_result_t res = ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
145 return (0 == res);
146 }
147
148
149 bool DebugAPI::WriteMemory(pid_t pid,
150 uint64_t addr,
151 void* src,
152 size_t size,
153 size_t* written_bytes_out) {
154 size_t written_bytes = 0;
155 size_t left_bytes = size;
156 ptrace_result_t res = 0;
157 const size_t bundle_sz = sizeof(res);
158 unsigned char* ptr_src = reinterpret_cast<unsigned char*>(src);
159 unsigned char* ptr_addr = reinterpret_cast<unsigned char*>(addr);
160
161 // Read first few bytes that rea not aligned on 4 (or 8 on 64-bit)
162 // bytes, if any.
163 uint64_t offset = addr;
164 size_t offset_from_4bytes = offset % bundle_sz;
165 if (0 != offset_from_4bytes) {
166 // printf("offset_from_4bytes = %d\n", (int)offset_from_4bytes);
167 unsigned char* beg_addr =
168 reinterpret_cast<unsigned char*>(offset - offset_from_4bytes);
169 res = ptrace(PTRACE_PEEKDATA, pid, beg_addr, 0);
170 // printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", beg_addr, res);
171 if (0 != errno) {
172 // printf("%d ptrace -> %d\n", __LINE__, errno);
173 return false;
174 }
175 unsigned char* p =
176 reinterpret_cast<unsigned char*>(&res) + offset_from_4bytes;
177 written_bytes = bundle_sz - offset_from_4bytes;
178 if (written_bytes > size)
179 written_bytes = size;
180
181 memcpy(p, ptr_src, written_bytes);
182 ptrace_result_t res2 = ptrace(PTRACE_POKEDATA, pid, beg_addr, reinterpret_ca st<void*>(res));
183 // printf("ptrace(PTRACE_POKEDATA(%p, 0x%lX) -> 0x%lX\n",
184 // beg_addr,
185 // res,
186 // res2);
187 if (0 != res2) {
188 // printf("%d ptrace(PTRACE_POKEDATA) -> %d\n", errno, __LINE__);
189 return false;
190 }
191
192 ptr_src += written_bytes;
193 ptr_addr += written_bytes;
194 left_bytes -= written_bytes;
195 }
196
197 while (left_bytes) {
198 size_t wr_bytes = bundle_sz;
199 if (wr_bytes > left_bytes)
200 wr_bytes = left_bytes;
201
202 ptrace_result_t data = 0;
203 if (left_bytes < bundle_sz) {
204 data = ptrace(PTRACE_PEEKDATA, pid, ptr_addr, 0);
205 if (0 != errno) {
206 // printf("%d ptrace(PTRACE_PEEKDATA) -> 0x%lX\n", __LINE__, data);
207 return false;
208 }
209 // printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", ptr_addr, data);
210 }
211 memcpy(&data, ptr_src, wr_bytes);
212 // printf("memcpy... %X\n", (unsigned int)(*ptr_src));
213 // printf("PTRACE_POKEDATA(%p) %lX\n", ptr_addr, data);
214
215 ptrace_result_t res = ptrace(PTRACE_POKEDATA, pid, ptr_addr, reinterpret_cas t<void*>(data));
216 if (0 != res) {
217 return false;
218 }
219
220 written_bytes += wr_bytes;
221 ptr_src += written_bytes;
222 ptr_addr += written_bytes;
223 left_bytes -= wr_bytes;
224 }
225
226 if (NULL != written_bytes_out)
227 *written_bytes_out = written_bytes;
228 return (size == written_bytes);
229 }
230
231 bool DebugAPI::ReadMemory(pid_t pid,
232 uint64_t addr,
233 void* dest,
234 size_t size,
235 size_t* readed_bytes_out) {
236 size_t readed_bytes = 0;
237 size_t left_bytes = size;
238 ptrace_result_t res = 0;
239 const size_t bundle_sz = sizeof(res);
240 char* ptr_dest = reinterpret_cast<char*>(dest);
241 char* ptr_addr = reinterpret_cast<char*>(addr);
242 //printf("DebugApi::ReadProcessMemory(%d, %p, %d)\n", pid, addr, (int)size);
243 //printf("left_bytes = %d\n", (int)left_bytes);
244
245 // Read first few bytes that rea not aligned on 4 (or 8 on 64-bit)
246 // bytes, if any.
247 uint64_t offset = addr;
248 size_t offset_from_4bytes = offset % bundle_sz;
249 //printf("===>>>>> offset_from_4bytes=%ld\n", offset_from_4bytes);
250 fflush(stdout);
251 if (0 != offset_from_4bytes) {
252 char* beg_addr = reinterpret_cast<char*>(offset - offset_from_4bytes);
253 res = ptrace(PTRACE_PEEKDATA, pid, beg_addr, 0);
254 //printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", beg_addr, res);
255 if (0 != errno) {
256 //printf("ptrace -> %d\n", errno);
257 //printf("Errno: %s\n", strerror(errno));
258 return false;
259 }
260 char* src = reinterpret_cast<char*>(&res) + offset_from_4bytes;
261 readed_bytes = bundle_sz - offset_from_4bytes;
262 //printf("readed_bytes = %d\n", (int)readed_bytes);
263 memcpy(ptr_dest, src, readed_bytes);
264 ptr_dest += readed_bytes;
265 ptr_addr += readed_bytes;
266 if (readed_bytes > left_bytes)
267 left_bytes = 0;
268 else
269 left_bytes -= readed_bytes;
270 //printf("left_bytes = %d\n", (int)left_bytes);
271 }
272
273 while (left_bytes) {
274 //printf("left_bytes = %d\n", (int)left_bytes);
275 res = ptrace(PTRACE_PEEKDATA, pid, ptr_addr, 0);
276 //printf("ptrace(PTRACE_PEEKDATA(%p) -> 0x%lX\n", ptr_addr, res);
277 if (0 != errno) {
278 //printf("Errno: %s\n", strerror(errno));
279 break;
280 }
281 size_t rd_bytes = bundle_sz;
282 if (rd_bytes > left_bytes)
283 rd_bytes = left_bytes;
284
285 //printf("rd_bytes = %d\n", (int)rd_bytes);
286 memcpy(ptr_dest, &res, rd_bytes);
287 readed_bytes += rd_bytes;
288 ptr_dest += rd_bytes;
289 ptr_addr += rd_bytes;
290 left_bytes -= rd_bytes;
291 }
292 if (NULL != readed_bytes_out)
293 *readed_bytes_out = readed_bytes;
294 //printf("size=%d readed_bytes=%d\n", (int)size, (int)readed_bytes);
295 return (size <= readed_bytes);
296 }
297
298 bool DebugAPI::ReadThreadContext(pid_t pid, user_regs_struct* context) {
299 int ret = ptrace(PTRACE_GETREGS, pid, NULL, context);
300 return (0 == ret);
301 }
302
303 bool DebugAPI::WriteThreadContext(pid_t pid, user_regs_struct* context) {
304 int ret = ptrace(PTRACE_SETREGS, pid, NULL, context);
305 return (0 == ret);
306 }
307
308 bool DebugAPI::WaitForDebugEvent(DebugEvent* de) {
309 de->pid_ = 0;
310 de->signal_no_ = 0;
311 de->exit_code_ = 0;
312 de->process_state_ = PROCESS_STOPPED;
313
314 int status = 0;
315 int options = WNOHANG | __WALL;
316 int res = waitpid(-1, &status, options);
317 if (-1 == res)
318 return false;
319
320 bool event_received = (0 != res);
321 if (event_received) {
322 de->pid_ = res;
323 if (WIFEXITED(status)) {
324 de->process_state_ = PROCESS_EXITED;
325 de->exit_code_ = WEXITSTATUS(status);
326 } else if (WIFSIGNALED(status)) {
327 de->process_state_ = PROCESS_TERMINATED;
328 de->signal_no_ = WTERMSIG(status);
329 } else if (WIFSTOPPED(status)) {
330 de->process_state_ = PROCESS_STOPPED;
331 de->signal_no_ = WSTOPSIG(status);
332 } else if (WIFCONTINUED(status)) {
333 de->process_state_ = PROCESS_STOPPED;
334 de->signal_no_ = 0;
335 }
336 }
337 return event_received;
338 }
339
340 } // namespace debug
341
OLDNEW
« no previous file with comments | « experimental/linux_debug_server/debugger/core/debug_api.h ('k') | experimental/linux_debug_server/debugger/core/debug_event.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698