Return values for locals, so "locals" can show them.
Also implement a couple of other JDWP commands so jdb can show the length
of arrays and the value of strings.
Change-Id: Ib2a4dc2ee784ee10bdb924e91b0150aa8a96845d
diff --git a/src/debugger.cc b/src/debugger.cc
index 1ad8cc2..976fb89 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -21,6 +21,7 @@
#include <set>
#include "class_linker.h"
+#include "context.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "stack_indirect_reference_table.h"
@@ -551,8 +552,9 @@
}
int Dbg::GetArrayLength(JDWP::ObjectId arrayId) {
- UNIMPLEMENTED(FATAL);
- return 0;
+ Object* o = gRegistry->Get<Object*>(arrayId);
+ Array* a = o->AsArray();
+ return a->GetLength();
}
uint8_t Dbg::GetArrayElementTag(JDWP::ObjectId arrayId) {
@@ -689,17 +691,14 @@
/*
* Reverse Eclipse hack.
*/
-static uint16_t DemangleSlot(uint16_t slot, Method** sp) {
- int newSlot = slot;
+static uint16_t DemangleSlot(uint16_t slot, Frame& f) {
if (slot == kEclipseWorkaroundSlot) {
- newSlot = 0;
+ return 0;
} else if (slot == 0) {
- Frame f;
- f.SetSP(sp);
Method* m = f.GetMethod();
- newSlot = m->NumRegisters() - m->NumIns();
+ return m->NumRegisters() - m->NumIns();
}
- return newSlot;
+ return slot;
}
void Dbg::OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply) {
@@ -811,10 +810,10 @@
static void Callback(void* context, uint16_t slot, uint32_t startAddress, uint32_t endAddress, const char *name, const char *descriptor, const char *signature) {
DebugCallbackContext* pContext = reinterpret_cast<DebugCallbackContext*>(context);
- slot = MangleSlot(slot, name);
-
LOG(VERBOSE) << StringPrintf(" %2d: %d(%d) '%s' '%s' '%s' slot=%d", pContext->numItems, startAddress, endAddress - startAddress, name, descriptor, signature, slot);
+ slot = MangleSlot(slot, name);
+
expandBufAdd8BE(pContext->pReply, startAddress);
expandBufAddUtf8String(pContext->pReply, name);
expandBufAddUtf8String(pContext->pReply, descriptor);
@@ -875,9 +874,9 @@
UNIMPLEMENTED(FATAL);
}
-char* Dbg::StringToUtf8(JDWP::ObjectId strId) {
- UNIMPLEMENTED(FATAL);
- return NULL;
+std::string Dbg::StringToUtf8(JDWP::ObjectId strId) {
+ String* s = gRegistry->Get<String*>(strId);
+ return s->ToModifiedUtf8();
}
Thread* DecodeThread(JDWP::ObjectId threadId) {
@@ -1119,61 +1118,70 @@
void Dbg::GetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag, uint8_t* buf, size_t expectedLen) {
Method** sp = reinterpret_cast<Method**>(frameId);
- slot = DemangleSlot(slot, sp);
+ Frame f;
+ f.SetSP(sp);
+ uint16_t reg = DemangleSlot(slot, f);
+ Method* m = f.GetMethod();
+
+ const VmapTable vmap_table(m->GetVmapTableRaw());
+ uint32_t vmap_offset;
+ if (vmap_table.IsInContext(reg, vmap_offset)) {
+ UNIMPLEMENTED(FATAL) << "don't know how to pull locals from callee save frames: " << vmap_offset;
+ }
switch (tag) {
case JDWP::JT_BOOLEAN:
{
- UNIMPLEMENTED(WARNING) << "get boolean local " << slot;
CHECK_EQ(expectedLen, 1U);
- uint32_t intVal = 0; // framePtr[slot];
+ uint32_t intVal = static_cast<uint32_t>(f.GetVReg(m, reg));
+ LOG(WARNING) << "get boolean local " << reg << " = " << intVal;
JDWP::Set1(buf+1, intVal != 0);
}
break;
case JDWP::JT_BYTE:
{
- UNIMPLEMENTED(WARNING) << "get byte local " << slot;
CHECK_EQ(expectedLen, 1U);
- uint32_t intVal = 0; // framePtr[slot];
+ uint32_t intVal = static_cast<uint32_t>(f.GetVReg(m, reg));
+ LOG(WARNING) << "get byte local " << reg << " = " << intVal;
JDWP::Set1(buf+1, intVal);
}
break;
case JDWP::JT_SHORT:
case JDWP::JT_CHAR:
{
- UNIMPLEMENTED(WARNING) << "get 16-bit local " << slot;
CHECK_EQ(expectedLen, 2U);
- uint32_t intVal = 0; // framePtr[slot];
+ uint32_t intVal = static_cast<uint32_t>(f.GetVReg(m, reg));
+ LOG(WARNING) << "get short/char local " << reg << " = " << intVal;
JDWP::Set2BE(buf+1, intVal);
}
break;
case JDWP::JT_INT:
case JDWP::JT_FLOAT:
{
- UNIMPLEMENTED(WARNING) << "get 32-bit local " << slot;
CHECK_EQ(expectedLen, 4U);
- uint32_t intVal = 0; // framePtr[slot];
+ uint32_t intVal = static_cast<uint32_t>(f.GetVReg(m, reg));
+ LOG(WARNING) << "get int/float local " << reg << " = " << intVal;
JDWP::Set4BE(buf+1, intVal);
}
break;
case JDWP::JT_ARRAY:
{
- UNIMPLEMENTED(WARNING) << "get array local " << slot;
CHECK_EQ(expectedLen, sizeof(JDWP::ObjectId));
- Object* o = NULL; // (Object*)framePtr[slot];
+ Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
+ LOG(WARNING) << "get array local " << reg << " = " << o;
if (o != NULL && !Heap::IsHeapAddress(o)) {
- LOG(FATAL) << "slot " << slot << " expected to hold array: " << o;
+ LOG(FATAL) << "reg " << reg << " expected to hold array: " << o;
}
JDWP::SetObjectId(buf+1, gRegistry->Add(o));
}
break;
case JDWP::JT_OBJECT:
{
- UNIMPLEMENTED(WARNING) << "get object local " << slot;
CHECK_EQ(expectedLen, sizeof(JDWP::ObjectId));
- Object* o = NULL; // (Object*)framePtr[slot];
+ Object* o = reinterpret_cast<Object*>(f.GetVReg(m, reg));
+ LOG(WARNING) << "get object local " << reg << " = " << o;
if (o != NULL && !Heap::IsHeapAddress(o)) {
- LOG(FATAL) << "slot " << slot << " expected to hold object: " << o;
+ LOG(FATAL) << "reg " << reg << " expected to hold object: " << o;
}
tag = TagFromObject(o);
JDWP::SetObjectId(buf+1, gRegistry->Add(o));
@@ -1182,9 +1190,9 @@
case JDWP::JT_DOUBLE:
case JDWP::JT_LONG:
{
- UNIMPLEMENTED(WARNING) << "get 64-bit local " << slot;
+ UNIMPLEMENTED(WARNING) << "get 64-bit local " << reg;
CHECK_EQ(expectedLen, 8U);
- uint64_t longVal = 0; // memcpy(&longVal, &framePtr[slot], 8);
+ uint64_t longVal = 0; // memcpy(&longVal, &framePtr[reg], 8);
JDWP::Set8BE(buf+1, longVal);
}
break;