Implement JDWP InvokeMethod and breakpoints on exception throwing.
Change-Id: I1142bee843104f0850fd7270752104d5d73a44f0
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index b628e6c..36e2657 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -31,6 +31,7 @@
namespace art {
+struct Method;
struct Thread;
namespace JDWP {
@@ -56,6 +57,7 @@
static inline RefTypeId ReadRefTypeId(const uint8_t** pBuf) { return Read8BE(pBuf); }
static inline FrameId ReadFrameId(const uint8_t** pBuf) { return Read8BE(pBuf); }
static inline JdwpTag ReadTag(const uint8_t** pBuf) { return static_cast<JdwpTag>(Read1(pBuf)); }
+static inline JdwpTypeTag ReadTypeTag(const uint8_t** pBuf) { return static_cast<JdwpTypeTag>(Read1(pBuf)); }
static inline void SetFieldId(uint8_t* buf, FieldId val) { return Set4BE(buf, val); }
static inline void SetMethodId(uint8_t* buf, MethodId val) { return Set4BE(buf, val); }
static inline void SetObjectId(uint8_t* buf, ObjectId val) { return Set8BE(buf, val); }
@@ -71,10 +73,10 @@
* Holds a JDWP "location".
*/
struct JdwpLocation {
- uint8_t typeTag; /* class or interface? */
- RefTypeId classId; /* method->clazz */
- MethodId methodId; /* method in which "idx" resides */
- uint64_t idx; /* relative index into code block */
+ JdwpTypeTag typeTag;
+ RefTypeId classId;
+ MethodId methodId;
+ uint64_t idx; // A Dex PC.
};
std::ostream& operator<<(std::ostream& os, const JdwpLocation& rhs);
diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc
index 15e1151..424d87f 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -535,7 +535,7 @@
* The JDWP thread has told us (and possibly all other threads) to
* resume. See if it has left anything in our DebugInvokeReq mailbox.
*/
- if (!pReq->invoke_needed) {
+ if (!pReq->invoke_needed_) {
/*LOGD("SuspendByPolicy: no invoke needed");*/
break;
}
@@ -543,14 +543,14 @@
/* grab this before posting/suspending again */
SetWaitForEventThread(Dbg::GetThreadSelfId());
- /* leave pReq->invoke_needed raised so we can check reentrancy */
+ /* leave pReq->invoke_needed_ raised so we can check reentrancy */
LOG(VERBOSE) << "invoking method...";
Dbg::ExecuteMethod(pReq);
pReq->error = ERR_NONE;
/* clear this before signaling */
- pReq->invoke_needed = false;
+ pReq->invoke_needed_ = false;
LOG(VERBOSE) << "invoke complete, signaling and self-suspending";
MutexLock mu(pReq->lock_);
@@ -567,7 +567,7 @@
*/
bool JdwpState::InvokeInProgress() {
DebugInvokeReq* pReq = Dbg::GetInvokeReq();
- return pReq->invoke_needed;
+ return pReq->invoke_needed_;
}
/*
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 9b5c080..238775e 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -49,7 +49,7 @@
*/
static void jdwpReadLocation(const uint8_t** pBuf, JdwpLocation* pLoc) {
memset(pLoc, 0, sizeof(*pLoc)); /* allows memcmp() later */
- pLoc->typeTag = Read1(pBuf);
+ pLoc->typeTag = ReadTypeTag(pBuf);
pLoc->classId = ReadObjectId(pBuf);
pLoc->methodId = ReadMethodId(pBuf);
pLoc->idx = Read8BE(pBuf);
@@ -1467,16 +1467,16 @@
* Returns the value of "this" for the specified frame.
*/
static JdwpError handleSF_ThisObject(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) {
- ObjectId threadId = ReadObjectId(&buf);
+ ReadObjectId(&buf); // Skip thread id.
FrameId frameId = ReadFrameId(&buf);
ObjectId objectId;
- if (!Dbg::GetThisObject(threadId, frameId, &objectId)) {
+ if (!Dbg::GetThisObject(frameId, &objectId)) {
return ERR_INVALID_FRAMEID;
}
uint8_t objectTag = Dbg::GetObjectTag(objectId);
- LOG(VERBOSE) << StringPrintf(" Req for 'this' in thread=%llx frame=%llx --> %llx '%c'", threadId, frameId, objectId, (char)objectTag);
+ LOG(VERBOSE) << StringPrintf(" Req for 'this' in frame=%llx --> %llx '%c'", frameId, objectId, (char)objectTag);
expandBufAdd1(pReply, objectTag);
expandBufAddObjectId(pReply, objectId);
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index 07ffc52..98490e2 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -451,9 +451,9 @@
}
std::ostream& operator<<(std::ostream& os, const JdwpLocation& rhs) {
- // TODO: do we really want the Class* and Method* as pointers?
- os << rhs.typeTag << " " << (void*) rhs.classId << " " << (void*) rhs.methodId << " " << rhs.idx
- << " (" << Dbg::GetClassDescriptor(rhs.classId) << "." << Dbg::GetMethodName(rhs.classId, rhs.methodId) << ")";
+ os << "JdwpLocation["
+ << Dbg::GetClassDescriptor(rhs.classId) << "." << Dbg::GetMethodName(rhs.classId, rhs.methodId)
+ << "@" << rhs.idx << " " << rhs.typeTag << "]";
return os;
}
@@ -481,6 +481,17 @@
return os;
}
+std::ostream& operator<<(std::ostream& os, const JdwpTypeTag& value) {
+ switch (value) {
+ case TT_CLASS: os << "TT_CLASS"; break;
+ case TT_INTERFACE: os << "TT_INTERFACE"; break;
+ case TT_ARRAY: os << "TT_ARRAY"; break;
+ default:
+ os << "JdwpTypeTag[" << static_cast<int32_t>(value) << "]";
+ }
+ return os;
+}
+
} // namespace JDWP
} // namespace art