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

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

Powered by Google App Engine
This is Rietveld 408576698