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

Side by Side Diff: src/trusted/gdb_rsp/target.cc

Issue 5633007: This change contains changes that were made on a separate copy of this code,... (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 10 years 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 | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright 2010 The Native Client Authors. All rights reserved. 2 * Copyright 2010 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can 3 * Use of this source code is governed by a BSD-style license that can
4 * be found in the LICENSE file. 4 * be found in the LICENSE file.
5 */ 5 */
6 6
7 #include <string.h> 7 #include <string.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <stdio.h> 9 #include <stdio.h>
10 10
(...skipping 15 matching lines...) Expand all
26 using port::IEvent; 26 using port::IEvent;
27 using port::IMutex; 27 using port::IMutex;
28 using port::IPlatform; 28 using port::IPlatform;
29 using port::IThread; 29 using port::IThread;
30 using port::MutexLock; 30 using port::MutexLock;
31 31
32 namespace gdb_rsp { 32 namespace gdb_rsp {
33 33
34 34
35 Target::Target(const Abi* abi) 35 Target::Target(const Abi* abi)
36 : abi_(abi), 36 : abi_(abi),
noelallen_use_chromium 2010/12/07 23:04:44 This should generate a warning. Initializers nee
mlinck 2010/12/10 21:10:27 In this particular case, it is the same order as i
37 mutex_(NULL), 37 stateMutex_(NULL),
38 publicMutex_(NULL),
38 sig_start_(NULL), 39 sig_start_(NULL),
39 sig_done_(NULL), 40 sig_done_(NULL),
40 send_done_(false),
41 ctx_(NULL), 41 ctx_(NULL),
42 cur_signal_(-1), 42 cur_signal_(-1),
43 sig_thread_(0), 43 sig_thread_(0),
44 run_thread_(-1), 44 run_req_(-1),
mmortensen 2010/12/07 22:53:58 Since this is an unsigned int, do we cause warning
mlinck 2010/12/10 21:10:27 I'll resolve this once I get some feedback on how
45 reg_thread_(-1) { 45 run_last_(0),
46 if (NULL == abi_) abi_ = Abi::Get(); 46 reg_req_(-1),
47 reg_last_(0) {
48 printf("Target constructed ");
noelallen_use_chromium 2010/12/07 23:04:44 looks like bogus prints. Fix this one and the on
mlinck 2010/12/10 21:10:27 Done.
49 if (NULL == abi_) {
50 printf("without ABI.\n");
51 abi_ = Abi::Get();
52 } else {
53 printf("with ABI.\n");
54 }
55 printf("Target got ABI: %s \n", abi_->GetName());
47 } 56 }
48 57
49 Target::~Target() { 58 Target::~Target() {
50 Destroy(); 59 Destroy();
51 } 60 }
52 61
53 bool Target::Init() { 62 bool Target::Init() {
54 string targ_xml = "l<target><architecture>"; 63 stateMutex_ = IMutex::Allocate();
55 64 publicMutex_ = IMutex::Allocate();
56 targ_xml += abi_->GetName();
57 targ_xml += "</architecture></target>";
58
59 // Set a more specific result which won't change.
60 properties_["target.xml"] = targ_xml;
61 properties_["Supported"] =
62 "PacketSize=7cf;qXfer:libraries:read+;qXfer:features:read+";
63
64 mutex_ = IMutex::Allocate();
65 sig_start_ = IEvent::Allocate(); 65 sig_start_ = IEvent::Allocate();
66 sig_done_ = IEvent::Allocate(); 66 sig_done_ = IEvent::Allocate();
67 ctx_ = new uint8_t[abi_->GetContextSize()]; 67 ctx_ = new uint8_t[abi_->GetContextSize()];
68 68
69 if ((NULL == mutex_) || (NULL == sig_start_) || (NULL == sig_done_) 69 if ((NULL == stateMutex_) || (NULL == publicMutex_) || (NULL == sig_start_)
70 || (NULL == ctx_)) { 70 || (NULL == sig_done_) || (NULL == ctx_)) {
71 Destroy(); 71 Destroy();
72 return false; 72 return false;
73 } 73 }
74 74
75 string targ_xml = "l<target><architecture>";
76 targ_xml += abi_->GetName();
77 printf("Populating Target Architecture with: #%s#.\n", abi_->GetName());
noelallen_use_chromium 2010/12/07 23:04:44 print (I'll assume you will grep for print instead
78 targ_xml += "</architecture></target>";
79
80 // Set a more specific result which won't change.
81 SetProperty("Xfer:features:read:target.xml", targ_xml);
82 SetProperty("Supported",
83 "PacketSize=7cf;qXfer:libraries:read+;qXfer:features:read+");
84
75 // Allow one exception to happen 85 // Allow one exception to happen
76 sig_start_->Signal(); 86 sig_start_->Signal();
77 return true; 87 return true;
78 } 88 }
79 89
90 bool Target::SetProperty(const std::string& name, const std::string& val) {
91 MutexLock lock(publicMutex_);
92 printf("SetProperty called with: %s.\n", name.c_str());
93 properties_[name] = val;
94 return true;
95 }
96
97 bool Target::GetProperty(const std::string& name, std::string* val) const {
98 MutexLock lock(publicMutex_);
99 PropertyMap_t::const_iterator itr = properties_.find(name);
100 if (itr == properties_.end()) return false;
101
102 *val = itr->second;
103 return true;
104 }
105
106 // MatchQuery looks for the longest prefix match, and returns that value.
107 // A match key is in one of two forms:
108 // 1 - <keyA>[:<keyB>[:<keyC>[...]]]
109 // 2 - <Cmd>:<Type>:read/write:<Object>:<start>,<end>
110 // We look for the second case, and assume the first if the format does not
111 // match. The second case is special in that it encodes a substring request.
112 // This allows transfers of very large values on a transport with a much
113 // smaller max packet size.
114 size_t Target::MatchQuery(const std::string& match, std::string* val) const {
115 // Starting at longest match...
116 stringvec parts = StringSplit(match, ":");
117 for (size_t cnt = parts.size(); cnt ; cnt--) {
118 // Append the sub-parts and look for a match.
119 std::string cmp;
120 for (size_t i = 0; i < cnt; i++) {
121 if (i) cmp += ":";
122 cmp += parts[i];
123 }
124
125 // If we find this cached value, return it and the match length
126 if (GetProperty(cmp, val)) {
127 // Check for a "<CMD>:<TYPE>:read:<OBJ>:<start>,<len>
128 if ((cnt == 4) && (parts[3] == "read") && (parts.size() == 5)) {
129 // Split the start,length field
130 stringvec args = StringSplit(parts[4], ",");
131 if (args.size() != 2) return cnt;
132
133 std::string tmp = *val;
134 size_t offs = strtoul(args[0].data(), NULL, 16);
135 size_t max = strtoul(args[1].data(), NULL, 16) + offs;
136 size_t len = tmp.size();
137
138 // Clear val and only send the requested portion
139 *val = "";
140 if (max >= len) max = len;
141 while (offs < max) {
142 *val += tmp[offs];
143 offs++;
144 }
145 }
146 return cnt;
147 }
148 }
149 return 0;
150 }
151
80 void Target::Destroy() { 152 void Target::Destroy() {
81 if (mutex_) IMutex::Free(mutex_); 153 if (stateMutex_) IMutex::Free(stateMutex_);
154 if (publicMutex_) IMutex::Free(publicMutex_);
82 if (sig_start_) IEvent::Free(sig_start_); 155 if (sig_start_) IEvent::Free(sig_start_);
83 if (sig_done_) IEvent::Free(sig_done_); 156 if (sig_done_) IEvent::Free(sig_done_);
84 157
85 delete[] ctx_; 158 delete[] ctx_;
86 } 159 }
87 160
88 bool Target::AddTemporaryBreakpoint(uint64_t address) { 161 bool Target::AddTemporaryBreakpoint(uint64_t address) {
162 MutexLock lock(publicMutex_);
89 const Abi::BPDef *bp = abi_->GetBreakpointDef(); 163 const Abi::BPDef *bp = abi_->GetBreakpointDef();
90 164
91 // If this ABI does not support breakpoints then fail 165 // If this ABI does not support breakpoints then fail
92 if (NULL == bp) return false; 166 if (NULL == bp) return false;
93 167
94 // If we alreay have a breakpoint here then don't add it 168 // If we already have a breakpoint here then don't add it
95 BreakMap_t::iterator itr = breakMap_.find(address); 169 BreakMap_t::iterator itr = breakMap_.find(address);
96 if (itr != breakMap_.end()) return false; 170 if (itr != breakMap_.end()) return false;
97 171
98 uint8_t *data = new uint8_t[bp->size_]; 172 uint8_t *data = new uint8_t[bp->size_];
99 if (NULL == data) return false; 173 if (NULL == data) return false;
100 174
101 // Copy the old code from here 175 // Copy the old code from here
102 if (IPlatform::GetMemory(address, bp->size_, data) == false) { 176 if (IPlatform::GetMemory(address, bp->size_, data) == false) {
103 delete[] data; 177 delete[] data;
104 return false; 178 return false;
105 } 179 }
106 if (IPlatform::SetMemory(address, bp->size_, bp->code_) == false) { 180 if (IPlatform::SetMemory(address, bp->size_, bp->code_) == false) {
107 delete[] data; 181 delete[] data;
108 return false; 182 return false;
109 } 183 }
110 184
111 breakMap_[address] = data; 185 breakMap_[address] = data;
112 return true; 186 return true;
113 } 187 }
114 188
115 bool Target::RemoveTemporaryBreakpoints() { 189 bool Target::RemoveTemporaryBreakpoints() {
190 MutexLock lock(publicMutex_);
116 const Abi::BPDef *bp = abi_->GetBreakpointDef(); 191 const Abi::BPDef *bp = abi_->GetBreakpointDef();
117 192
118 // Iterate through the map, removing breakpoints 193 // Iterate through the map, removing breakpoints
119 while (!breakMap_.empty()) { 194 while (!breakMap_.empty()) {
120 // Copy the key/value locally 195 // Copy the key/value locally
121 BreakMap_t::iterator cur = breakMap_.begin(); 196 BreakMap_t::iterator cur = breakMap_.begin();
122 uint64_t addr = cur->first; 197 uint64_t addr = cur->first;
123 uint8_t *data = cur->second; 198 uint8_t *data = cur->second;
124 199
125 // Then remove it from the map 200 // Then remove it from the map
126 breakMap_.erase(cur); 201 breakMap_.erase(cur);
127 202
128 // Copy back the old code, and free the data 203 // Copy back the old code, and free the data
129 IPlatform::SetMemory(addr, bp->size_, data); 204 IPlatform::SetMemory(addr, bp->size_, data);
130 delete[] data; 205 delete[] data;
131 } 206 }
132 207
133 return true; 208 return true;
134 } 209 }
135 210
136 211
137
138 void Target::Signal(uint32_t id, int8_t sig, bool wait) { 212 void Target::Signal(uint32_t id, int8_t sig, bool wait) {
139 // Wait for this signal's turn in the signal Q. 213 // Wait for this signal's turn in the signal Q.
140 sig_start_->Wait(); 214 sig_start_->Wait();
141 { 215 {
142 // Now lock the target, sleeping all active threads 216 // Lock the signal state information to revent a race
143 MutexLock lock(mutex_); 217 MutexLock lock(stateMutex_);
144 218
145 // Suspend all threads except this one 219 // Signal the stub that we are ready to process a trap
146 uint32_t curId; 220 // by locking the signal information, and updating it.
147 bool more = GetFirstThreadId(&curId); 221 sig_thread_ = id;
148 while (more) {
149 if (curId != id) {
150 IThread *thread = threads_[curId];
151 thread->Suspend();
152 }
153 more = GetNextThreadId(&curId);
154 }
155
156 // Signal the stub (Run thread) that we are ready to process
157 // a trap, by updating the signal information and releasing
158 // the lock.
159 reg_thread_ = id;
160 run_thread_ = id;
161 cur_signal_ = sig; 222 cur_signal_ = sig;
162 } 223 }
163 224
164 // Wait for permission to continue 225 // Wait for permission to continue
165 if (wait) sig_done_->Wait(); 226 if (wait) sig_done_->Wait();
166 } 227 }
167 228
229 void Target::Update() {
230 // Next update the current thread info
231 char tmp[16];
232 snprintf(tmp, sizeof(tmp), "QC%x", sig_thread_);
233 SetProperty("C", tmp);
234 }
235
236 void Target::Pause() {
237 // put all active threads to sleep.
238 uint32_t curId;
239 bool more = GetFirstThreadId(&curId);
240 while (more) {
241 IThread *thread = GetThread(curId);
242 if (thread->GetState() == IThread::RUNNING) thread->Suspend();
243 more = GetNextThreadId(&curId);
244 }
245 }
246
247 void Target::Resume() {
248 // Now that we are done, we want to continue in the "correct order".
249 // This means letting the active thread go first, in case we are single
250 // stepping and want to catch it again. This is a desired behavior but
251 // it is not guaranteed since another thread may already be in an
252 // exception state and next in line to notify the target.
253
254 // Wake up the run thread if it needs it, so it can go first
255 IThread* thread = GetThread(GetRunThreadId());
256 if (thread->GetState() == IThread::SUSPENDED) thread->Resume();
257
258 // If we took an exception, let the handler resume and allow
259 // the next exception to trigger (although it will still
260 // block until we release the mutex).
261 if (cur_signal_) {
262 sig_done_->Signal();
263 sig_start_->Signal();
264 }
265
266 // Now wake up everyone else that needs it
267 uint32_t curId;
268 bool more = GetFirstThreadId(&curId);
269 while (more) {
270 IThread* thread = GetThread(curId);
271
272 // Definitely don't mess with breakpoint state here and let debugger decide
273 // when it's time to turn off breakpoints.
274 if (thread->GetState() == IThread::SUSPENDED) thread->Resume();
275 more = GetNextThreadId(&curId);
276 }
277 }
278
168 void Target::Run(Session *ses) { 279 void Target::Run(Session *ses) {
169 bool first = true; 280 bool first = true;
281
170 do { 282 do {
171 // Give everyone else a chance to use the lock 283 // Give everyone else a chance to use the lock
172 IPlatform::Relinquish(100); 284 IPlatform::Relinquish(100);
173 285
174 // Lock to prevent anyone else from modifying threads 286 // Lock to prevent anyone else from modifying threads
175 // or updating the signal information. 287 // or updating the signal information.
176 MutexLock lock(mutex_); 288 MutexLock lock(stateMutex_);
177 Packet recv, reply; 289 Packet recv, reply;
178 290
179 uint32_t id = 0;
180
181 // If no signal is waiting for this iteration... 291 // If no signal is waiting for this iteration...
182 if (-1 == cur_signal_) { 292 if (-1 == cur_signal_) {
183 // but the debugger is talking to us then force a break 293 // but the debugger is talking to use
184 if (ses->DataAvailable()) { 294 if (ses->DataAvailable()) {
185 // set signal to 0 to signify paused 295 // Then simulate a signal, by setting the state data
296 // Set signal to 0 to signify paused
186 cur_signal_ = 0; 297 cur_signal_ = 0;
187 298
188 // put all the threads to sleep. 299 // Set the "signaling" thread to the preferred thread
189 uint32_t curId; 300 sig_thread_ = GetRunThreadId();
190 bool more = GetFirstThreadId(&curId);
191 while (more) {
192 if (curId != id) {
193 IThread *thread = threads_[curId];
194 thread->Suspend();
195 }
196 more = GetNextThreadId(&curId);
197 }
198 } else { 301 } else {
199 // otherwise, nothing to do so try again. 302 // otherwise, we are not signaled, and we are not chatting
303 // release the lock, and try again.
200 continue; 304 continue;
201 } 305 }
202 } else {
203 // otherwise there really is an exception so get the id of the thread
204 id = GetRegThreadId();
205 } 306 }
206 307
207 // If we got this far, then there is some kind of signal. 308 // We have a signal, so pause everyone
208 // So first, remove the breakpoints 309 Pause();
209 RemoveTemporaryBreakpoints();
210 310
211 // Next update the current thread info 311 // Update our local state information
212 char tmp[16]; 312 Update();
213 snprintf(tmp, sizeof(tmp), "QC%x", id);
214 properties_["C"] = tmp;
215 313
216 if (first) { 314 if (first) {
217 // First time on a connection, we don't sent the signal 315 // First time on a connection, we don't send the signal
218 first = false; 316 first = false;
219 } else { 317 } else {
220 // All other times, send the signal that triggered us 318 // All other times, send the signal that triggered us
221 Packet pktOut; 319 Packet pktOut;
222 pktOut.AddRawChar('S'); 320 pktOut.AddRawChar('S');
223 pktOut.AddWord8(cur_signal_); 321 pktOut.AddWord8(cur_signal_);
224 ses->SendPacketOnly(&pktOut); 322 ses->SendPacketOnly(&pktOut);
225 } 323 }
226 324
227 // Now we are ready to process commands 325 // Now we are ready to process commands
228 // Loop through packets until we process a continue 326 // Loop through packets until we process a continue
229 // packet. 327 // packet.
230 do { 328 do {
231 if (ses->GetPacket(&recv)) { 329 if (ses->GetPacket(&recv)) {
232 reply.Clear(); 330 reply.Clear();
233 if (ProcessPacket(&recv, &reply)) { 331 if (ProcessPacket(&recv, &reply)) {
234 // If this is a continue command, break out of this loop 332 // If this is a continue command, break out of this loop
235 break; 333 break;
236 } else { 334 } else {
237 // Othwerise send the reponse 335 // Otherwise send the reponse
238 ses->SendPacket(&reply); 336 ses->SendPacket(&reply);
239 } 337 }
240 } 338 }
241 } while (ses->Connected()); 339 } while (ses->Connected());
242 340
341 // Start everyone again.
342 Resume();
243 343
244 // Now that we are done, we want to continue in the "correct order". 344 // Reset our state before we return, clearing the signal. However
245 // This means letting the active thread go first, in case we are single 345 // we do not reset run_thread or reg_thread to preserve the last context.
246 // stepping and want to catch it again. This is a desired behavior but 346 cur_signal_ = -1;
247 // it is not guaranteed since another thread may already be in an 347 sig_thread_ = 0;
248 // exception state and next in line to notify the target.
249 348
250 // If the run thread is not the exception thread, wake it up now. 349 // At this point, we destroy the MutexLock, allowing anyone else to
251 uint32_t run_thread = GetRunThreadId(); 350 // and/remove threads or register a new signal.
252 if (run_thread != id
253 && run_thread != static_cast<uint32_t>(-1)) {
254 IThread* thread = threads_[run_thread];
255 thread->Resume();
256 }
257
258 // Next, wake up the exception thread, if there is one and it needs
259 // to wake up.
260 if (id && send_done_) sig_done_->Signal();
261
262 // Now wake up everyone else
263 uint32_t curId;
264 bool more = GetFirstThreadId(&curId);
265 while (more) {
266 if ((curId != id) && (curId != GetRunThreadId())) {
267 IThread *thread = threads_[curId];
268 thread->Resume();
269 }
270 more = GetNextThreadId(&curId);
271 }
272
273 // Reset the signal value
274 cur_signal_ = -1;
275
276 // If we took an exception, let the handler resume and allow
277 // the next exception to come in.
278 if (cur_signal_) {
279 sig_done_->Signal();
280 sig_start_->Signal();
281 }
282
283 // Continue running until the connection is lost. 351 // Continue running until the connection is lost.
284 } while (ses->Connected()); 352 } while (ses->Connected());
285 } 353 }
286 354
287 355
288
289
290 bool Target::GetFirstThreadId(uint32_t *id) { 356 bool Target::GetFirstThreadId(uint32_t *id) {
291 threadItr_ = threads_.begin(); 357 threadItr_ = threads_.begin();
292 return GetNextThreadId(id); 358 return GetNextThreadId(id);
293 } 359 }
294 360
295 bool Target::GetNextThreadId(uint32_t *id) { 361 bool Target::GetNextThreadId(uint32_t *id) {
296 if (threadItr_ == threads_.end()) return false; 362 if (threadItr_ == threads_.end()) return false;
297 363
298 *id = (*threadItr_).first; 364 *id = (*threadItr_).first;
299 threadItr_++; 365 threadItr_++;
300 366
301 return true; 367 return true;
302 } 368 }
303 369
304 370
305
306 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) { 371 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) {
307 char cmd; 372 char cmd;
308 int32_t seq = -1; 373 int32_t seq = -1;
309 ErrDef err = NONE; 374 ErrDef err = NONE;
310 375
311 // Clear the outbound message 376 // Clear the outbound message
312 pktOut->Clear(); 377 pktOut->Clear();
313 378
314 // Pull out the sequence. 379 // Pull out the sequence.
315 pktIn->GetSequence(&seq); 380 pktIn->GetSequence(&seq);
316 if (seq != -1) pktOut->SetSequence(seq); 381 if (seq != -1) pktOut->SetSequence(seq);
317 382
318 // Find the command 383 // Find the command
319 pktIn->GetRawChar(&cmd); 384 pktIn->GetRawChar(&cmd);
320 385
321 switch (cmd) { 386 switch (cmd) {
387 // In the case of a force break, drop through
388 // and print the signal. We have already suspended
389 // the threads at this point.
390 case 0x03:
391
322 // IN : $? 392 // IN : $?
323 // OUT: $Sxx 393 // OUT: $Sxx
324 case '?': 394 case '?':
395 // This case asks why the target has halted.
325 pktOut->AddRawChar('S'); 396 pktOut->AddRawChar('S');
326 pktOut->AddWord8(cur_signal_); 397 pktOut->AddWord8(cur_signal_);
327 break; 398 break;
328 399
329 // IN : $d 400 // IN : $d
330 // OUT: -NONE- 401 // OUT: -NONE-
331 case 'd': 402 case 'd':
403 // This packet could be asking the debugger to detach but
404 // we should never receive it.
332 Detach(); 405 Detach();
333 break; 406 return true;
334 407
335 // IN : $g 408 // IN : $g
336 // OUT: $xx...xx 409 // OUT: $xx...xx
337 case 'g': { 410 case 'g': {
411 // This packet is requesting the value of a general register.
338 uint32_t id = GetRegThreadId(); 412 uint32_t id = GetRegThreadId();
339 if (0 == id) { 413 if (0 == id) {
340 err = BAD_ARGS; 414 err = BAD_ARGS;
341 break; 415 break;
342 } 416 }
343 417
344 IThread *thread = GetThread(id); 418 IThread *thread = GetThread(id);
345 if (NULL == thread) { 419 if (NULL == thread) {
346 err = BAD_ARGS; 420 err = BAD_ARGS;
347 break; 421 break;
348 } 422 }
349 423
350 // Copy OS preserved registers to GDB payload 424 // Copy OS preserved registers to GDB payload
351 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) { 425 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
352 const Abi::RegDef *def = abi_->GetRegisterDef(a); 426 const Abi::RegDef *def = abi_->GetRegisterDef(a);
353 thread->GetRegister(a, &ctx_[def->offset_], def->bytes_); 427 thread->GetRegister(a, &ctx_[def->offset_], def->bytes_);
354 } 428 }
355 429
356 pktOut->AddBlock(ctx_, abi_->GetContextSize()); 430 pktOut->AddBlock(ctx_, abi_->GetContextSize());
357 break; 431 break;
358 } 432 }
359 433
360 // IN : $Gxx..xx 434 // IN : $Gxx..xx
361 // OUT: $OK 435 // OUT: $OK
362 case 'G': { 436 case 'G': {
437 // This packet is requesting that the value of a general register be
438 // changed to something else.
363 uint32_t id = GetRegThreadId(); 439 uint32_t id = GetRegThreadId();
364 if (0 == id) { 440 if (0 == id) {
365 err = BAD_ARGS; 441 err = BAD_ARGS;
366 break; 442 break;
367 } 443 }
368 444
369 IThread *thread = threads_[id]; 445 IThread *thread = threads_[id];
370 if (NULL == thread) { 446 if (NULL == thread) {
371 err = BAD_ARGS; 447 err = BAD_ARGS;
372 break; 448 break;
373 } 449 }
374 450
375 // GDB payload to OS registers 451 // GDB payload to OS registers
376 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) { 452 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
377 const Abi::RegDef *def = abi_->GetRegisterDef(a); 453 const Abi::RegDef *def = abi_->GetRegisterDef(a);
378 thread->SetRegister(a, &ctx_[def->offset_], def->bytes_); 454 thread->SetRegister(a, &ctx_[def->offset_], def->bytes_);
379 } 455 }
380 pktOut->AddBlock(ctx_, abi_->GetContextSize()); 456 pktOut->AddBlock(ctx_, abi_->GetContextSize());
381 break; 457 break;
382 } 458 }
383 459
384 // IN : $H(c/g)(-1,0,xxxx) 460 // IN : $H(c/g)(-1,0,xxxx)
385 // OUT: $OK 461 // OUT: $OK
386 case 'H': { 462 case 'H': {
387 char type; 463 // This packet is requesting that the thread be set for subsequent
388 uint64_t id; 464 // operations.
465 char type;
466 uint64_t id;
389 467
390 if (!pktIn->GetRawChar(&type)) { 468 if (!pktIn->GetRawChar(&type)) {
391 err = BAD_FORMAT; 469 err = BAD_FORMAT;
470 break;
471 }
472 if (!pktIn->GetNumberSep(&id, 0)) {
473 err = BAD_FORMAT;
474 break;
475 }
476
477 if (threads_.begin() == threads_.end()) {
478 err = BAD_ARGS;
479 break;
480 }
481
482 // If we are using "any" get the first thread
483 if (id == static_cast<uint64_t>(-1)) id = threads_.begin()->first;
484
485 // Verify that we have the thread
486 if (threads_.find(static_cast<uint32_t>(id)) == threads_.end()) {
487 err = BAD_ARGS;
488 break;
489 }
490
491 pktOut->AddString("OK");
492 switch (type) {
493 case 'g':
494 reg_req_ = static_cast<uint32_t>(id);
392 break; 495 break;
393 } 496
394 if (!pktIn->GetNumberSep(&id, 0)) { 497 case 'c':
395 err = BAD_FORMAT; 498 run_req_ = static_cast<uint32_t>(id);
396 break; 499 break;
397 }
398 500
399 if (threads_.begin() == threads_.end()) { 501 default:
400 err = BAD_ARGS;
401 break;
402 }
403
404 // If we are using "any" get the first thread
405 if (id == static_cast<uint64_t>(-1)) id = threads_.begin()->first;
406
407 // Verify that we have the thread
408 if (threads_.find(static_cast<uint32_t>(id)) == threads_.end()) {
409 err = BAD_ARGS; 502 err = BAD_ARGS;
410 break; 503 break;
411 } 504 }
505 break;
506 }
412 507
413 pktOut->AddString("OK"); 508 case 'k':
414 switch (type) { 509 port::IPlatform::LogError("Process killed by debugger.");
415 case 'g': 510 break;
416 reg_thread_ = static_cast<uint32_t>(id);
417 break;
418
419 case 'c':
420 run_thread_ = static_cast<uint32_t>(id);
421 break;
422
423 default:
424 err = BAD_ARGS;
425 break;
426 }
427 break;
428 }
429 511
430 // IN : $maaaa,llll 512 // IN : $maaaa,llll
431 // OUT: $xx..xx 513 // OUT: $xx..xx
432 case 'm': { 514 case 'm': {
433 uint64_t addr; 515 // This packet is requesting a read operation for more than one byte.
434 uint64_t wlen; 516 uint64_t addr;
435 uint32_t len; 517 uint64_t wlen;
436 if (!pktIn->GetNumberSep(&addr, 0)) { 518 uint32_t len;
437 err = BAD_FORMAT; 519 if (!pktIn->GetNumberSep(&addr, 0)) {
438 break; 520 err = BAD_FORMAT;
439 }
440
441 if (!pktIn->GetNumberSep(&wlen, 0)) {
442 err = BAD_FORMAT;
443 break;
444 }
445
446 len = static_cast<uint32_t>(wlen);
447 uint8_t *block = new uint8_t[len];
448 if (!port::IPlatform::GetMemory(addr, len, block)) err = FAILED;
449
450 pktOut->AddBlock(block, len);
451 break; 521 break;
452 } 522 }
453 523
524 if (!pktIn->GetNumberSep(&wlen, 0)) {
525 err = BAD_FORMAT;
526 break;
527 }
528
529 len = static_cast<uint32_t>(wlen);
530 uint8_t *block = new uint8_t[len];
531 if (!port::IPlatform::GetMemory(addr, len, block)) err = FAILED;
532
533 pktOut->AddBlock(block, len);
534 break;
535 }
536
454 // IN : $Maaaa,llll:xx..xx 537 // IN : $Maaaa,llll:xx..xx
455 // OUT: $OK 538 // OUT: $OK
456 case 'M': { 539 case 'M': {
457 uint64_t addr; 540 // This packet is requesting that multiple bytes be overwritten,
458 uint64_t wlen; 541 // starting at a specific address.
459 uint32_t len; 542 uint64_t addr;
543 uint64_t wlen;
544 uint32_t len;
460 545
461 if (!pktIn->GetNumberSep(&addr, 0)) { 546 if (!pktIn->GetNumberSep(&addr, 0)) {
462 err = BAD_FORMAT; 547 err = BAD_FORMAT;
463 break; 548 break;
464 } 549 }
465 if (!pktIn->GetNumberSep(&wlen, 0)) { 550 if (!pktIn->GetNumberSep(&wlen, 0)) {
466 err = BAD_FORMAT; 551 err = BAD_FORMAT;
467 break;
468 }
469
470 len = static_cast<uint32_t>(wlen);
471 uint8_t *block = new uint8_t[len];
472 pktIn->GetBlock(block, len);
473
474 if (!port::IPlatform::SetMemory(addr, len, block)) err = FAILED;
475
476 pktOut->AddString("OK");
477 break; 552 break;
478 } 553 }
479 554
555 len = static_cast<uint32_t>(wlen);
556 uint8_t *block = new uint8_t[len];
557 pktIn->GetBlock(block, len);
558
559 if (!port::IPlatform::SetMemory(addr, len, block)) err = FAILED;
560
561 pktOut->AddString("OK");
562 break;
563 }
564
480 case 'q': { 565 case 'q': {
566 // This packet is carrying out a general query, possibly for supported
567 // commands and the like.
481 string tmp; 568 string tmp;
482 const char *str = &pktIn->GetPayload()[1]; 569 const char *str = &pktIn->GetPayload()[1];
483 stringvec toks = StringSplit(str, ":;"); 570 stringvec toks = StringSplit(str, ";");
484 PropertyMap_t::const_iterator itr = properties_.find(toks[0]); 571 std::string strout;
572
573 // Check if we can find this query in the local cache
574 if (MatchQuery(toks[0], &strout)) {
575 pktOut->AddString(strout.data());
576 break;
577 }
485 578
486 // If this is a thread query 579 // If this is a thread query
487 if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) { 580 if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) {
488 uint32_t curr; 581 uint32_t curr;
489 bool more = false; 582 bool more = false;
490 if (str[0] == 'f') { 583 if (str[0] == 'f') {
491 more = GetFirstThreadId(&curr); 584 more = GetFirstThreadId(&curr);
492 } else { 585 } else {
493 more = GetNextThreadId(&curr); 586 more = GetNextThreadId(&curr);
494 } 587 }
495 588
496 if (!more) { 589 if (!more) {
497 pktOut->AddString("l"); 590 pktOut->AddString("l");
498 } else { 591 } else {
499 pktOut->AddString("m"); 592 pktOut->AddString("m");
500 pktOut->AddNumberSep(curr, 0); 593 pktOut->AddNumberSep(curr, 0);
501 } 594 }
502 break; 595 break;
503 } 596 }
504 597
505 // Check for architecture query 598 // Didn't find anything
506 tmp = "Xfer:features:read:target.xml";
507 if (!strncmp(str, tmp.data(), tmp.length())) {
508 stringvec args = StringSplit(&str[tmp.length()+1], ",");
509 if (args.size() != 2) break;
510
511 const char *out = properties_["target.xml"].data();
512 int offs = strtol(args[0].data(), NULL, 16);
513 int max = strtol(args[1].data(), NULL, 16) + offs;
514 int len = static_cast<int>(strlen(out));
515
516 if (max >= len) max = len;
517
518 while (offs < max) {
519 pktOut->AddRawChar(out[offs]);
520 offs++;
521 }
522 break;
523 }
524
525 // Check the property cache
526 if (itr != properties_.end()) {
527 pktOut->AddString(itr->second.data());
528 }
529 break; 599 break;
530 } 600 }
531 601
532 case 'T': { 602 case 'T': {
603 // This packet constitutes a check, whether a given thread is alive or
604 // dead.
533 uint64_t id; 605 uint64_t id;
534 if (!pktIn->GetNumberSep(&id, 0)) { 606 if (!pktIn->GetNumberSep(&id, 0)) {
535 err = BAD_FORMAT; 607 err = BAD_FORMAT;
536 break; 608 break;
537 } 609 }
538 610
539 if (GetThread(static_cast<uint32_t>(id)) == NULL) { 611 if (GetThread(static_cast<uint32_t>(id)) == NULL) {
540 err = BAD_ARGS; 612 err = BAD_ARGS;
541 break; 613 break;
542 } 614 }
543 615
544 pktOut->AddString("OK"); 616 pktOut->AddString("OK");
545 break; 617 break;
546 } 618 }
547 619
548 case 's': { 620 case 's': {
621 // This packet is asking for a thread to step a single instruction
549 IThread *thread = GetThread(GetRunThreadId()); 622 IThread *thread = GetThread(GetRunThreadId());
550 if (thread) thread->SetStep(true); 623 if (thread) thread->SetStep(true);
551 return true; 624 return true;
552 } 625 }
553 626
554 case 'c': 627 default:
555 return true; 628 // If the command is not recognized, ignore it by sending an empty reply.
556 629 // Don't use LogError here or the debug stub will crash instead of
557 default: { 630 // negotiating a protocol with the debugger.
558 // If the command is not recognzied, ignore it by sending an 631 port::IPlatform::LogInfo("Unknown command: %s", pktIn->GetPayload());
559 // empty reply. 632 break;
560 string str;
561 pktIn->GetString(&str);
562 port::IPlatform::LogError("Unknown command: %s", str.data());
563 return false;
564 }
565 } 633 }
566 634
567 // If there is an error, return the error code instead of a payload 635 // If there is an error, return the error code instead of a payload
568 if (err) { 636 if (err) {
569 pktOut->Clear(); 637 pktOut->Clear();
570 pktOut->AddRawChar('E'); 638 pktOut->AddRawChar('E');
571 pktOut->AddWord8(err); 639 pktOut->AddWord8(err);
572 } 640 }
573 return false; 641 return false;
574 } 642 }
575 643
576 644
577 void Target::TrackThread(IThread* thread) { 645 void Target::TrackThread(IThread* thread) {
646 MutexLock lock(stateMutex_);
647
578 uint32_t id = thread->GetId(); 648 uint32_t id = thread->GetId();
579 mutex_->Lock();
580 threads_[id] = thread; 649 threads_[id] = thread;
581 mutex_->Unlock();
582 } 650 }
583 651
584 void Target::IgnoreThread(IThread* thread) { 652 void Target::IgnoreThread(IThread* thread) {
653 MutexLock lock(stateMutex_);
654
585 uint32_t id = thread->GetId(); 655 uint32_t id = thread->GetId();
586 mutex_->Lock();
587 ThreadMap_t::iterator itr = threads_.find(id); 656 ThreadMap_t::iterator itr = threads_.find(id);
588
589 if (itr != threads_.end()) threads_.erase(itr); 657 if (itr != threads_.end()) threads_.erase(itr);
590 mutex_->Lock();
591 } 658 }
592 659
593 660
594 void Target::Detach() { 661 void Target::Detach() {
595 port::IPlatform::LogInfo("Requested Detach.\n"); 662 port::IPlatform::LogInfo("Requested Detach.\n");
596 } 663 }
597 664
598 665
599 uint32_t Target::GetRegThreadId() const { 666 uint32_t Target::GetRegThreadId() const {
600 ThreadMap_t::const_iterator itr; 667 IThread* thread;
668 uint32_t id = 0;
601 669
602 switch (reg_thread_) { 670 switch (reg_req_) {
603 // If we wany "any" then try the signal'd thread first
604 case 0: 671 case 0:
605 case 0xFFFFFFFF: 672 case 0xFFFFFFFF:
606 itr = threads_.begin(); 673 // If we wany "any" then try the last result first
674 thread = GetThread(reg_last_);
675
676 // If not there, try the sig_thread next
677 if (NULL == thread) thread = GetThread(sig_thread_);
678
679 // If stil not there, get the first thread
680 if (NULL == thread) thread = threads_.begin()->second;
607 break; 681 break;
608 682
609 default: 683 default:
610 itr = threads_.find(reg_thread_); 684 // Otherwise, get the specificly requested one
685 thread = GetThread(reg_req_);
611 break; 686 break;
612 } 687 }
613 688
614 if (itr == threads_.end()) return 0; 689 // Update last result.
690 if (NULL == thread) {
691 reg_last_ = 0;
692 } else {
693 reg_last_ = thread->GetId();
694 }
615 695
616 return itr->first; 696 // Return the result
697 return reg_last_;
617 } 698 }
618 699
619 uint32_t Target::GetRunThreadId() const { 700 uint32_t Target::GetRunThreadId() const {
620 return run_thread_; 701 IThread* thread;
702 uint32_t id = 0;
703
704 switch (run_req_) {
705 case 0:
706 case 0xFFFFFFFF:
707 // If we wany "any" then try the last result first
708 thread = GetThread(run_last_);
709
710 // If not there, try the sig_thread next
711 if (NULL == thread) thread = GetThread(sig_thread_);
712
713 // If stil not there, get the first thread
714 if (NULL == thread) thread = threads_.begin()->second;
715 break;
716
717 default:
718 // Otherwise, get the specificly requested one
719 thread = GetThread(run_req_);
720 break;
721 }
722
723 // Update last result.
724 if (NULL == thread) {
725 run_last_ = 0;
726 } else {
727 run_last_ = thread->GetId();
728 }
729
730 // Return the result
731 return run_last_;
621 } 732 }
622 733
623 IThread* Target::GetThread(uint32_t id) { 734 IThread* Target::GetThread(uint32_t id) const {
624 ThreadMap_t::const_iterator itr; 735 ThreadMap_t::const_iterator itr;
625 itr = threads_.find(id); 736 itr = threads_.find(id);
626 if (itr != threads_.end()) return itr->second; 737 if (itr != threads_.end()) return itr->second;
627 738
628 return NULL; 739 return NULL;
629 } 740 }
630 741
631 742
632 } // namespace gdb_rsp 743 } // namespace gdb_rsp
633 744
634 745
635 746
636 747
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698