diff options
| author | 2011-11-30 12:11:41 -0800 | |
|---|---|---|
| committer | 2011-11-30 12:11:41 -0800 | |
| commit | 6cb58afbc1cb1cec4220f49febda2177b2c0bfce (patch) | |
| tree | 7c2925682bb3eded2cc608a3aa29765587bcab78 /src | |
| parent | 50e537e4ad78897295c77ec21f4ef9cd45c99528 (diff) | |
| parent | 68fdbd07fc2b8856905e06f3cc945b046c3bfcd3 (diff) | |
Merge "Return values for locals, so "locals" can show them." into dalvik-dev
Diffstat (limited to 'src')
| -rw-r--r-- | src/context.h | 37 | ||||
| -rw-r--r-- | src/debugger.cc | 70 | ||||
| -rw-r--r-- | src/debugger.h | 2 | ||||
| -rw-r--r-- | src/jdwp/jdwp_handler.cc | 11 | ||||
| -rw-r--r-- | src/object.h | 17 | ||||
| -rw-r--r-- | src/thread.cc | 20 |
6 files changed, 85 insertions, 72 deletions
diff --git a/src/context.h b/src/context.h index b4a8b65b77..75eb8ca8d5 100644 --- a/src/context.h +++ b/src/context.h @@ -3,6 +3,7 @@ #ifndef ART_SRC_CONTEXT_H_ #define ART_SRC_CONTEXT_H_ +#include <stddef.h> #include <stdint.h> namespace art { @@ -34,6 +35,42 @@ class Context { virtual void DoLongJump() = 0; }; +class VmapTable { + public: + VmapTable(const uint16_t* table) : table_(table) { + } + + uint16_t operator[](size_t i) const { + return table_[i + 1]; + } + + size_t size() const { + return table_[0]; + } + + // Is register 'reg' in the context or on the stack? + bool IsInContext(size_t reg, uint32_t& vmap_offset) const { + vmap_offset = 0xEBAD0FF5; + // TODO: take advantage of the registers being ordered + for (size_t i = 0; i < size(); ++i) { + // Stop if we find what we are are looking for... + if (table_[i + 1] == reg) { + vmap_offset = i; + return true; + } + // ...or the INVALID_VREG that marks lr. + // TODO: x86? + if (table_[i + 1] == 0xffff) { + break; + } + } + return false; + } + + private: + const uint16_t* table_; +}; + } // namespace art #endif // ART_SRC_CONTEXT_H_ diff --git a/src/debugger.cc b/src/debugger.cc index 1ad8cc262c..976fb89ad6 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 @@ size_t Dbg::GetTagWidth(int tag) { } 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 @@ static uint16_t MangleSlot(uint16_t slot, const char* name) { /* * 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 @@ void Dbg::OutputVariableTable(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId 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 @@ void Dbg::SetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, 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 @@ bool Dbg::GetThisObject(JDWP::ObjectId threadId, JDWP::FrameId frameId, JDWP::Ob 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 @@ void Dbg::GetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot 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; diff --git a/src/debugger.h b/src/debugger.h index 538ebbaf8d..ec20458544 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -171,7 +171,7 @@ public: static void GetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, JDWP::ExpandBuf* pReply); static void SetStaticFieldValue(JDWP::RefTypeId refTypeId, JDWP::FieldId fieldId, uint64_t rawValue, int width); - static char* StringToUtf8(JDWP::ObjectId strId); + static std::string StringToUtf8(JDWP::ObjectId strId); /* * Thread, ThreadGroup, Frame diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc index 3d00930e20..c0a44e0730 100644 --- a/src/jdwp/jdwp_handler.cc +++ b/src/jdwp/jdwp_handler.cc @@ -157,9 +157,7 @@ static JdwpError finishInvoke(JdwpState* state, /* show detailed debug output */ if (resultTag == JT_STRING && exceptObjId == 0) { if (resultValue != 0) { - char* str = Dbg::StringToUtf8(resultValue); - LOG(VERBOSE) << StringPrintf(" string '%s'", str); - free(str); + LOG(VERBOSE) << " string '" << Dbg::StringToUtf8(resultValue) << "'"; } else { LOG(VERBOSE) << " string (null)"; } @@ -875,12 +873,11 @@ static JdwpError handleOR_IsCollected(JdwpState* state, const uint8_t* buf, int */ static JdwpError handleSR_Value(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { ObjectId stringObject = ReadObjectId(&buf); - char* str = Dbg::StringToUtf8(stringObject); + std::string str(Dbg::StringToUtf8(stringObject)); - LOG(VERBOSE) << StringPrintf(" Req for str %llx --> '%s'", stringObject, str); + LOG(VERBOSE) << StringPrintf(" Req for str %llx --> '%s'", stringObject, str.c_str()); - expandBufAddUtf8String(pReply, str); - free(str); + expandBufAddUtf8String(pReply, str.c_str()); return ERR_NONE; } diff --git a/src/object.h b/src/object.h index 91fca63728..85542d2c27 100644 --- a/src/object.h +++ b/src/object.h @@ -808,22 +808,7 @@ class MANAGED Method : public Object { SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table_offset)); } - const uint16_t* GetVmapTable() const { - const uint16_t* vmap = GetVmapTableRaw(); - if (vmap == NULL) { - return vmap; - } - return vmap + 1; - } - - uint16_t GetVmapTableLength() const { - const uint16_t* vmap = GetVmapTableRaw(); - if (vmap == NULL) { - return 0; - } - return *vmap; - } - + // Callers should wrap the uint16_t* in a VmapTable instance for convenient access. const uint16_t* GetVmapTableRaw() const { return GetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(Method, vmap_table_), false); } diff --git a/src/thread.cc b/src/thread.cc index 8dc81c2d1a..b6962f9e1e 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -1431,29 +1431,15 @@ class ReferenceMapVisitor : public Thread::StackVisitor { verifier::PcToReferenceMap map(m); const uint8_t* reg_bitmap = map.FindBitMap(m->ToDexPC(pc)); CHECK(reg_bitmap != NULL); - const uint16_t* vmap = m->GetVmapTable(); + const VmapTable vmap_table(m->GetVmapTableRaw()); // For all dex registers in the bitmap size_t num_regs = std::min(map.RegWidth() * 8, static_cast<size_t>(m->NumRegisters())); for (size_t reg = 0; reg < num_regs; ++reg) { // Does this register hold a reference? if (TestBitmap(reg, reg_bitmap)) { - // Is the reference in the context or on the stack? - bool in_context = false; - uint32_t vmap_offset = 0xEBAD0FF5; - // TODO: take advantage of the registers being ordered - for (int i = 0; i < m->GetVmapTableLength(); i++) { - // stop if we find what we are are looking for or the INVALID_VREG that marks lr - if (vmap[i] == 0xffff) { - break; - } - if (vmap[i] == reg) { - in_context = true; - vmap_offset = i; - break; - } - } + uint32_t vmap_offset; Object* ref; - if (in_context) { + if (vmap_table.IsInContext(reg, vmap_offset)) { // Compute the register we need to load from the context uint32_t spill_mask = m->GetCoreSpillMask(); CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask))); |