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

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
« src/trusted/gdb_rsp/target.h ('K') | « 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 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),
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),
Cliff L. Biffle 2010/12/14 21:46:08 You appear to be using two magic numbers, 0 and -1
mlinck 2010/12/16 20:03:01 I have addressed this by creating a new constant,
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--) {
Cliff L. Biffle 2010/12/14 21:46:08 Excess space before semicolon.
mlinck 2010/12/16 20:03:01 Done.
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)) {
Cliff L. Biffle 2010/12/14 21:46:08 Doing this inside the loop is confusing. It seems
mlinck 2010/12/16 20:03:01 I've clarified this code a little bit but the only
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 an event that indicates that the Run Thread is ready to process
207 // the next signal.
140 sig_start_->Wait(); 208 sig_start_->Wait();
141 { 209 {
142 // Now lock the target, sleeping all active threads 210 // Lock the signal state information to prevent a race.
143 MutexLock lock(mutex_); 211 MutexLock lock(stateMutex_);
144 212
145 // Suspend all threads except this one 213 // Signal the stub that we are ready to process a trap
146 uint32_t curId; 214 // by locking the signal information, and updating it.
147 bool more = GetFirstThreadId(&curId); 215 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; 216 cur_signal_ = sig;
162 } 217 }
163 218
164 // Wait for permission to continue 219 // Wait for the signal to be fully processed before exiting.
165 if (wait) sig_done_->Wait(); 220 if (wait) sig_done_->Wait();
166 } 221 }
167 222
223 void Target::Update() {
224 // Next update the current thread info
225 char tmp[16];
Cliff L. Biffle 2010/12/14 21:46:08 Looks like this will be, at largest, 11 bytes.
mlinck 2010/12/16 20:03:01 Done.
226 snprintf(tmp, sizeof(tmp), "QC%x", sig_thread_);
Cliff L. Biffle 2010/12/14 21:46:08 Consider using NACL_ARRAY_SIZE macro here -- it wi
Cliff L. Biffle 2010/12/14 21:46:08 Incidentally, isn't there a nice C++ way of doing
mlinck 2010/12/16 20:03:01 Since we have a known max-length and don't want to
mlinck 2010/12/16 20:03:01 Implicit conversion between string and char * is b
227 SetProperty("C", tmp);
228 }
229
230 void Target::Pause() {
231 // Put all active threads to sleep.
232 uint32_t curId;
233 bool more = GetFirstThreadId(&curId);
234 while (more) {
235 IThread *thread = GetThread(curId);
236 if (thread->GetState() == IThread::RUNNING) thread->Suspend();
237 more = GetNextThreadId(&curId);
238 }
239 }
240
241 void Target::Resume() {
242 // Now that we are done, we want to continue in the "correct order".
243 // This means letting the active thread go first, in case we are single
244 // stepping and want to catch it again. This is a desired behavior but
245 // it is not guaranteed since another thread may already be in an
246 // exception state and next in line to notify the target.
247
248 // Wake up the run thread if it needs it, so it can go first
249 IThread* thread = GetThread(GetRunThreadId());
250 if (thread->GetState() == IThread::SUSPENDED) thread->Resume();
251
252 // If we took an exception, let the handler resume and allow
253 // the next exception to trigger (although it will still
254 // block until we release the mutex).
255 if (cur_signal_) {
Cliff L. Biffle 2010/12/14 21:46:08 I see cur_signal_ being set to 0, -1, and actual v
mlinck 2010/12/16 20:03:01 This has never worked. I have an issue to investi
256 sig_done_->Signal();
257 sig_start_->Signal();
258 }
259
260 // Now wake up everyone else that needs it
261 uint32_t curId;
262 bool more = GetFirstThreadId(&curId);
263 while (more) {
264 IThread* thread = GetThread(curId);
265
266 // Definitely don't mess with breakpoint state here and let debugger decide
267 // when it's time to turn off breakpoints.
268 if (thread->GetState() == IThread::SUSPENDED) thread->Resume();
269 more = GetNextThreadId(&curId);
270 }
271 }
272
168 void Target::Run(Session *ses) { 273 void Target::Run(Session *ses) {
169 bool first = true; 274 bool first = true;
275
170 do { 276 do {
171 // Give everyone else a chance to use the lock 277 // Prevent tight loop so this thread doesn't churn up CPU.
172 IPlatform::Relinquish(100); 278 IPlatform::Relinquish(100);
173 279
174 // Lock to prevent anyone else from modifying threads 280 // Lock to prevent anyone else from modifying threads
175 // or updating the signal information. 281 // or updating the signal information.
176 MutexLock lock(mutex_); 282 MutexLock lock(stateMutex_);
177 Packet recv, reply; 283 Packet recv, reply;
178 284
179 uint32_t id = 0;
180
181 // If no signal is waiting for this iteration... 285 // If no signal is waiting for this iteration...
182 if (-1 == cur_signal_) { 286 if (-1 == cur_signal_) {
183 // but the debugger is talking to us then force a break 287 // but the debugger is talking to us
184 if (ses->DataAvailable()) { 288 if (ses->DataAvailable()) {
185 // set signal to 0 to signify paused 289 // Then simulate a signal, by setting the state data
290 // Set signal to 0 to signify paused
186 cur_signal_ = 0; 291 cur_signal_ = 0;
187 292
188 // put all the threads to sleep. 293 // Set the "signaling" thread to the preferred thread
189 uint32_t curId; 294 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 { 295 } else {
199 // otherwise, nothing to do so try again. 296 // otherwise, we are not signaled, and we are not chatting
297 // release the lock, and try again.
200 continue; 298 continue;
201 } 299 }
202 } else {
203 // otherwise there really is an exception so get the id of the thread
204 id = GetRegThreadId();
205 } 300 }
206 301
207 // If we got this far, then there is some kind of signal. 302 // We have a signal, so pause everyone
208 // So first, remove the breakpoints 303 Pause();
209 RemoveTemporaryBreakpoints();
210 304
211 // Next update the current thread info 305 // Update our local state information
212 char tmp[16]; 306 Update();
213 snprintf(tmp, sizeof(tmp), "QC%x", id);
214 properties_["C"] = tmp;
215 307
216 if (first) { 308 if (first) {
217 // First time on a connection, we don't sent the signal 309 // First time on a connection, we don't send the signal
218 first = false; 310 first = false;
219 } else { 311 } else {
220 // All other times, send the signal that triggered us 312 // All other times, send the signal that triggered us
221 Packet pktOut; 313 Packet pktOut;
222 pktOut.AddRawChar('S'); 314 pktOut.AddRawChar('S');
223 pktOut.AddWord8(cur_signal_); 315 pktOut.AddWord8(cur_signal_);
224 ses->SendPacketOnly(&pktOut); 316 ses->SendPacketOnly(&pktOut);
225 } 317 }
226 318
227 // Now we are ready to process commands 319 // Now we are ready to process commands
228 // Loop through packets until we process a continue 320 // Loop through packets until we process a continue
229 // packet. 321 // packet.
230 do { 322 do {
231 if (ses->GetPacket(&recv)) { 323 if (ses->GetPacket(&recv)) {
232 reply.Clear(); 324 reply.Clear();
233 if (ProcessPacket(&recv, &reply)) { 325 if (ProcessPacket(&recv, &reply)) {
234 // If this is a continue command, break out of this loop 326 // If this is a continue command, break out of this loop
235 break; 327 break;
236 } else { 328 } else {
237 // Othwerise send the reponse 329 // Otherwise send the reponse
238 ses->SendPacket(&reply); 330 ses->SendPacket(&reply);
239 } 331 }
240 } 332 }
241 } while (ses->Connected()); 333 } while (ses->Connected());
242 334
335 // Start everyone again.
336 Resume();
243 337
244 // Now that we are done, we want to continue in the "correct order". 338 // Reset our state before we return, clearing the signal. However
245 // This means letting the active thread go first, in case we are single 339 // 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 340 cur_signal_ = -1;
247 // it is not guaranteed since another thread may already be in an 341 sig_thread_ = 0;
248 // exception state and next in line to notify the target.
249 342
250 // If the run thread is not the exception thread, wake it up now. 343 // At this point, we destroy the MutexLock, allowing anyone else to
251 uint32_t run_thread = GetRunThreadId(); 344 // 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. 345 // Continue running until the connection is lost.
284 } while (ses->Connected()); 346 } while (ses->Connected());
285 } 347 }
286 348
287 349
288
289
290 bool Target::GetFirstThreadId(uint32_t *id) { 350 bool Target::GetFirstThreadId(uint32_t *id) {
291 threadItr_ = threads_.begin(); 351 threadItr_ = threads_.begin();
292 return GetNextThreadId(id); 352 return GetNextThreadId(id);
293 } 353 }
294 354
295 bool Target::GetNextThreadId(uint32_t *id) { 355 bool Target::GetNextThreadId(uint32_t *id) {
296 if (threadItr_ == threads_.end()) return false; 356 if (threadItr_ == threads_.end()) return false;
297 357
298 *id = (*threadItr_).first; 358 *id = (*threadItr_).first;
299 threadItr_++; 359 threadItr_++;
300 360
301 return true; 361 return true;
302 } 362 }
303 363
304 364
305
306 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) { 365 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) {
307 char cmd; 366 char cmd;
308 int32_t seq = -1; 367 int32_t seq = -1;
309 ErrDef err = NONE; 368 ErrDef err = NONE;
310 369
311 // Clear the outbound message 370 // Clear the outbound message
312 pktOut->Clear(); 371 pktOut->Clear();
313 372
314 // Pull out the sequence. 373 // Pull out the sequence.
315 pktIn->GetSequence(&seq); 374 pktIn->GetSequence(&seq);
316 if (seq != -1) pktOut->SetSequence(seq); 375 if (seq != -1) pktOut->SetSequence(seq);
317 376
318 // Find the command 377 // Find the command
319 pktIn->GetRawChar(&cmd); 378 pktIn->GetRawChar(&cmd);
320 379
321 switch (cmd) { 380 switch (cmd) {
381 // In the case of a force break, drop through
382 // and print the signal. We have already suspended
383 // the threads at this point.
384 case 0x03:
385
322 // IN : $? 386 // IN : $?
323 // OUT: $Sxx 387 // OUT: $Sxx
324 case '?': 388 case '?':
389 // This case asks why the target has halted.
325 pktOut->AddRawChar('S'); 390 pktOut->AddRawChar('S');
326 pktOut->AddWord8(cur_signal_); 391 pktOut->AddWord8(cur_signal_);
327 break; 392 break;
328 393
329 // IN : $d 394 // IN : $d
330 // OUT: -NONE- 395 // OUT: -NONE-
331 case 'd': 396 case 'd':
397 // This packet could be asking the debugger to detach but
398 // we should never receive it.
332 Detach(); 399 Detach();
333 break; 400 return true;
334 401
335 // IN : $g 402 // IN : $g
336 // OUT: $xx...xx 403 // OUT: $xx...xx
337 case 'g': { 404 case 'g': {
405 // This packet is requesting the value of a general register.
338 uint32_t id = GetRegThreadId(); 406 uint32_t id = GetRegThreadId();
339 if (0 == id) { 407 if (0 == id) {
340 err = BAD_ARGS; 408 err = BAD_ARGS;
341 break; 409 break;
342 } 410 }
343 411
344 IThread *thread = GetThread(id); 412 IThread *thread = GetThread(id);
345 if (NULL == thread) { 413 if (NULL == thread) {
346 err = BAD_ARGS; 414 err = BAD_ARGS;
347 break; 415 break;
348 } 416 }
349 417
350 // Copy OS preserved registers to GDB payload 418 // Copy OS preserved registers to GDB payload
351 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) { 419 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
352 const Abi::RegDef *def = abi_->GetRegisterDef(a); 420 const Abi::RegDef *def = abi_->GetRegisterDef(a);
353 thread->GetRegister(a, &ctx_[def->offset_], def->bytes_); 421 thread->GetRegister(a, &ctx_[def->offset_], def->bytes_);
354 } 422 }
355 423
356 pktOut->AddBlock(ctx_, abi_->GetContextSize()); 424 pktOut->AddBlock(ctx_, abi_->GetContextSize());
357 break; 425 break;
358 } 426 }
359 427
360 // IN : $Gxx..xx 428 // IN : $Gxx..xx
361 // OUT: $OK 429 // OUT: $OK
362 case 'G': { 430 case 'G': {
431 // This packet is requesting that the value of a general register be
432 // changed to something else.
363 uint32_t id = GetRegThreadId(); 433 uint32_t id = GetRegThreadId();
364 if (0 == id) { 434 if (0 == id) {
365 err = BAD_ARGS; 435 err = BAD_ARGS;
366 break; 436 break;
367 } 437 }
368 438
369 IThread *thread = threads_[id]; 439 IThread *thread = threads_[id];
370 if (NULL == thread) { 440 if (NULL == thread) {
371 err = BAD_ARGS; 441 err = BAD_ARGS;
372 break; 442 break;
373 } 443 }
374 444
375 // GDB payload to OS registers 445 // GDB payload to OS registers
376 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) { 446 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
377 const Abi::RegDef *def = abi_->GetRegisterDef(a); 447 const Abi::RegDef *def = abi_->GetRegisterDef(a);
378 thread->SetRegister(a, &ctx_[def->offset_], def->bytes_); 448 thread->SetRegister(a, &ctx_[def->offset_], def->bytes_);
379 } 449 }
380 pktOut->AddBlock(ctx_, abi_->GetContextSize()); 450 pktOut->AddBlock(ctx_, abi_->GetContextSize());
381 break; 451 break;
382 } 452 }
383 453
384 // IN : $H(c/g)(-1,0,xxxx) 454 // IN : $H(c/g)(-1,0,xxxx)
385 // OUT: $OK 455 // OUT: $OK
386 case 'H': { 456 case 'H': {
387 char type; 457 // This packet is requesting that the thread be set for subsequent
388 uint64_t id; 458 // operations.
459 char type;
460 uint64_t id;
389 461
390 if (!pktIn->GetRawChar(&type)) { 462 if (!pktIn->GetRawChar(&type)) {
391 err = BAD_FORMAT; 463 err = BAD_FORMAT;
464 break;
465 }
466 if (!pktIn->GetNumberSep(&id, 0)) {
467 err = BAD_FORMAT;
468 break;
469 }
470
471 if (threads_.begin() == threads_.end()) {
472 err = BAD_ARGS;
473 break;
474 }
475
476 // If we are using "any" get the first thread
477 if (id == static_cast<uint64_t>(-1)) id = threads_.begin()->first;
478
479 // Verify that we have the thread
480 if (threads_.find(static_cast<uint32_t>(id)) == threads_.end()) {
481 err = BAD_ARGS;
482 break;
483 }
484
485 pktOut->AddString("OK");
486 switch (type) {
487 case 'g':
488 reg_req_ = static_cast<uint32_t>(id);
392 break; 489 break;
393 } 490
394 if (!pktIn->GetNumberSep(&id, 0)) { 491 case 'c':
395 err = BAD_FORMAT; 492 run_req_ = static_cast<uint32_t>(id);
396 break; 493 break;
397 }
398 494
399 if (threads_.begin() == threads_.end()) { 495 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; 496 err = BAD_ARGS;
410 break; 497 break;
411 } 498 }
499 break;
500 }
412 501
413 pktOut->AddString("OK"); 502 case 'k':
414 switch (type) { 503 port::IPlatform::LogError("Process killed by debugger.");
415 case 'g': 504 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 505
430 // IN : $maaaa,llll 506 // IN : $maaaa,llll
431 // OUT: $xx..xx 507 // OUT: $xx..xx
432 case 'm': { 508 case 'm': {
433 uint64_t addr; 509 // This packet is requesting a memory read of size llll, starting
434 uint64_t wlen; 510 // at address aaaa.
435 uint32_t len; 511 uint64_t addr;
436 if (!pktIn->GetNumberSep(&addr, 0)) { 512 uint64_t wlen;
437 err = BAD_FORMAT; 513 uint32_t len;
438 break; 514 if (!pktIn->GetNumberSep(&addr, 0)) {
439 } 515 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; 516 break;
452 } 517 }
453 518
519 if (!pktIn->GetNumberSep(&wlen, 0)) {
520 err = BAD_FORMAT;
521 break;
522 }
523
524 len = static_cast<uint32_t>(wlen);
525 uint8_t *block = new uint8_t[len];
526 if (!port::IPlatform::GetMemory(addr, len, block)) err = FAILED;
527
528 pktOut->AddBlock(block, len);
529 break;
530 }
531
454 // IN : $Maaaa,llll:xx..xx 532 // IN : $Maaaa,llll:xx..xx
455 // OUT: $OK 533 // OUT: $OK
456 case 'M': { 534 case 'M': {
457 uint64_t addr; 535 // This packet is requesting one or more bytes be overwritten,
458 uint64_t wlen; 536 // starting at a specific address.
459 uint32_t len; 537 uint64_t addr;
538 uint64_t wlen;
539 uint32_t len;
460 540
461 if (!pktIn->GetNumberSep(&addr, 0)) { 541 if (!pktIn->GetNumberSep(&addr, 0)) {
462 err = BAD_FORMAT; 542 err = BAD_FORMAT;
463 break; 543 break;
464 } 544 }
465 if (!pktIn->GetNumberSep(&wlen, 0)) { 545 if (!pktIn->GetNumberSep(&wlen, 0)) {
466 err = BAD_FORMAT; 546 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; 547 break;
478 } 548 }
479 549
550 len = static_cast<uint32_t>(wlen);
551 uint8_t *block = new uint8_t[len];
552 pktIn->GetBlock(block, len);
553
554 if (!port::IPlatform::SetMemory(addr, len, block)) err = FAILED;
555
556 pktOut->AddString("OK");
557 delete[] block;
558 break;
559 }
560
480 case 'q': { 561 case 'q': {
562 // This packet is carrying out a general query, possibly for supported
563 // commands and the like.
481 string tmp; 564 string tmp;
482 const char *str = &pktIn->GetPayload()[1]; 565 const char *str = &pktIn->GetPayload()[1];
483 stringvec toks = StringSplit(str, ":;"); 566 stringvec toks = StringSplit(str, ";");
484 PropertyMap_t::const_iterator itr = properties_.find(toks[0]); 567 std::string strout;
568
569 // Check if we can find this query in the local cache
570 if (MatchQuery(toks[0], &strout)) {
571 pktOut->AddString(strout.data());
572 break;
573 }
485 574
486 // If this is a thread query 575 // If this is a thread query
487 if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) { 576 if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) {
488 uint32_t curr; 577 uint32_t curr;
489 bool more = false; 578 bool more = false;
490 if (str[0] == 'f') { 579 if (str[0] == 'f') {
491 more = GetFirstThreadId(&curr); 580 more = GetFirstThreadId(&curr);
492 } else { 581 } else {
493 more = GetNextThreadId(&curr); 582 more = GetNextThreadId(&curr);
494 } 583 }
495 584
496 if (!more) { 585 if (!more) {
497 pktOut->AddString("l"); 586 pktOut->AddString("l");
498 } else { 587 } else {
499 pktOut->AddString("m"); 588 pktOut->AddString("m");
500 pktOut->AddNumberSep(curr, 0); 589 pktOut->AddNumberSep(curr, 0);
501 } 590 }
502 break; 591 break;
503 } 592 }
504 593
505 // Check for architecture query 594 // 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; 595 break;
530 } 596 }
531 597
532 case 'T': { 598 case 'T': {
599 // This packet constitutes a check, whether a given thread is alive or
600 // dead.
533 uint64_t id; 601 uint64_t id;
534 if (!pktIn->GetNumberSep(&id, 0)) { 602 if (!pktIn->GetNumberSep(&id, 0)) {
535 err = BAD_FORMAT; 603 err = BAD_FORMAT;
536 break; 604 break;
537 } 605 }
538 606
539 if (GetThread(static_cast<uint32_t>(id)) == NULL) { 607 if (GetThread(static_cast<uint32_t>(id)) == NULL) {
540 err = BAD_ARGS; 608 err = BAD_ARGS;
541 break; 609 break;
542 } 610 }
543 611
544 pktOut->AddString("OK"); 612 pktOut->AddString("OK");
545 break; 613 break;
546 } 614 }
547 615
548 case 's': { 616 case 's': {
617 // This packet is asking for a thread to step a single instruction
549 IThread *thread = GetThread(GetRunThreadId()); 618 IThread *thread = GetThread(GetRunThreadId());
550 if (thread) thread->SetStep(true); 619 if (thread) thread->SetStep(true);
551 return true; 620 return true;
552 } 621 }
553 622
554 case 'c': 623 default:
555 return true; 624 // If the command is not recognized, ignore it by sending an empty reply.
556 625 // Don't use LogError here or the debug stub will crash instead of
557 default: { 626 // negotiating a protocol with the debugger.
558 // If the command is not recognzied, ignore it by sending an 627 port::IPlatform::LogInfo("Unknown command: %s", pktIn->GetPayload());
559 // empty reply. 628 break;
560 string str;
561 pktIn->GetString(&str);
562 port::IPlatform::LogError("Unknown command: %s", str.data());
563 return false;
564 }
565 } 629 }
566 630
567 // If there is an error, return the error code instead of a payload 631 // If there is an error, return the error code instead of a payload
568 if (err) { 632 if (err) {
569 pktOut->Clear(); 633 pktOut->Clear();
570 pktOut->AddRawChar('E'); 634 pktOut->AddRawChar('E');
571 pktOut->AddWord8(err); 635 pktOut->AddWord8(err);
572 } 636 }
573 return false; 637 return false;
574 } 638 }
575 639
576 640
577 void Target::TrackThread(IThread* thread) { 641 void Target::TrackThread(IThread* thread) {
642 MutexLock lock(stateMutex_);
643
578 uint32_t id = thread->GetId(); 644 uint32_t id = thread->GetId();
579 mutex_->Lock();
580 threads_[id] = thread; 645 threads_[id] = thread;
581 mutex_->Unlock();
582 } 646 }
583 647
584 void Target::IgnoreThread(IThread* thread) { 648 void Target::IgnoreThread(IThread* thread) {
649 MutexLock lock(stateMutex_);
650
585 uint32_t id = thread->GetId(); 651 uint32_t id = thread->GetId();
586 mutex_->Lock();
587 ThreadMap_t::iterator itr = threads_.find(id); 652 ThreadMap_t::iterator itr = threads_.find(id);
588
589 if (itr != threads_.end()) threads_.erase(itr); 653 if (itr != threads_.end()) threads_.erase(itr);
590 mutex_->Lock();
591 } 654 }
592 655
593 656
594 void Target::Detach() { 657 void Target::Detach() {
595 port::IPlatform::LogInfo("Requested Detach.\n"); 658 port::IPlatform::LogInfo("Requested Detach.\n");
596 } 659 }
597 660
598 661
599 uint32_t Target::GetRegThreadId() const { 662 uint32_t Target::GetRegThreadId() const {
600 ThreadMap_t::const_iterator itr; 663 IThread* thread;
664 uint32_t id = 0;
601 665
602 switch (reg_thread_) { 666 switch (reg_req_) {
603 // If we wany "any" then try the signal'd thread first
604 case 0: 667 case 0:
605 case 0xFFFFFFFF: 668 case 0xFFFFFFFF:
606 itr = threads_.begin(); 669 // If we wany "any" then try the last result first
670 thread = GetThread(reg_last_);
671
672 // If not there, try the sig_thread next
673 if (NULL == thread) thread = GetThread(sig_thread_);
674
675 // If stil not there, get the first thread
676 if (NULL == thread) thread = threads_.begin()->second;
607 break; 677 break;
608 678
609 default: 679 default:
610 itr = threads_.find(reg_thread_); 680 // Otherwise, get the specificly requested one
681 thread = GetThread(reg_req_);
611 break; 682 break;
612 } 683 }
613 684
614 if (itr == threads_.end()) return 0; 685 // Update last result.
686 if (NULL == thread) {
687 reg_last_ = 0;
688 } else {
689 reg_last_ = thread->GetId();
690 }
615 691
616 return itr->first; 692 // Return the result
693 return reg_last_;
617 } 694 }
618 695
619 uint32_t Target::GetRunThreadId() const { 696 uint32_t Target::GetRunThreadId() const {
620 return run_thread_; 697 IThread* thread;
698 uint32_t id = 0;
699
700 switch (run_req_) {
701 case 0:
702 case 0xFFFFFFFF:
703 // If we wany "any" then try the last result first
704 thread = GetThread(run_last_);
705
706 // If not there, try the sig_thread next
707 if (NULL == thread) thread = GetThread(sig_thread_);
708
709 // If stil not there, get the first thread
710 if (NULL == thread) thread = threads_.begin()->second;
711 break;
712
713 default:
714 // Otherwise, get the specificly requested one
715 thread = GetThread(run_req_);
716 break;
717 }
718
719 // Update last result.
720 if (NULL == thread) {
721 run_last_ = 0;
722 } else {
723 run_last_ = thread->GetId();
724 }
725
726 // Return the result
727 return run_last_;
621 } 728 }
622 729
623 IThread* Target::GetThread(uint32_t id) { 730 IThread* Target::GetThread(uint32_t id) const {
624 ThreadMap_t::const_iterator itr; 731 ThreadMap_t::const_iterator itr;
625 itr = threads_.find(id); 732 itr = threads_.find(id);
626 if (itr != threads_.end()) return itr->second; 733 if (itr != threads_.end()) return itr->second;
627 734
628 return NULL; 735 return NULL;
629 } 736 }
630 737
631 738
632 } // namespace gdb_rsp 739 } // namespace gdb_rsp
633 740
634 741
635 742
636 743
OLDNEW
« src/trusted/gdb_rsp/target.h ('K') | « src/trusted/gdb_rsp/target.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698