blob: 8e0d4c38a7220ce32322eb914aa73496d12aaf4d [file] [log] [blame]
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * Send events to the debugger.
18 */
19#include "debugger.h"
20#include "jdwp/jdwp_priv.h"
21#include "jdwp/jdwp_constants.h"
22#include "jdwp/jdwp_handler.h"
23#include "jdwp/jdwp_event.h"
24#include "jdwp/jdwp_expand_buf.h"
25#include "logging.h"
26#include "stringprintf.h"
27
28#include <stdlib.h>
29#include <string.h>
30#include <stddef.h> /* for offsetof() */
31#include <unistd.h>
32
33/*
34General notes:
35
36The event add/remove stuff usually happens from the debugger thread,
37in response to requests from the debugger, but can also happen as the
38result of an event in an arbitrary thread (e.g. an event with a "count"
39mod expires). It's important to keep the event list locked when processing
40events.
41
42Event posting can happen from any thread. The JDWP thread will not usually
43post anything but VM start/death, but if a JDWP request causes a class
44to be loaded, the ClassPrepare event will come from the JDWP thread.
45
46
47We can have serialization issues when we post an event to the debugger.
48For example, a thread could send an "I hit a breakpoint and am suspending
49myself" message to the debugger. Before it manages to suspend itself, the
50debugger's response ("not interested, resume thread") arrives and is
51processed. We try to resume a thread that hasn't yet suspended.
52
53This means that, after posting an event to the debugger, we need to wait
54for the event thread to suspend itself (and, potentially, all other threads)
55before processing any additional requests from the debugger. While doing
56so we need to be aware that multiple threads may be hitting breakpoints
57or other events simultaneously, so we either need to wait for all of them
58or serialize the events with each other.
59
60The current mechanism works like this:
61 Event thread:
62 - If I'm going to suspend, grab the "I am posting an event" token. Wait
63 for it if it's not currently available.
64 - Post the event to the debugger.
65 - If appropriate, suspend others and then myself. As part of suspending
66 myself, release the "I am posting" token.
67 JDWP thread:
68 - When an event arrives, see if somebody is posting an event. If so,
69 sleep until we can acquire the "I am posting an event" token. Release
70 it immediately and continue processing -- the event we have already
71 received should not interfere with other events that haven't yet
72 been posted.
73
74Some care must be taken to avoid deadlock:
75
76 - thread A and thread B exit near-simultaneously, and post thread-death
77 events with a "suspend all" clause
78 - thread A gets the event token, thread B sits and waits for it
79 - thread A wants to suspend all other threads, but thread B is waiting
80 for the token and can't be suspended
81
82So we need to mark thread B in such a way that thread A doesn't wait for it.
83
84If we just bracket the "grab event token" call with a change to VMWAIT
85before sleeping, the switch back to RUNNING state when we get the token
86will cause thread B to suspend (remember, thread A's global suspend is
87still in force, even after it releases the token). Suspending while
88holding the event token is very bad, because it prevents the JDWP thread
89from processing incoming messages.
90
91We need to change to VMWAIT state at the *start* of posting an event,
92and stay there until we either finish posting the event or decide to
93put ourselves to sleep. That way we don't interfere with anyone else and
94don't allow anyone else to interfere with us.
95*/
96
97
98#define kJdwpEventCommandSet 64
99#define kJdwpCompositeCommand 100
100
101namespace art {
102
103namespace JDWP {
104
105/*
106 * Stuff to compare against when deciding if a mod matches. Only the
107 * values for mods valid for the event being evaluated will be filled in.
108 * The rest will be zeroed.
109 */
110struct ModBasket {
111 const JdwpLocation* pLoc; /* LocationOnly */
Elliott Hughesa2155262011-11-16 16:26:58 -0800112 std::string className; /* ClassMatch/ClassExclude */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700113 ObjectId threadId; /* ThreadOnly */
114 RefTypeId classId; /* ClassOnly */
115 RefTypeId excepClassId; /* ExceptionOnly */
116 bool caught; /* ExceptionOnly */
117 FieldId field; /* FieldOnly */
118 ObjectId thisPtr; /* InstanceOnly */
119 /* nothing for StepOnly -- handled differently */
120};
121
122/*
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700123 * Lock the "event" mutex, which guards the list of registered events.
124 */
125static void lockEventMutex(JdwpState* state) {
126 //Dbg::ThreadWaiting();
127 state->event_lock_.Lock();
128 //Dbg::ThreadRunning();
129}
130
131/*
132 * Unlock the "event" mutex.
133 */
134static void unlockEventMutex(JdwpState* state) {
135 state->event_lock_.Unlock();
136}
137
138/*
139 * Dump an event to the log file.
140 */
141static void dumpEvent(const JdwpEvent* pEvent) {
142 LOG(INFO) << StringPrintf("Event id=0x%4x %p (prev=%p next=%p):", pEvent->requestId, pEvent, pEvent->prev, pEvent->next);
143 LOG(INFO) << " kind=" << pEvent->eventKind << " susp=" << pEvent->suspendPolicy << " modCount=" << pEvent->modCount;
144
145 for (int i = 0; i < pEvent->modCount; i++) {
146 const JdwpEventMod* pMod = &pEvent->mods[i];
147 LOG(INFO) << " " << static_cast<JdwpModKind>(pMod->modKind);
148 /* TODO - show details */
149 }
150}
151
152/*
153 * Add an event to the list. Ordering is not important.
154 *
155 * If something prevents the event from being registered, e.g. it's a
156 * single-step request on a thread that doesn't exist, the event will
157 * not be added to the list, and an appropriate error will be returned.
158 */
159JdwpError RegisterEvent(JdwpState* state, JdwpEvent* pEvent) {
160 lockEventMutex(state);
161
162 CHECK(state != NULL);
163 CHECK(pEvent != NULL);
164 CHECK(pEvent->prev == NULL);
165 CHECK(pEvent->next == NULL);
166
167 /*
168 * If one or more "break"-type mods are used, register them with
169 * the interpreter.
170 */
171 for (int i = 0; i < pEvent->modCount; i++) {
172 const JdwpEventMod* pMod = &pEvent->mods[i];
173 if (pMod->modKind == MK_LOCATION_ONLY) {
174 /* should only be for Breakpoint, Step, and Exception */
175 Dbg::WatchLocation(&pMod->locationOnly.loc);
176 } else if (pMod->modKind == MK_STEP) {
177 /* should only be for EK_SINGLE_STEP; should only be one */
178 JdwpStepSize size = static_cast<JdwpStepSize>(pMod->step.size);
179 JdwpStepDepth depth = static_cast<JdwpStepDepth>(pMod->step.depth);
180 Dbg::ConfigureStep(pMod->step.threadId, size, depth);
181 } else if (pMod->modKind == MK_FIELD_ONLY) {
182 /* should be for EK_FIELD_ACCESS or EK_FIELD_MODIFICATION */
183 dumpEvent(pEvent); /* TODO - need for field watches */
184 }
185 }
186
187 /*
188 * Add to list.
189 */
190 if (state->eventList != NULL) {
191 pEvent->next = state->eventList;
192 state->eventList->prev = pEvent;
193 }
194 state->eventList = pEvent;
195 state->numEvents++;
196
197 unlockEventMutex(state);
198
199 return ERR_NONE;
200}
201
202/*
203 * Remove an event from the list. This will also remove the event from
204 * any optimization tables, e.g. breakpoints.
205 *
206 * Does not free the JdwpEvent.
207 *
208 * Grab the eventLock before calling here.
209 */
210static void unregisterEvent(JdwpState* state, JdwpEvent* pEvent) {
211 if (pEvent->prev == NULL) {
212 /* head of the list */
213 CHECK(state->eventList == pEvent);
214
215 state->eventList = pEvent->next;
216 } else {
217 pEvent->prev->next = pEvent->next;
218 }
219
220 if (pEvent->next != NULL) {
221 pEvent->next->prev = pEvent->prev;
222 pEvent->next = NULL;
223 }
224 pEvent->prev = NULL;
225
226 /*
227 * Unhook us from the interpreter, if necessary.
228 */
229 for (int i = 0; i < pEvent->modCount; i++) {
230 JdwpEventMod* pMod = &pEvent->mods[i];
231 if (pMod->modKind == MK_LOCATION_ONLY) {
232 /* should only be for Breakpoint, Step, and Exception */
233 Dbg::UnwatchLocation(&pMod->locationOnly.loc);
234 }
235 if (pMod->modKind == MK_STEP) {
236 /* should only be for EK_SINGLE_STEP; should only be one */
237 Dbg::UnconfigureStep(pMod->step.threadId);
238 }
239 }
240
241 state->numEvents--;
242 CHECK(state->numEvents != 0 || state->eventList == NULL);
243}
244
245/*
246 * Remove the event with the given ID from the list.
247 *
248 * Failure to find the event isn't really an error, but it is a little
249 * weird. (It looks like Eclipse will try to be extra careful and will
250 * explicitly remove one-off single-step events.)
251 */
252void UnregisterEventById(JdwpState* state, uint32_t requestId) {
253 lockEventMutex(state);
254
255 JdwpEvent* pEvent = state->eventList;
256 while (pEvent != NULL) {
257 if (pEvent->requestId == requestId) {
258 unregisterEvent(state, pEvent);
259 EventFree(pEvent);
260 goto done; /* there can be only one with a given ID */
261 }
262
263 pEvent = pEvent->next;
264 }
265
266 //LOGD("Odd: no match when removing event reqId=0x%04x", requestId);
267
268done:
269 unlockEventMutex(state);
270}
271
272/*
273 * Remove all entries from the event list.
274 */
275void UnregisterAll(JdwpState* state) {
276 lockEventMutex(state);
277
278 JdwpEvent* pEvent = state->eventList;
279 while (pEvent != NULL) {
280 JdwpEvent* pNextEvent = pEvent->next;
281
282 unregisterEvent(state, pEvent);
283 EventFree(pEvent);
284 pEvent = pNextEvent;
285 }
286
287 state->eventList = NULL;
288
289 unlockEventMutex(state);
290}
291
292/*
293 * Allocate a JdwpEvent struct with enough space to hold the specified
294 * number of mod records.
295 */
296JdwpEvent* EventAlloc(int numMods) {
297 JdwpEvent* newEvent;
298 int allocSize = offsetof(JdwpEvent, mods) + numMods * sizeof(newEvent->mods[0]);
299 newEvent = reinterpret_cast<JdwpEvent*>(malloc(allocSize));
300 memset(newEvent, 0, allocSize);
301 return newEvent;
302}
303
304/*
305 * Free a JdwpEvent.
306 *
307 * Do not call this until the event has been removed from the list.
308 */
309void EventFree(JdwpEvent* pEvent) {
310 if (pEvent == NULL) {
311 return;
312 }
313
314 /* make sure it was removed from the list */
315 CHECK(pEvent->prev == NULL);
316 CHECK(pEvent->next == NULL);
317 /* want to check state->eventList != pEvent */
318
319 /*
320 * Free any hairy bits in the mods.
321 */
322 for (int i = 0; i < pEvent->modCount; i++) {
323 if (pEvent->mods[i].modKind == MK_CLASS_MATCH) {
324 free(pEvent->mods[i].classMatch.classPattern);
325 pEvent->mods[i].classMatch.classPattern = NULL;
326 }
327 if (pEvent->mods[i].modKind == MK_CLASS_EXCLUDE) {
328 free(pEvent->mods[i].classExclude.classPattern);
329 pEvent->mods[i].classExclude.classPattern = NULL;
330 }
331 }
332
333 free(pEvent);
334}
335
336/*
337 * Allocate storage for matching events. To keep things simple we
338 * use an array with enough storage for the entire list.
339 *
340 * The state->eventLock should be held before calling.
341 */
342static JdwpEvent** allocMatchList(JdwpState* state) {
343 return (JdwpEvent**) malloc(sizeof(JdwpEvent*) * state->numEvents);
344}
345
346/*
347 * Run through the list and remove any entries with an expired "count" mod
348 * from the event list, then free the match list.
349 */
350static void cleanupMatchList(JdwpState* state, JdwpEvent** matchList, int matchCount) {
351 JdwpEvent** ppEvent = matchList;
352
353 while (matchCount--) {
354 JdwpEvent* pEvent = *ppEvent;
355
356 for (int i = 0; i < pEvent->modCount; i++) {
357 if (pEvent->mods[i].modKind == MK_COUNT && pEvent->mods[i].count.count == 0) {
358 LOG(VERBOSE) << "##### Removing expired event";
359 unregisterEvent(state, pEvent);
360 EventFree(pEvent);
361 break;
362 }
363 }
364
365 ppEvent++;
366 }
367
368 free(matchList);
369}
370
371/*
372 * Match a string against a "restricted regular expression", which is just
373 * a string that may start or end with '*' (e.g. "*.Foo" or "java.*").
374 *
375 * ("Restricted name globbing" might have been a better term.)
376 */
Elliott Hughesa2155262011-11-16 16:26:58 -0800377static bool patternMatch(const char* pattern, const std::string& target) {
378 size_t patLen = strlen(pattern);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700379
380 if (pattern[0] == '*') {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700381 patLen--;
382 // TODO: remove printf when we find a test case to verify this
Elliott Hughesa2155262011-11-16 16:26:58 -0800383 LOG(ERROR) << ">>> comparing '" << (pattern + 1) << "' to '" << (target.c_str() + (target.size()-patLen)) << "'";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700384
Elliott Hughesa2155262011-11-16 16:26:58 -0800385 if (target.size() < patLen) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700386 return false;
387 }
Elliott Hughesa2155262011-11-16 16:26:58 -0800388 return strcmp(pattern+1, target.c_str() + (target.size()-patLen)) == 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700389 } else if (pattern[patLen-1] == '*') {
Elliott Hughesa2155262011-11-16 16:26:58 -0800390 return strncmp(pattern, target.c_str(), patLen-1) == 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700391 } else {
Elliott Hughesa2155262011-11-16 16:26:58 -0800392 return strcmp(pattern, target.c_str()) == 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700393 }
394}
395
396/*
397 * See if two locations are equal.
398 *
399 * It's tempting to do a bitwise compare ("struct ==" or memcmp), but if
400 * the storage wasn't zeroed out there could be undefined values in the
401 * padding. Besides, the odds of "idx" being equal while the others aren't
402 * is very small, so this is usually just a simple integer comparison.
403 */
404static inline bool locationMatch(const JdwpLocation* pLoc1, const JdwpLocation* pLoc2) {
405 return pLoc1->idx == pLoc2->idx &&
406 pLoc1->methodId == pLoc2->methodId &&
407 pLoc1->classId == pLoc2->classId &&
408 pLoc1->typeTag == pLoc2->typeTag;
409}
410
411/*
412 * See if the event's mods match up with the contents of "basket".
413 *
414 * If we find a Count mod before rejecting an event, we decrement it. We
415 * need to do this even if later mods cause us to ignore the event.
416 */
417static bool modsMatch(JdwpState* state, JdwpEvent* pEvent, ModBasket* basket) {
418 JdwpEventMod* pMod = pEvent->mods;
419
420 for (int i = pEvent->modCount; i > 0; i--, pMod++) {
421 switch (pMod->modKind) {
422 case MK_COUNT:
423 CHECK_GT(pMod->count.count, 0);
424 pMod->count.count--;
425 break;
426 case MK_CONDITIONAL:
427 CHECK(false); // should not be getting these
428 break;
429 case MK_THREAD_ONLY:
430 if (pMod->threadOnly.threadId != basket->threadId) {
431 return false;
432 }
433 break;
434 case MK_CLASS_ONLY:
435 if (!Dbg::MatchType(basket->classId, pMod->classOnly.refTypeId)) {
436 return false;
437 }
438 break;
439 case MK_CLASS_MATCH:
440 if (!patternMatch(pMod->classMatch.classPattern, basket->className)) {
441 return false;
442 }
443 break;
444 case MK_CLASS_EXCLUDE:
445 if (patternMatch(pMod->classMatch.classPattern, basket->className)) {
446 return false;
447 }
448 break;
449 case MK_LOCATION_ONLY:
450 if (!locationMatch(&pMod->locationOnly.loc, basket->pLoc)) {
451 return false;
452 }
453 break;
454 case MK_EXCEPTION_ONLY:
455 if (pMod->exceptionOnly.refTypeId != 0 && !Dbg::MatchType(basket->excepClassId, pMod->exceptionOnly.refTypeId)) {
456 return false;
457 }
458 if ((basket->caught && !pMod->exceptionOnly.caught) || (!basket->caught && !pMod->exceptionOnly.uncaught)) {
459 return false;
460 }
461 break;
462 case MK_FIELD_ONLY:
463 if (!Dbg::MatchType(basket->classId, pMod->fieldOnly.refTypeId) || pMod->fieldOnly.fieldId != basket->field) {
464 return false;
465 }
466 break;
467 case MK_STEP:
468 if (pMod->step.threadId != basket->threadId) {
469 return false;
470 }
471 break;
472 case MK_INSTANCE_ONLY:
473 if (pMod->instanceOnly.objectId != basket->thisPtr) {
474 return false;
475 }
476 break;
477 default:
478 LOG(ERROR) << "unhandled mod kind " << pMod->modKind;
479 CHECK(false);
480 break;
481 }
482 }
483 return true;
484}
485
486/*
487 * Find all events of type "eventKind" with mods that match up with the
488 * rest of the arguments.
489 *
490 * Found events are appended to "matchList", and "*pMatchCount" is advanced,
491 * so this may be called multiple times for grouped events.
492 *
493 * DO NOT call this multiple times for the same eventKind, as Count mods are
494 * decremented during the scan.
495 */
496static void findMatchingEvents(JdwpState* state, JdwpEventKind eventKind,
497 ModBasket* basket, JdwpEvent** matchList, int* pMatchCount) {
498 /* start after the existing entries */
499 matchList += *pMatchCount;
500
501 JdwpEvent* pEvent = state->eventList;
502 while (pEvent != NULL) {
503 if (pEvent->eventKind == eventKind && modsMatch(state, pEvent, basket)) {
504 *matchList++ = pEvent;
505 (*pMatchCount)++;
506 }
507
508 pEvent = pEvent->next;
509 }
510}
511
512/*
513 * Scan through the list of matches and determine the most severe
514 * suspension policy.
515 */
516static JdwpSuspendPolicy scanSuspendPolicy(JdwpEvent** matchList, int matchCount) {
517 JdwpSuspendPolicy policy = SP_NONE;
518
519 while (matchCount--) {
520 if ((*matchList)->suspendPolicy > policy) {
521 policy = (*matchList)->suspendPolicy;
522 }
523 matchList++;
524 }
525
526 return policy;
527}
528
529/*
530 * Three possibilities:
531 * SP_NONE - do nothing
532 * SP_EVENT_THREAD - suspend ourselves
533 * SP_ALL - suspend everybody except JDWP support thread
534 */
535static void suspendByPolicy(JdwpState* state, JdwpSuspendPolicy suspendPolicy) {
536 if (suspendPolicy == SP_NONE) {
537 return;
538 }
539
540 if (suspendPolicy == SP_ALL) {
Elliott Hughes475fc232011-10-25 15:00:35 -0700541 Dbg::SuspendVM();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700542 } else {
543 CHECK_EQ(suspendPolicy, SP_EVENT_THREAD);
544 }
545
546 /* this is rare but possible -- see CLASS_PREPARE handling */
547 if (Dbg::GetThreadSelfId() == state->debugThreadId) {
548 LOG(INFO) << "NOTE: suspendByPolicy not suspending JDWP thread";
549 return;
550 }
551
552 DebugInvokeReq* pReq = Dbg::GetInvokeReq();
553 while (true) {
554 pReq->ready = true;
555 Dbg::SuspendSelf();
556 pReq->ready = false;
557
558 /*
559 * The JDWP thread has told us (and possibly all other threads) to
560 * resume. See if it has left anything in our DebugInvokeReq mailbox.
561 */
Elliott Hughes475fc232011-10-25 15:00:35 -0700562 if (!pReq->invoke_needed) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700563 /*LOGD("suspendByPolicy: no invoke needed");*/
564 break;
565 }
566
567 /* grab this before posting/suspending again */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700568 state->SetWaitForEventThread(Dbg::GetThreadSelfId());
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700569
Elliott Hughes475fc232011-10-25 15:00:35 -0700570 /* leave pReq->invoke_needed raised so we can check reentrancy */
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700571 LOG(VERBOSE) << "invoking method...";
572 Dbg::ExecuteMethod(pReq);
573
Elliott Hughes475fc232011-10-25 15:00:35 -0700574 pReq->error = ERR_NONE;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700575
576 /* clear this before signaling */
Elliott Hughes475fc232011-10-25 15:00:35 -0700577 pReq->invoke_needed = false;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700578
579 LOG(VERBOSE) << "invoke complete, signaling and self-suspending";
580 MutexLock mu(pReq->lock_);
581 pReq->cond_.Signal();
582 }
583}
584
585/*
586 * Determine if there is a method invocation in progress in the current
587 * thread.
588 *
Elliott Hughes475fc232011-10-25 15:00:35 -0700589 * We look at the "invoke_needed" flag in the per-thread DebugInvokeReq
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700590 * state. If set, we're in the process of invoking a method.
591 */
592static bool invokeInProgress(JdwpState* state) {
593 DebugInvokeReq* pReq = Dbg::GetInvokeReq();
Elliott Hughes475fc232011-10-25 15:00:35 -0700594 return pReq->invoke_needed;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700595}
596
597/*
598 * We need the JDWP thread to hold off on doing stuff while we post an
599 * event and then suspend ourselves.
600 *
601 * Call this with a threadId of zero if you just want to wait for the
602 * current thread operation to complete.
603 *
604 * This could go to sleep waiting for another thread, so it's important
605 * that the thread be marked as VMWAIT before calling here.
606 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700607void JdwpState::SetWaitForEventThread(ObjectId threadId) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700608 bool waited = false;
609
610 /* this is held for very brief periods; contention is unlikely */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700611 MutexLock mu(event_thread_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700612
613 /*
614 * If another thread is already doing stuff, wait for it. This can
615 * go to sleep indefinitely.
616 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700617 while (eventThreadId != 0) {
618 LOG(VERBOSE) << StringPrintf("event in progress (0x%llx), 0x%llx sleeping", eventThreadId, threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700619 waited = true;
Elliott Hughes376a7a02011-10-24 18:35:55 -0700620 event_thread_cond_.Wait(event_thread_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700621 }
622
623 if (waited || threadId != 0) {
624 LOG(VERBOSE) << StringPrintf("event token grabbed (0x%llx)", threadId);
625 }
626 if (threadId != 0) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700627 eventThreadId = threadId;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700628 }
629}
630
631/*
632 * Clear the threadId and signal anybody waiting.
633 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700634void JdwpState::ClearWaitForEventThread() {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700635 /*
636 * Grab the mutex. Don't try to go in/out of VMWAIT mode, as this
637 * function is called by dvmSuspendSelf(), and the transition back
638 * to RUNNING would confuse it.
639 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700640 MutexLock mu(event_thread_lock_);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700641
Elliott Hughes376a7a02011-10-24 18:35:55 -0700642 CHECK_NE(eventThreadId, 0U);
643 LOG(VERBOSE) << StringPrintf("cleared event token (0x%llx)", eventThreadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700644
Elliott Hughes376a7a02011-10-24 18:35:55 -0700645 eventThreadId = 0;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700646
Elliott Hughes376a7a02011-10-24 18:35:55 -0700647 event_thread_cond_.Signal();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700648}
649
650
651/*
652 * Prep an event. Allocates storage for the message and leaves space for
653 * the header.
654 */
655static ExpandBuf* eventPrep() {
656 ExpandBuf* pReq = expandBufAlloc();
657 expandBufAddSpace(pReq, kJDWPHeaderLen);
658 return pReq;
659}
660
661/*
662 * Write the header into the buffer and send the packet off to the debugger.
663 *
664 * Takes ownership of "pReq" (currently discards it).
665 */
666static void eventFinish(JdwpState* state, ExpandBuf* pReq) {
667 uint8_t* buf = expandBufGetBuffer(pReq);
668
Elliott Hughesf7c3b662011-10-27 12:04:56 -0700669 Set4BE(buf, expandBufGetLength(pReq));
670 Set4BE(buf+4, state->NextRequestSerial());
671 Set1(buf+8, 0); /* flags */
672 Set1(buf+9, kJdwpEventCommandSet);
673 Set1(buf+10, kJdwpCompositeCommand);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700674
Elliott Hughes376a7a02011-10-24 18:35:55 -0700675 state->SendRequest(pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700676
677 expandBufFree(pReq);
678}
679
680
681/*
682 * Tell the debugger that we have finished initializing. This is always
683 * sent, even if the debugger hasn't requested it.
684 *
685 * This should be sent "before the main thread is started and before
686 * any application code has been executed". The thread ID in the message
687 * must be for the main thread.
688 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700689bool JdwpState::PostVMStart() {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700690 JdwpSuspendPolicy suspendPolicy;
691 ObjectId threadId = Dbg::GetThreadSelfId();
692
Elliott Hughes376a7a02011-10-24 18:35:55 -0700693 if (options_->suspend) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700694 suspendPolicy = SP_ALL;
695 } else {
696 suspendPolicy = SP_NONE;
697 }
698
699 /* probably don't need this here */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700700 lockEventMutex(this);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700701
702 ExpandBuf* pReq = NULL;
703 if (true) {
704 LOG(VERBOSE) << "EVENT: " << EK_VM_START;
705 LOG(VERBOSE) << " suspendPolicy=" << suspendPolicy;
706
707 pReq = eventPrep();
708 expandBufAdd1(pReq, suspendPolicy);
709 expandBufAdd4BE(pReq, 1);
710
711 expandBufAdd1(pReq, EK_VM_START);
712 expandBufAdd4BE(pReq, 0); /* requestId */
713 expandBufAdd8BE(pReq, threadId);
714 }
715
Elliott Hughes376a7a02011-10-24 18:35:55 -0700716 unlockEventMutex(this);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700717
718 /* send request and possibly suspend ourselves */
719 if (pReq != NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700720 int old_state = Dbg::ThreadWaiting();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700721 if (suspendPolicy != SP_NONE) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700722 SetWaitForEventThread(threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700723 }
724
Elliott Hughes376a7a02011-10-24 18:35:55 -0700725 eventFinish(this, pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700726
Elliott Hughes376a7a02011-10-24 18:35:55 -0700727 suspendByPolicy(this, suspendPolicy);
728 Dbg::ThreadContinuing(old_state);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700729 }
730
731 return true;
732}
733
734// TODO: This doesn't behave like the real dvmDescriptorToName.
735// I'm hoping this isn't used to communicate with the debugger, and we can just use descriptors.
Elliott Hughesa2155262011-11-16 16:26:58 -0800736std::string dvmDescriptorToName(const std::string& descriptor) {
737 return descriptor;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700738}
739
740/*
741 * A location of interest has been reached. This handles:
742 * Breakpoint
743 * SingleStep
744 * MethodEntry
745 * MethodExit
746 * These four types must be grouped together in a single response. The
747 * "eventFlags" indicates the type of event(s) that have happened.
748 *
749 * Valid mods:
750 * Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, InstanceOnly
751 * LocationOnly (for breakpoint/step only)
752 * Step (for step only)
753 *
754 * Interesting test cases:
755 * - Put a breakpoint on a native method. Eclipse creates METHOD_ENTRY
756 * and METHOD_EXIT events with a ClassOnly mod on the method's class.
757 * - Use "run to line". Eclipse creates a BREAKPOINT with Count=1.
758 * - Single-step to a line with a breakpoint. Should get a single
759 * event message with both events in it.
760 */
761bool PostLocationEvent(JdwpState* state, const JdwpLocation* pLoc, ObjectId thisPtr, int eventFlags) {
762 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700763
764 memset(&basket, 0, sizeof(basket));
765 basket.pLoc = pLoc;
766 basket.classId = pLoc->classId;
767 basket.thisPtr = thisPtr;
768 basket.threadId = Dbg::GetThreadSelfId();
Elliott Hughesa2155262011-11-16 16:26:58 -0800769 basket.className = dvmDescriptorToName(Dbg::GetClassDescriptor(pLoc->classId));
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700770
771 /*
772 * On rare occasions we may need to execute interpreted code in the VM
773 * while handling a request from the debugger. Don't fire breakpoints
774 * while doing so. (I don't think we currently do this at all, so
775 * this is mostly paranoia.)
776 */
777 if (basket.threadId == state->debugThreadId) {
778 LOG(VERBOSE) << "Ignoring location event in JDWP thread";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700779 return false;
780 }
781
782 /*
783 * The debugger variable display tab may invoke the interpreter to format
784 * complex objects. We want to ignore breakpoints and method entry/exit
785 * traps while working on behalf of the debugger.
786 *
787 * If we don't ignore them, the VM will get hung up, because we'll
788 * suspend on a breakpoint while the debugger is still waiting for its
789 * method invocation to complete.
790 */
791 if (invokeInProgress(state)) {
792 LOG(VERBOSE) << "Not checking breakpoints during invoke (" << basket.className << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700793 return false;
794 }
795
796 /* don't allow the list to be updated while we scan it */
797 lockEventMutex(state);
798
799 JdwpEvent** matchList = allocMatchList(state);
800 int matchCount = 0;
801
802 if ((eventFlags & Dbg::kBreakPoint) != 0) {
803 findMatchingEvents(state, EK_BREAKPOINT, &basket, matchList, &matchCount);
804 }
805 if ((eventFlags & Dbg::kSingleStep) != 0) {
806 findMatchingEvents(state, EK_SINGLE_STEP, &basket, matchList, &matchCount);
807 }
808 if ((eventFlags & Dbg::kMethodEntry) != 0) {
809 findMatchingEvents(state, EK_METHOD_ENTRY, &basket, matchList, &matchCount);
810 }
811 if ((eventFlags & Dbg::kMethodExit) != 0) {
812 findMatchingEvents(state, EK_METHOD_EXIT, &basket, matchList, &matchCount);
813 }
814
815 ExpandBuf* pReq = NULL;
816 JdwpSuspendPolicy suspendPolicy = SP_NONE;
817 if (matchCount != 0) {
818 LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
819 << basket.className << "." << Dbg::GetMethodName(pLoc->classId, pLoc->methodId)
820 << " thread=" << (void*) basket.threadId << " code=" << (void*) pLoc->idx << ")";
821
822 suspendPolicy = scanSuspendPolicy(matchList, matchCount);
823 LOG(VERBOSE) << " suspendPolicy=" << suspendPolicy;
824
825 pReq = eventPrep();
826 expandBufAdd1(pReq, suspendPolicy);
827 expandBufAdd4BE(pReq, matchCount);
828
829 for (int i = 0; i < matchCount; i++) {
830 expandBufAdd1(pReq, matchList[i]->eventKind);
831 expandBufAdd4BE(pReq, matchList[i]->requestId);
832 expandBufAdd8BE(pReq, basket.threadId);
833 AddLocation(pReq, pLoc);
834 }
835 }
836
837 cleanupMatchList(state, matchList, matchCount);
838 unlockEventMutex(state);
839
840 /* send request and possibly suspend ourselves */
841 if (pReq != NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700842 int old_state = Dbg::ThreadWaiting();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700843 if (suspendPolicy != SP_NONE) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700844 state->SetWaitForEventThread(basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700845 }
846
847 eventFinish(state, pReq);
848
849 suspendByPolicy(state, suspendPolicy);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700850 Dbg::ThreadContinuing(old_state);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700851 }
852
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700853 return matchCount != 0;
854}
855
856/*
857 * A thread is starting or stopping.
858 *
859 * Valid mods:
860 * Count, ThreadOnly
861 */
Elliott Hughes234ab152011-10-26 14:02:26 -0700862bool JdwpState::PostThreadChange(ObjectId threadId, bool start) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700863 CHECK_EQ(threadId, Dbg::GetThreadSelfId());
864
865 /*
866 * I don't think this can happen.
867 */
Elliott Hughes234ab152011-10-26 14:02:26 -0700868 if (invokeInProgress(this)) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700869 LOG(WARNING) << "Not posting thread change during invoke";
870 return false;
871 }
872
873 ModBasket basket;
874 memset(&basket, 0, sizeof(basket));
875 basket.threadId = threadId;
876
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700877 ExpandBuf* pReq = NULL;
878 JdwpSuspendPolicy suspendPolicy = SP_NONE;
Elliott Hughes234ab152011-10-26 14:02:26 -0700879 int matchCount = 0;
880 {
881 // Don't allow the list to be updated while we scan it.
882 MutexLock mu(event_lock_);
883 JdwpEvent** matchList = allocMatchList(this);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700884
Elliott Hughes234ab152011-10-26 14:02:26 -0700885 if (start) {
886 findMatchingEvents(this, EK_THREAD_START, &basket, matchList, &matchCount);
887 } else {
888 findMatchingEvents(this, EK_THREAD_DEATH, &basket, matchList, &matchCount);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700889 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700890
Elliott Hughes234ab152011-10-26 14:02:26 -0700891 if (matchCount != 0) {
892 LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
893 << "thread=" << (void*) basket.threadId << ")";
894
895 suspendPolicy = scanSuspendPolicy(matchList, matchCount);
896 LOG(VERBOSE) << " suspendPolicy=" << suspendPolicy;
897
898 pReq = eventPrep();
899 expandBufAdd1(pReq, suspendPolicy);
900 expandBufAdd4BE(pReq, matchCount);
901
902 for (int i = 0; i < matchCount; i++) {
903 expandBufAdd1(pReq, matchList[i]->eventKind);
904 expandBufAdd4BE(pReq, matchList[i]->requestId);
905 expandBufAdd8BE(pReq, basket.threadId);
906 }
907 }
908
909 cleanupMatchList(this, matchList, matchCount);
910 }
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700911
912 /* send request and possibly suspend ourselves */
913 if (pReq != NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -0700914 int old_state = Dbg::ThreadWaiting();
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700915 if (suspendPolicy != SP_NONE) {
Elliott Hughes234ab152011-10-26 14:02:26 -0700916 SetWaitForEventThread(basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700917 }
Elliott Hughes234ab152011-10-26 14:02:26 -0700918 eventFinish(this, pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700919
Elliott Hughes234ab152011-10-26 14:02:26 -0700920 suspendByPolicy(this, suspendPolicy);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700921 Dbg::ThreadContinuing(old_state);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700922 }
923
924 return matchCount != 0;
925}
926
927/*
928 * Send a polite "VM is dying" message to the debugger.
929 *
930 * Skips the usual "event token" stuff.
931 */
Elliott Hughes376a7a02011-10-24 18:35:55 -0700932bool JdwpState::PostVMDeath() {
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700933 LOG(VERBOSE) << "EVENT: " << EK_VM_DEATH;
934
935 ExpandBuf* pReq = eventPrep();
936 expandBufAdd1(pReq, SP_NONE);
937 expandBufAdd4BE(pReq, 1);
938
939 expandBufAdd1(pReq, EK_VM_DEATH);
940 expandBufAdd4BE(pReq, 0);
Elliott Hughes376a7a02011-10-24 18:35:55 -0700941 eventFinish(this, pReq);
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700942 return true;
943}
944
945/*
946 * An exception has been thrown. It may or may not have been caught.
947 *
948 * Valid mods:
949 * Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude, LocationOnly,
950 * ExceptionOnly, InstanceOnly
951 *
952 * The "exceptionId" has not been added to the GC-visible object registry,
953 * because there's a pretty good chance that we're not going to send it
954 * up the debugger.
955 */
956bool PostException(JdwpState* state, const JdwpLocation* pThrowLoc,
957 ObjectId exceptionId, RefTypeId exceptionClassId,
958 const JdwpLocation* pCatchLoc, ObjectId thisPtr)
959{
960 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700961
962 memset(&basket, 0, sizeof(basket));
963 basket.pLoc = pThrowLoc;
964 basket.classId = pThrowLoc->classId;
965 basket.threadId = Dbg::GetThreadSelfId();
Elliott Hughesa2155262011-11-16 16:26:58 -0800966 basket.className = dvmDescriptorToName(Dbg::GetClassDescriptor(basket.classId));
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700967 basket.excepClassId = exceptionClassId;
968 basket.caught = (pCatchLoc->classId != 0);
969 basket.thisPtr = thisPtr;
970
971 /* don't try to post an exception caused by the debugger */
972 if (invokeInProgress(state)) {
973 LOG(VERBOSE) << "Not posting exception hit during invoke (" << basket.className << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700974 return false;
975 }
976
977 /* don't allow the list to be updated while we scan it */
978 lockEventMutex(state);
979
980 JdwpEvent** matchList = allocMatchList(state);
981 int matchCount = 0;
982
983 findMatchingEvents(state, EK_EXCEPTION, &basket, matchList, &matchCount);
984
985 ExpandBuf* pReq = NULL;
986 JdwpSuspendPolicy suspendPolicy = SP_NONE;
987 if (matchCount != 0) {
988 LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total)"
989 << " thread=" << (void*) basket.threadId
990 << " exceptId=" << (void*) exceptionId
991 << " caught=" << basket.caught << ")";
992 LOG(VERBOSE) << StringPrintf(" throw: %d %llx %x %lld (%s.%s)", pThrowLoc->typeTag,
993 pThrowLoc->classId, pThrowLoc->methodId, pThrowLoc->idx,
Elliott Hughesa2155262011-11-16 16:26:58 -0800994 Dbg::GetClassDescriptor(pThrowLoc->classId).c_str(),
Elliott Hughes872d4ec2011-10-21 17:07:15 -0700995 Dbg::GetMethodName(pThrowLoc->classId, pThrowLoc->methodId));
996 if (pCatchLoc->classId == 0) {
997 LOG(VERBOSE) << " catch: (not caught)";
998 } else {
999 LOG(VERBOSE) << StringPrintf(" catch: %d %llx %x %lld (%s.%s)", pCatchLoc->typeTag,
1000 pCatchLoc->classId, pCatchLoc->methodId, pCatchLoc->idx,
Elliott Hughesa2155262011-11-16 16:26:58 -08001001 Dbg::GetClassDescriptor(pCatchLoc->classId).c_str(),
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001002 Dbg::GetMethodName(pCatchLoc->classId, pCatchLoc->methodId));
1003 }
1004
1005 suspendPolicy = scanSuspendPolicy(matchList, matchCount);
1006 LOG(VERBOSE) << " suspendPolicy=" << suspendPolicy;
1007
1008 pReq = eventPrep();
1009 expandBufAdd1(pReq, suspendPolicy);
1010 expandBufAdd4BE(pReq, matchCount);
1011
1012 for (int i = 0; i < matchCount; i++) {
1013 expandBufAdd1(pReq, matchList[i]->eventKind);
1014 expandBufAdd4BE(pReq, matchList[i]->requestId);
1015 expandBufAdd8BE(pReq, basket.threadId);
1016
1017 AddLocation(pReq, pThrowLoc);
1018 expandBufAdd1(pReq, JT_OBJECT);
1019 expandBufAdd8BE(pReq, exceptionId);
1020 AddLocation(pReq, pCatchLoc);
1021 }
1022
1023 /* don't let the GC discard it */
1024 Dbg::RegisterObjectId(exceptionId);
1025 }
1026
1027 cleanupMatchList(state, matchList, matchCount);
1028 unlockEventMutex(state);
1029
1030 /* send request and possibly suspend ourselves */
1031 if (pReq != NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -07001032 int old_state = Dbg::ThreadWaiting();
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001033 if (suspendPolicy != SP_NONE) {
Elliott Hughes376a7a02011-10-24 18:35:55 -07001034 state->SetWaitForEventThread(basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001035 }
1036
1037 eventFinish(state, pReq);
1038
1039 suspendByPolicy(state, suspendPolicy);
Elliott Hughes376a7a02011-10-24 18:35:55 -07001040 Dbg::ThreadContinuing(old_state);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001041 }
1042
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001043 return matchCount != 0;
1044}
1045
1046/*
1047 * Announce that a class has been loaded.
1048 *
1049 * Valid mods:
1050 * Count, ThreadOnly, ClassOnly, ClassMatch, ClassExclude
1051 */
1052bool PostClassPrepare(JdwpState* state, int tag, RefTypeId refTypeId, const char* signature, int status) {
1053 ModBasket basket;
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001054
1055 memset(&basket, 0, sizeof(basket));
1056 basket.classId = refTypeId;
1057 basket.threadId = Dbg::GetThreadSelfId();
Elliott Hughesa2155262011-11-16 16:26:58 -08001058 basket.className = dvmDescriptorToName(Dbg::GetClassDescriptor(basket.classId));
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001059
1060 /* suppress class prep caused by debugger */
1061 if (invokeInProgress(state)) {
1062 LOG(VERBOSE) << "Not posting class prep caused by invoke (" << basket.className << ")";
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001063 return false;
1064 }
1065
1066 /* don't allow the list to be updated while we scan it */
1067 lockEventMutex(state);
1068
1069 JdwpEvent** matchList = allocMatchList(state);
1070 int matchCount = 0;
1071
1072 findMatchingEvents(state, EK_CLASS_PREPARE, &basket, matchList, &matchCount);
1073
1074 ExpandBuf* pReq = NULL;
1075 JdwpSuspendPolicy suspendPolicy = SP_NONE;
1076 if (matchCount != 0) {
1077 LOG(VERBOSE) << "EVENT: " << matchList[0]->eventKind << "(" << matchCount << " total) "
1078 << "thread=" << (void*) basket.threadId << ")";
1079
1080 suspendPolicy = scanSuspendPolicy(matchList, matchCount);
1081 LOG(VERBOSE) << " suspendPolicy=" << suspendPolicy;
1082
1083 if (basket.threadId == state->debugThreadId) {
1084 /*
1085 * JDWP says that, for a class prep in the debugger thread, we
1086 * should set threadId to null and if any threads were supposed
1087 * to be suspended then we suspend all other threads.
1088 */
1089 LOG(VERBOSE) << " NOTE: class prepare in debugger thread!";
1090 basket.threadId = 0;
1091 if (suspendPolicy == SP_EVENT_THREAD) {
1092 suspendPolicy = SP_ALL;
1093 }
1094 }
1095
1096 pReq = eventPrep();
1097 expandBufAdd1(pReq, suspendPolicy);
1098 expandBufAdd4BE(pReq, matchCount);
1099
1100 for (int i = 0; i < matchCount; i++) {
1101 expandBufAdd1(pReq, matchList[i]->eventKind);
1102 expandBufAdd4BE(pReq, matchList[i]->requestId);
1103 expandBufAdd8BE(pReq, basket.threadId);
1104
1105 expandBufAdd1(pReq, tag);
1106 expandBufAdd8BE(pReq, refTypeId);
Elliott Hughesa2155262011-11-16 16:26:58 -08001107 expandBufAddUtf8String(pReq, signature);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001108 expandBufAdd4BE(pReq, status);
1109 }
1110 }
1111
1112 cleanupMatchList(state, matchList, matchCount);
1113
1114 unlockEventMutex(state);
1115
1116 /* send request and possibly suspend ourselves */
1117 if (pReq != NULL) {
Elliott Hughes376a7a02011-10-24 18:35:55 -07001118 int old_state = Dbg::ThreadWaiting();
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001119 if (suspendPolicy != SP_NONE) {
Elliott Hughes376a7a02011-10-24 18:35:55 -07001120 state->SetWaitForEventThread(basket.threadId);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001121 }
1122 eventFinish(state, pReq);
1123
1124 suspendByPolicy(state, suspendPolicy);
Elliott Hughes376a7a02011-10-24 18:35:55 -07001125 Dbg::ThreadContinuing(old_state);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001126 }
1127
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001128 return matchCount != 0;
1129}
1130
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001131/*
1132 * Send up a chunk of DDM data.
1133 *
1134 * While this takes the form of a JDWP "event", it doesn't interact with
1135 * other debugger traffic, and can't suspend the VM, so we skip all of
1136 * the fun event token gymnastics.
1137 */
Elliott Hughes82188472011-11-07 18:11:48 -08001138void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iovcnt) {
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001139 uint8_t header[kJDWPHeaderLen + 8];
1140 size_t dataLen = 0;
1141
1142 CHECK(iov != NULL);
1143 CHECK(iovcnt > 0 && iovcnt < 10);
1144
1145 /*
1146 * "Wrap" the contents of the iovec with a JDWP/DDMS header. We do
1147 * this by creating a new copy of the vector with space for the header.
1148 */
1149 iovec wrapiov[iovcnt+1];
1150 for (int i = 0; i < iovcnt; i++) {
1151 wrapiov[i+1].iov_base = iov[i].iov_base;
1152 wrapiov[i+1].iov_len = iov[i].iov_len;
1153 dataLen += iov[i].iov_len;
1154 }
1155
1156 /* form the header (JDWP plus DDMS) */
Elliott Hughesf7c3b662011-10-27 12:04:56 -07001157 Set4BE(header, sizeof(header) + dataLen);
1158 Set4BE(header+4, NextRequestSerial());
1159 Set1(header+8, 0); /* flags */
1160 Set1(header+9, kJDWPDdmCmdSet);
1161 Set1(header+10, kJDWPDdmCmd);
1162 Set4BE(header+11, type);
1163 Set4BE(header+15, dataLen);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001164
1165 wrapiov[0].iov_base = header;
1166 wrapiov[0].iov_len = sizeof(header);
1167
1168 /*
1169 * Make sure we're in VMWAIT in case the write blocks.
1170 */
Elliott Hughes376a7a02011-10-24 18:35:55 -07001171 int old_state = Dbg::ThreadWaiting();
1172 (*transport->sendBufferedRequest)(this, wrapiov, iovcnt + 1);
1173 Dbg::ThreadContinuing(old_state);
Elliott Hughes872d4ec2011-10-21 17:07:15 -07001174}
1175
1176} // namespace JDWP
1177
1178} // namespace art