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

Side by Side Diff: experimental/linux_debug_server/debugger/nacl-gdb_server/debug_server.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/nacl-gdb_server/debug_server.h"
5 #include <stdio.h>
6 #include <signal.h>
7 #include <algorithm>
8 #include "debugger/core/debuggee_thread.h"
9 #include "debugger/rsp/rsp_common_replies.h"
10 #include "debugger/rsp/rsp_control_packets.h"
11 #include "debugger/rsp/rsp_info_packets.h"
12 #include "debugger/rsp/rsp_packet_utils.h"
13 #include "debugger/rsp/rsp_packets.h"
14 #include "debugger/rsp/rsp_threads_packets.h"
15 #include "debugger/nacl-gdb_server/gdb_registers.h"
16
17 namespace {
18 const int kReadBufferSize = 1024;
19 const int kVS2008_THREAD_INFO = 0x406D1388;
20 const int kStopTimeoutMs = 1000;
21 const int kMaxPacketsToReadAtOnce = 100;
22
23 // Error codes returned to the client (debugger).
24 const int kErrorNoFocusedThread = 1;
25 const int kErrorNoFocusedProcess = 2;
26 const int kErrorSetFocusToAllThreadsIsNotSupported = 3;
27 const int kErrorReadMemoryFailed = 4;
28 const int kErrorPacketIsTooLarge = 5;
29 const int kErrorWriteMemoryFailed = 6;
30 const int kErrorGetThreadContextFailed = 7;
31 const int kErrorSetThreadContextFailed = 8;
32 const int kErrorSingleStepFailed = 9;
33 const int kErrorThreadIsDead = 10;
34 const int kErrorThreadNotFound = 11;
35
36 rsp::StopReply CreateStopReplyFromDebugEvent(const debug::DebugEvent& de) {
37 switch (de.process_state_) {
38 case debug::RUNNING: return rsp::StopReply(rsp::StopReply::STILL _RUNNING);
39 case debug::PROCESS_STOPPED: {
40 rsp::StopReply msg(rsp::StopReply::SIGNALED);
41 msg.set_signal_number(de.signal_no_);
42 return msg;
43 }
44 case debug::PROCESS_TERMINATED: {
45 rsp::StopReply msg(rsp::StopReply::TERMINATED);
46 msg.set_signal_number(de.signal_no_);
47 return msg;
48 }
49 case debug::PROCESS_EXITED: {
50 rsp::StopReply msg(rsp::StopReply::EXITED);
51 msg.set_exit_code(de.exit_code_);
52 return msg;
53 }
54 }
55 return rsp::StopReply(rsp::StopReply::EXITED);
56 }
57
58 #define AAA(x) printf("\t%s = 0x%lx\n", #x, context.x)
59
60 void PrintContext(const user_regs_struct& context) {
61 printf("Context {\n");
62 AAA(r15);
63 AAA(r14);
64 AAA(r13);
65 AAA(r12);
66 AAA(rbp);
67 AAA(rbx);
68 AAA(r11);
69 AAA(r10);
70 AAA(r9);
71 AAA(r8);
72 AAA(rax);
73 AAA(rcx);
74 AAA(rdx);
75 AAA(rsi);
76 AAA(rdi);
77 AAA(rip);
78 AAA(cs);
79 AAA(eflags);
80 AAA(rsp);
81 AAA(ss);
82 AAA(ds);
83 AAA(es);
84 AAA(fs);
85 AAA(gs);
86 printf("}\n");
87 }
88
89 } // namespace
90
91 namespace debug {
92 DebugServer::DebugServer(DebugAPI* debug_api, int listen_port)
93 : debug_api_(debug_api),
94 client_connected_(false),
95 debuggee_process_(NULL),
96 focused_thread_id_(0),
97 listen_port_(listen_port),
98 continue_from_halt_(false) {
99 }
100
101 DebugServer::~DebugServer() {
102 if (NULL != debuggee_process_) {
103 delete debuggee_process_;
104 debuggee_process_ = NULL;
105 }
106 }
107
108 bool DebugServer::Init() {
109 rsp_packetizer_.SetPacketConsumer(this);
110 debuggee_process_ = new DebuggeeProcess(debug_api_);
111 if (NULL == debuggee_process_)
112 return false;
113
114 return ListenForRspConnection();
115 }
116
117 bool DebugServer::ListenForRspConnection() {
118 bool res = listening_socket_.Listen(listen_port_);
119 if (res)
120 printf("Started listening on port %d ...\n", listen_port_);
121 else
122 printf("DebugServer::ListenForRspConnection failed port=%d",
123 listen_port_);
124
125 return res;
126 }
127
128 void DebugServer::HandleNetwork() {
129 if (!client_connection_.IsConnected()) {
130 if (client_connected_) {
131 client_connected_ = false;
132 printf("Dropped connection from debugger.\n");
133 }
134 if (listening_socket_.Accept(20, &client_connection_)) {
135 client_connected_ = true;
136 printf("Got connection from debugger.\n");
137 }
138 } else {
139 char buff[kReadBufferSize];
140 for (int i = 0; i < kMaxPacketsToReadAtOnce; i++) {
141 size_t read_bytes = client_connection_.Read(buff,
142 sizeof(buff) - 1,
143 20);
144 if (read_bytes > 0) {
145 buff[read_bytes] = 0;
146 printf("r>[%s]\n", buff);
147 rsp_packetizer_.OnData(buff, read_bytes);
148 } else {
149 break;
150 }
151 }
152 }
153 }
154
155 void DebugServer::HandleExecutionEngine() {
156 DebugEvent de;
157 if (debuggee_process_->WaitForDebugEventAndDispatchIt(&de)) {
158 // Now, we have a halted NaCl process on our hands.
159 if (0 == focused_thread_id_)
160 focused_thread_id_ = de.pid_;
161 if (continue_from_halt_) {
162 continue_from_halt_ = false;
163 SendRspMessageToClient(CreateStopReplyFromDebugEvent(de) );
164 }
165 }
166 }
167
168 void DebugServer::DoWork() {
169 HandleNetwork();
170 HandleExecutionEngine();
171 }
172
173 void DebugServer::SendRspMessageToClient(const rsp::Packet& msg) {
174 Blob text;
175 msg.ToBlob(&text);
176 Blob wire_msg;
177 rsp::PacketUtils::AddEnvelope(text, &wire_msg);
178 client_connection_.WriteAll(wire_msg);
179 printf("T>[%s]\n", text.ToString().c_str());
180 printf("t>[%s]\n", wire_msg.ToString().c_str());
181 }
182
183 DebuggeeThread* DebugServer::GetFocusedThread() {
184 DebuggeeThread* thread = debuggee_process_->GetThread(focused_thread_id_ );
185 if (NULL == thread)
186 SendErrorReply(kErrorNoFocusedThread);
187 return thread;
188 }
189
190 void DebugServer::OnUnknownCommand() {
191 // Empty RSP packet is returned for unsupported commands.
192 SendRspMessageToClient(rsp::EmptyPacket());
193 }
194
195 void DebugServer::OnPacket(const Blob& body, bool valid_checksum) {
196 if (valid_checksum)
197 client_connection_.WriteAll("+", 1); // Send low-level RSP acknowledgment.
198
199 Blob msg = body;
200 rsp::Packet* command = rsp::Packet::CreateFromBlob(&msg, NULL);
201 if (NULL != command) {
202 command->AcceptVisitor(this);
203 delete command;
204 } else {
205 OnUnknownCommand();
206 }
207 }
208
209 void DebugServer::OnUnexpectedByte(uint8_t unexpected_byte) {
210 printf("msg='DebugServer::OnUnexpectedChar' c='0x%x'",
211 static_cast<int>(unexpected_byte));
212 }
213
214 void DebugServer::SendErrorReply(int error) {
215 SendRspMessageToClient(rsp::ErrorReply(error));
216 }
217
218 void DebugServer::OnBreak() {
219 debug_api_->PostSignal(focused_thread_id_, SIGSTOP);
220 }
221
222 void DebugServer::Visit(rsp::GetStopReasonCommand* packet) {
223 DebuggeeThread* thread = GetFocusedThread();
224 if (NULL == thread)
225 return;
226 SendRspMessageToClient(CreateStopReplyFromDebugEvent(thread->last_debug_ event()));
227 }
228
229 void DebugServer::Visit(rsp::ContinueCommand* packet) {
230 DebuggeeThread* thread = GetFocusedThread();
231 if (NULL != thread) {
232 continue_from_halt_ = true;
233 debuggee_process_->Continue(focused_thread_id_);
234 }
235 }
236
237 void DebugServer::Visit(rsp::QuerySupportedCommand* packet) {
238 rsp::QuerySupportedReply reply;
239 reply.AddFeature("PacketSize", "7cf");
240 reply.AddFeature("qXfer:libraries:read", "+");
241 reply.AddFeature("qXfer:features:read", "+");
242 SendRspMessageToClient(reply);
243 }
244
245 void DebugServer::Visit(rsp::QXferFeaturesReadCommand* packet) {
246 // qXfer:features:read:target.xml:0,7ca
247 if (packet->file_name() == "target.xml") {
248 rsp::QXferReply reply;
249 reply.set_body("<target><architecture>i386:x86-64</architecture></target>");
250 reply.set_eom(true);
251 SendRspMessageToClient(reply);
252 } else {
253 OnUnknownCommand();
254 }
255 }
256
257 void DebugServer::Visit(rsp::SetCurrentThreadCommand* packet) {
258 int tid = static_cast<int>(packet->thread_id());
259 bool res = false;
260 if (-1 == tid) { // all threads
261 res = true;
262 } else if (0 == tid) { // any thread
263 res = true;
264 } else {
265 DebuggeeThread* thread = debuggee_process_->GetThread(tid);
266 if (NULL != thread) {
267 res = true;
268 focused_thread_id_ = tid;
269 }
270 }
271 if (res)
272 SendRspMessageToClient(rsp::OkReply());
273 else
274 SendErrorReply(kErrorThreadNotFound);
275 }
276
277 void DebugServer::Visit(rsp::ReadMemoryCommand* packet) {
278 size_t sz = packet->num_of_bytes();
279 if (0 == sz) {
280 SendRspMessageToClient(rsp::EmptyPacket());
281 return;
282 }
283 char buff[rsp::kMaxRspPacketSize / 2]; // 2 characters per byte.
284 if (sizeof(buff) < sz)
285 sz = sizeof(buff);
286
287 DebuggeeThread* thread = GetFocusedThread();
288 if (NULL != thread) {
289 uint64_t addr = packet->addr();
290 // massage address to support gdb
291 if (addr < debuggee_process_->nexe_mem_base())
292 addr += debuggee_process_->nexe_mem_base();
293
294 size_t rd = 0;
295 if (debug_api_->ReadMemory(focused_thread_id_, addr, buff, sz, & rd)) {
296 rsp::BlobReply reply;
297 reply.set_data(buff, sz);
298 SendRspMessageToClient(reply);
299 } else {
300 SendErrorReply(kErrorReadMemoryFailed);
301 }
302 }
303 }
304
305 void DebugServer::Visit(rsp::WriteMemoryCommand* packet) {
306 const debug::Blob& data = packet->data();
307 DebuggeeThread* thread = GetFocusedThread();
308 if (NULL != thread) {
309 char tmp[rsp::kMaxRspPacketSize];
310 if (data.size() > sizeof(tmp)) {
311 SendErrorReply(kErrorPacketIsTooLarge);
312 return;
313 }
314 data.Peek(0, tmp, data.size());
315 uint64_t addr = packet->addr();
316 // massage address to support gdb
317 if (addr < debuggee_process_->nexe_mem_base())
318 addr += debuggee_process_->nexe_mem_base();
319
320 size_t wr = 0;
321 bool res = debug_api_->WriteMemory(focused_thread_id_, addr, tmp , data.size(), &wr);
322 if (res)
323 SendRspMessageToClient(rsp::OkReply());
324 else
325 SendErrorReply(kErrorWriteMemoryFailed);
326 }
327 }
328
329 void DebugServer::Visit(rsp::ReadRegistersCommand* packet) {
330 DebuggeeThread* thread = GetFocusedThread();
331 if (NULL != thread) {
332 user_regs_struct context;
333 if (!debug_api_->ReadThreadContext(thread->id(), &context)) {
334 SendErrorReply(kErrorGetThreadContextFailed);
335 } else {
336 PrintContext(context);
337 Blob blob;
338 rsp::CONTEXTToGdbRegisters(context, &blob);
339 rsp::BlobReply reply;
340 reply.set_data(blob);
341 SendRspMessageToClient(reply);
342 }
343 }
344 }
345
346 void DebugServer::Visit(rsp::WriteRegistersCommand* packet) {
347 DebuggeeThread* thread = GetFocusedThread();
348 if (NULL != thread) {
349 user_regs_struct context;
350 if (!debug_api_->ReadThreadContext(thread->id(), &context)) {
351 SendErrorReply(kErrorGetThreadContextFailed);
352 return;
353 }
354 rsp::GdbRegistersToCONTEXT(packet->data(), &context);
355 if (!debug_api_->WriteThreadContext(thread->id(), &context))
356 SendErrorReply(kErrorSetThreadContextFailed);
357 else
358 SendRspMessageToClient(rsp::OkReply());
359 }
360 }
361
362 void DebugServer::Visit(rsp::GetCurrentThreadCommand* packet) {
363 rsp::GetCurrentThreadReply reply;
364 reply.set_value(focused_thread_id_);
365 SendRspMessageToClient(reply);
366 }
367
368 void DebugServer::Visit(rsp::StepCommand* packet) {
369 DebuggeeThread* thread = GetFocusedThread();
370 if (NULL != thread) {
371 if (!debug_api_->SingleStep(focused_thread_id_)) {
372 SendErrorReply(kErrorSingleStepFailed);
373 } else {
374 thread->Continue();
375 continue_from_halt_ = true;
376 }
377 }
378 }
379
380 void DebugServer::Visit(rsp::IsThreadAliveCommand* packet) {
381 if (NULL != debuggee_process_->GetThread(packet->value()))
382 SendRspMessageToClient(rsp::OkReply());
383 else
384 SendErrorReply(kErrorThreadNotFound);
385 }
386
387 void DebugServer::Visit(rsp::GetThreadInfoCommand* packet) {
388 rsp::GetThreadInfoReply reply;
389 if (packet->get_more()) {
390 // TODO(garianov): add support for multi-packet replies.
391 reply.set_eom(true);
392 } else {
393 std::deque<int> tids;
394 debuggee_process_->GetThreadsIds(&tids);
395 reply.set_threads_ids(tids);
396 reply.set_eom(false);
397 }
398 SendRspMessageToClient(reply);
399 }
400
401 void DebugServer::Visit(rsp::GetOffsetsCommand* packet) {
402 uint64_t mb = debuggee_process_->nexe_mem_base();
403 rsp::GetOffsetsReply reply;
404 reply.set_data_offset(mb);
405 reply.set_text_offset(mb);
406
407 SendRspMessageToClient(reply);
408 }
409
410 } // namespace debug
411
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698