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

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

Powered by Google App Engine
This is Rietveld 408576698