Implement Method.Bytecodes.
Change-Id: Ib24c1244818c1d5aa10606a4998c0e52fa2b70bd
diff --git a/src/debugger.cc b/src/debugger.cc
index 1df7fe9..5db7bf5 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1359,6 +1359,24 @@
JDWP::Set4BE(expandBufGetBuffer(pReply) + variable_count_offset, context.variable_count);
}
+JDWP::JdwpError Dbg::GetBytecodes(JDWP::RefTypeId, JDWP::MethodId method_id,
+ std::vector<uint8_t>& bytecodes)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ AbstractMethod* m = FromMethodId(method_id);
+ if (m == NULL) {
+ return JDWP::ERR_INVALID_METHODID;
+ }
+ MethodHelper mh(m);
+ const DexFile::CodeItem* code_item = mh.GetCodeItem();
+ size_t byte_count = code_item->insns_size_in_code_units_ * 2;
+ const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_);
+ const uint8_t* end = begin + byte_count;
+ for (const uint8_t* p = begin; p != end; ++p) {
+ bytecodes.push_back(*p);
+ }
+ return JDWP::ERR_NONE;
+}
+
JDWP::JdwpTag Dbg::GetFieldBasicTag(JDWP::FieldId field_id) {
return BasicTagFromDescriptor(FieldHelper(FromFieldId(field_id)).GetTypeDescriptor());
}
diff --git a/src/debugger.h b/src/debugger.h
index c03adea..b33216b 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -196,9 +196,9 @@
std::vector<JDWP::ObjectId>& referring_objects)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- /*
- * Method and Field
- */
+ //
+ // Methods and fields.
+ //
static std::string GetMethodName(JDWP::RefTypeId ref_type_id, JDWP::MethodId id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static JDWP::JdwpError OutputDeclaredFields(JDWP::RefTypeId ref_type_id, bool with_generic,
@@ -216,6 +216,9 @@
static void OutputVariableTable(JDWP::RefTypeId ref_type_id, JDWP::MethodId id, bool with_generic,
JDWP::ExpandBuf* pReply)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static JDWP::JdwpError GetBytecodes(JDWP::RefTypeId class_id, JDWP::MethodId method_id,
+ std::vector<uint8_t>& bytecodes)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static JDWP::JdwpTag GetFieldBasicTag(JDWP::FieldId field_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc
index 23a3130..14dd2a5 100644
--- a/src/jdwp/jdwp_handler.cc
+++ b/src/jdwp/jdwp_handler.cc
@@ -383,7 +383,7 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
expandBufAdd1(reply, false); // canWatchFieldModification
expandBufAdd1(reply, false); // canWatchFieldAccess
- expandBufAdd1(reply, false); // canGetBytecodes
+ expandBufAdd1(reply, true); // canGetBytecodes
expandBufAdd1(reply, true); // canGetSyntheticAttribute
expandBufAdd1(reply, true); // canGetOwnedMonitorInfo
expandBufAdd1(reply, true); // canGetCurrentContendedMonitor
@@ -828,6 +828,25 @@
return M_VariableTable(state, buf, dataLen, pReply, true);
}
+static JdwpError M_Bytecodes(JdwpState*, const uint8_t* buf, int, ExpandBuf* reply)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ RefTypeId class_id = ReadRefTypeId(&buf);
+ MethodId method_id = ReadMethodId(&buf);
+
+ std::vector<uint8_t> bytecodes;
+ JdwpError rc = Dbg::GetBytecodes(class_id, method_id, bytecodes);
+ if (rc != ERR_NONE) {
+ return rc;
+ }
+
+ expandBufAdd4BE(reply, bytecodes.size());
+ for (size_t i = 0; i < bytecodes.size(); ++i) {
+ expandBufAdd1(reply, bytecodes[i]);
+ }
+
+ return ERR_NONE;
+}
+
/*
* Given an object reference, return the runtime type of the object
* (class or array).
@@ -1680,7 +1699,7 @@
/* Method command set (6) */
{ 6, 1, M_LineTable, "Method.LineTable" },
{ 6, 2, M_VariableTable, "Method.VariableTable" },
- { 6, 3, NULL, "Method.Bytecodes" },
+ { 6, 3, M_Bytecodes, "Method.Bytecodes" },
{ 6, 4, NULL, "Method.IsObsolete" },
{ 6, 5, M_VariableTableWithGeneric, "Method.VariableTableWithGeneric" },