diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/debugger.cc | 154 | ||||
-rw-r--r-- | src/debugger.h | 33 | ||||
-rw-r--r-- | src/hprof/hprof.cc | 12 | ||||
-rw-r--r-- | src/hprof/hprof.h | 2 | ||||
-rw-r--r-- | src/jdwp/jdwp_bits.h | 16 | ||||
-rw-r--r-- | src/jdwp/jdwp_constants.cc | 47 | ||||
-rw-r--r-- | src/jdwp/jdwp_constants.h | 15 | ||||
-rw-r--r-- | src/jdwp/jdwp_event.cc | 6 | ||||
-rw-r--r-- | src/jdwp/jdwp_event.h | 24 | ||||
-rw-r--r-- | src/jdwp/jdwp_handler.cc | 164 | ||||
-rw-r--r-- | src/object.h | 6 |
11 files changed, 268 insertions, 211 deletions
diff --git a/src/debugger.cc b/src/debugger.cc index b2ea527dea..eede552e59 100644 --- a/src/debugger.cc +++ b/src/debugger.cc @@ -447,18 +447,29 @@ void Dbg::VisitRoots(Heap::RootVisitor* visitor, void* arg) { } std::string Dbg::GetClassDescriptor(JDWP::RefTypeId classId) { - Class* c = gRegistry->Get<Class*>(classId); - return ClassHelper(c).GetDescriptor(); + Object* o = gRegistry->Get<Object*>(classId); + if (o == NULL || !o->IsClass()) { + return StringPrintf("non-class %p", o); // This is only used for debugging output anyway. + } + return ClassHelper(o->AsClass()).GetDescriptor(); } -JDWP::ObjectId Dbg::GetClassObject(JDWP::RefTypeId id) { - UNIMPLEMENTED(FATAL); - return 0; +bool Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& classObjectId) { + Object* o = gRegistry->Get<Object*>(id); + if (o == NULL || !o->IsClass()) { + return false; + } + classObjectId = gRegistry->Add(o); + return true; } -JDWP::RefTypeId Dbg::GetSuperclass(JDWP::RefTypeId id) { - Class* c = gRegistry->Get<Class*>(id); - return gRegistry->Add(c->GetSuperClass()); +bool Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclassId) { + Object* o = gRegistry->Get<Object*>(id); + if (o == NULL || !o->IsClass()) { + return false; + } + superclassId = gRegistry->Add(o->AsClass()->GetSuperClass()); + return true; } JDWP::ObjectId Dbg::GetClassLoader(JDWP::RefTypeId id) { @@ -466,21 +477,32 @@ JDWP::ObjectId Dbg::GetClassLoader(JDWP::RefTypeId id) { return gRegistry->Add(o->GetClass()->GetClassLoader()); } -uint32_t Dbg::GetAccessFlags(JDWP::RefTypeId id) { - Class* c = gRegistry->Get<Class*>(id); - return c->GetAccessFlags() & kAccJavaFlagsMask; +bool Dbg::GetAccessFlags(JDWP::RefTypeId id, uint32_t& access_flags) { + Object* o = gRegistry->Get<Object*>(id); + if (o == NULL || !o->IsClass()) { + return false; + } + access_flags = o->AsClass()->GetAccessFlags() & kAccJavaFlagsMask; + return true; } -bool Dbg::IsInterface(JDWP::RefTypeId classId) { - Class* c = gRegistry->Get<Class*>(classId); - return c->IsInterface(); +bool Dbg::IsInterface(JDWP::RefTypeId classId, bool& is_interface) { + Object* o = gRegistry->Get<Object*>(classId); + if (o == NULL || !o->IsClass()) { + return false; + } + is_interface = o->AsClass()->IsInterface(); + return true; } -void Dbg::GetClassList(uint32_t* pClassCount, JDWP::RefTypeId** pClasses) { +void Dbg::GetClassList(std::vector<JDWP::RefTypeId>& classes) { // Get the complete list of reference classes (i.e. all classes except // the primitive types). // Returns a newly-allocated buffer full of RefTypeId values. struct ClassListCreator { + ClassListCreator(std::vector<JDWP::RefTypeId>& classes) : classes(classes) { + } + static bool Visit(Class* c, void* arg) { return reinterpret_cast<ClassListCreator*>(arg)->Visit(c); } @@ -492,24 +514,24 @@ void Dbg::GetClassList(uint32_t* pClassCount, JDWP::RefTypeId** pClasses) { return true; } - std::vector<JDWP::RefTypeId> classes; + std::vector<JDWP::RefTypeId>& classes; }; - ClassListCreator clc; + ClassListCreator clc(classes); Runtime::Current()->GetClassLinker()->VisitClasses(ClassListCreator::Visit, &clc); - *pClassCount = clc.classes.size(); - *pClasses = new JDWP::RefTypeId[clc.classes.size()]; - for (size_t i = 0; i < clc.classes.size(); ++i) { - (*pClasses)[i] = clc.classes[i]; - } } void Dbg::GetVisibleClassList(JDWP::ObjectId classLoaderId, uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf) { UNIMPLEMENTED(FATAL); } -void Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) { - Class* c = gRegistry->Get<Class*>(classId); +bool Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor) { + Object* o = gRegistry->Get<Object*>(classId); + if (o == NULL || !o->IsClass()) { + return false; + } + + Class* c = o->AsClass(); if (c->IsArrayClass()) { *pStatus = JDWP::CS_VERIFIED | JDWP::CS_PREPARED; *pTypeTag = JDWP::TT_ARRAY; @@ -525,9 +547,10 @@ void Dbg::GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uin if (pDescriptor != NULL) { *pDescriptor = ClassHelper(c).GetDescriptor(); } + return true; } -void Dbg::FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids) { +void Dbg::FindLoadedClassBySignature(const std::string& descriptor, std::vector<JDWP::RefTypeId>& ids) { std::vector<Class*> classes; Runtime::Current()->GetClassLinker()->LookupClasses(descriptor, classes); ids.clear(); @@ -553,17 +576,22 @@ uint8_t Dbg::GetClassObjectType(JDWP::RefTypeId refTypeId) { return 0; } -std::string Dbg::GetSignature(JDWP::RefTypeId refTypeId) { - Class* c = gRegistry->Get<Class*>(refTypeId); - CHECK(c != NULL); - return ClassHelper(c).GetDescriptor(); +bool Dbg::GetSignature(JDWP::RefTypeId refTypeId, std::string& signature) { + Object* o = gRegistry->Get<Object*>(refTypeId); + if (o == NULL || !o->IsClass()) { + return false; + } + signature = ClassHelper(o->AsClass()).GetDescriptor(); + return true; } bool Dbg::GetSourceFile(JDWP::RefTypeId refTypeId, std::string& result) { - Class* c = gRegistry->Get<Class*>(refTypeId); - CHECK(c != NULL); - result = ClassHelper(c).GetSourceFile(); - return result == NULL; + Object* o = gRegistry->Get<Object*>(refTypeId); + if (o == NULL || !o->IsClass()) { + return false; + } + result = ClassHelper(o->AsClass()).GetSourceFile(); + return result != NULL; } uint8_t Dbg::GetObjectTag(JDWP::ObjectId objectId) { @@ -700,25 +728,33 @@ bool Dbg::SetArrayElements(JDWP::ObjectId arrayId, int offset, int count, const return true; } -JDWP::ObjectId Dbg::CreateString(const char* str) { - return gRegistry->Add(String::AllocFromModifiedUtf8(str)); +JDWP::ObjectId Dbg::CreateString(const std::string& str) { + return gRegistry->Add(String::AllocFromModifiedUtf8(str.c_str())); } -JDWP::ObjectId Dbg::CreateObject(JDWP::RefTypeId classId) { - Class* c = gRegistry->Get<Class*>(classId); - return gRegistry->Add(c->AllocObject()); +bool Dbg::CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_object) { + Object* o = gRegistry->Get<Object*>(classId); + if (o == NULL || !o->IsClass()) { + return false; + } + new_object = gRegistry->Add(o->AsClass()->AllocObject()); + return true; } /* * Used by Eclipse's "Display" view to evaluate "new byte[5]" to get "(byte[]) [0, 0, 0, 0, 0]". */ -JDWP::ObjectId Dbg::CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length) { - Class* array_class = gRegistry->Get<Class*>(arrayTypeId); - CHECK(array_class->IsArrayClass()) << PrettyClass(array_class); - return gRegistry->Add(Array::Alloc(array_class, length)); +bool Dbg::CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length, JDWP::ObjectId& new_array) { + Object* o = gRegistry->Get<Object*>(arrayTypeId); + if (o == NULL || !o->IsClass()) { + return false; + } + new_array = gRegistry->Add(Array::Alloc(o->AsClass(), length)); + return true; } bool Dbg::MatchType(JDWP::RefTypeId instClassId, JDWP::RefTypeId classId) { + // TODO: error handling if the RefTypeIds aren't actually Class*s. return gRegistry->Get<Class*>(instClassId)->InstanceOf(gRegistry->Get<Class*>(classId)); } @@ -815,10 +851,13 @@ static uint16_t DemangleSlot(uint16_t slot, Frame& f) { return slot; } -void Dbg::OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) { - Class* c = gRegistry->Get<Class*>(refTypeId); - CHECK(c != NULL); +bool Dbg::OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) { + Object* o = gRegistry->Get<Object*>(refTypeId); + if (o == NULL || !o->IsClass()) { + return false; + } + Class* c = o->AsClass(); size_t instance_field_count = c->NumInstanceFields(); size_t static_field_count = c->NumStaticFields(); @@ -836,12 +875,16 @@ void Dbg::OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool with_generic, JDW } expandBufAdd4BE(pReply, MangleAccessFlags(f->GetAccessFlags())); } + return true; } -void Dbg::OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) { - Class* c = gRegistry->Get<Class*>(refTypeId); - CHECK(c != NULL); +bool Dbg::OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool with_generic, JDWP::ExpandBuf* pReply) { + Object* o = gRegistry->Get<Object*>(refTypeId); + if (o == NULL || !o->IsClass()) { + return false; + } + Class* c = o->AsClass(); size_t direct_method_count = c->NumDirectMethods(); size_t virtual_method_count = c->NumVirtualMethods(); @@ -859,17 +902,21 @@ void Dbg::OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool with_generic, JD } expandBufAdd4BE(pReply, MangleAccessFlags(m->GetAccessFlags())); } + return true; } -void Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply) { - Class* c = gRegistry->Get<Class*>(refTypeId); - CHECK(c != NULL); - ClassHelper kh(c); +bool Dbg::OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply) { + Object* o = gRegistry->Get<Object*>(refTypeId); + if (o == NULL || !o->IsClass()) { + return false; + } + ClassHelper kh(o->AsClass()); size_t interface_count = kh.NumInterfaces(); expandBufAdd4BE(pReply, interface_count); for (size_t i = 0; i < interface_count; ++i) { expandBufAddRefTypeId(pReply, gRegistry->Add(kh.GetInterface(i))); } + return true; } void Dbg::OutputLineTable(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId, JDWP::ExpandBuf* pReply) { @@ -1621,11 +1668,12 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) { // Translate the method through the vtable, unless the debugger wants to suppress it. Method* m = pReq->method_; + LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m); if ((pReq->options_ & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver_ != NULL) { m = pReq->class_->FindVirtualMethodForVirtualOrInterface(pReq->method_); + LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m); } CHECK(m != NULL); - LOG(VERBOSE) << "ExecuteMethod " << PrettyMethod(m); CHECK_EQ(sizeof(jvalue), sizeof(uint64_t)); diff --git a/src/debugger.h b/src/debugger.h index 079863559b..bcc5d79523 100644 --- a/src/debugger.h +++ b/src/debugger.h @@ -37,7 +37,10 @@ struct Thread; * Invoke-during-breakpoint support. */ struct DebugInvokeReq { - DebugInvokeReq() : lock_("a DebugInvokeReq lock"), cond_("a DebugInvokeReq condition variable") { + DebugInvokeReq() + : invoke_needed_(false), + lock_("a DebugInvokeReq lock"), + cond_("a DebugInvokeReq condition variable") { } /* boolean; only set when we're in the tail end of an event handler */ @@ -126,18 +129,18 @@ public: * Class, Object, Array */ static std::string GetClassDescriptor(JDWP::RefTypeId id); - static JDWP::ObjectId GetClassObject(JDWP::RefTypeId id); - static JDWP::RefTypeId GetSuperclass(JDWP::RefTypeId id); + static bool GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId& classObjectId); + static bool GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId& superclassId); static JDWP::ObjectId GetClassLoader(JDWP::RefTypeId id); - static uint32_t GetAccessFlags(JDWP::RefTypeId id); - static bool IsInterface(JDWP::RefTypeId id); - static void GetClassList(uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf); + static bool GetAccessFlags(JDWP::RefTypeId id, uint32_t& access_flags); + static bool IsInterface(JDWP::RefTypeId classId, bool& is_interface); + static void GetClassList(std::vector<JDWP::RefTypeId>& classes); static void GetVisibleClassList(JDWP::ObjectId classLoaderId, uint32_t* pNumClasses, JDWP::RefTypeId** pClassRefBuf); - static void GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor); - static void FindLoadedClassBySignature(const char* descriptor, std::vector<JDWP::RefTypeId>& ids); + static bool GetClassInfo(JDWP::RefTypeId classId, JDWP::JdwpTypeTag* pTypeTag, uint32_t* pStatus, std::string* pDescriptor); + static void FindLoadedClassBySignature(const std::string& descriptor, std::vector<JDWP::RefTypeId>& ids); static void GetObjectType(JDWP::ObjectId objectId, JDWP::JdwpTypeTag* pRefTypeTag, JDWP::RefTypeId* pRefTypeId); static uint8_t GetClassObjectType(JDWP::RefTypeId refTypeId); - static std::string GetSignature(JDWP::RefTypeId refTypeId); + static bool GetSignature(JDWP::RefTypeId refTypeId, std::string& signature); static bool GetSourceFile(JDWP::RefTypeId refTypeId, std::string& source_file); static uint8_t GetObjectTag(JDWP::ObjectId objectId); static size_t GetTagWidth(JDWP::JdwpTag tag); @@ -147,9 +150,9 @@ public: static bool OutputArray(JDWP::ObjectId arrayId, int firstIndex, int count, JDWP::ExpandBuf* pReply); static bool SetArrayElements(JDWP::ObjectId arrayId, int firstIndex, int count, const uint8_t* buf); - static JDWP::ObjectId CreateString(const char* str); - static JDWP::ObjectId CreateObject(JDWP::RefTypeId classId); - static JDWP::ObjectId CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length); + static JDWP::ObjectId CreateString(const std::string& str); + static bool CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_object); + static bool CreateArrayObject(JDWP::RefTypeId arrayTypeId, uint32_t length, JDWP::ObjectId& new_array); static bool MatchType(JDWP::RefTypeId instClassId, JDWP::RefTypeId classId); @@ -157,9 +160,9 @@ public: * Method and Field */ static std::string GetMethodName(JDWP::RefTypeId refTypeId, JDWP::MethodId id); - static void OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply); - static void OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply); - static void OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply); + static bool OutputDeclaredFields(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply); + static bool OutputDeclaredMethods(JDWP::RefTypeId refTypeId, bool withGeneric, JDWP::ExpandBuf* pReply); + static bool OutputDeclaredInterfaces(JDWP::RefTypeId refTypeId, JDWP::ExpandBuf* pReply); static void OutputLineTable(JDWP::RefTypeId refTypeId, JDWP::MethodId methodId, JDWP::ExpandBuf* pReply); static void OutputVariableTable(JDWP::RefTypeId refTypeId, JDWP::MethodId id, bool withGeneric, JDWP::ExpandBuf* pReply); diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc index d2134e0148..8dadfdf14a 100644 --- a/src/hprof/hprof.cc +++ b/src/hprof/hprof.cc @@ -59,7 +59,7 @@ Hprof::Hprof(const char* outputFileName, int fd, bool writeHeader, bool directTo current_heap_(HPROF_HEAP_DEFAULT), objects_in_segment_(0), direct_to_ddms_(0), - file_name_(NULL), + file_name_(outputFileName), file_data_ptr_(NULL), file_data_size_(0), mem_fp_(NULL), @@ -76,7 +76,6 @@ Hprof::Hprof(const char* outputFileName, int fd, bool writeHeader, bool directTo } direct_to_ddms_ = directToDdms; - file_name_ = strdup(outputFileName); mem_fp_ = fp; fd_ = fd; @@ -535,11 +534,11 @@ bool Hprof::Finish() { FlushCurrentRecord(); // create a new Hprof for the start of the file (as opposed to this, which is the tail) - Hprof headCtx(file_name_, fd_, true, direct_to_ddms_); + Hprof headCtx(file_name_.c_str(), fd_, true, direct_to_ddms_); headCtx.classes_ = classes_; headCtx.strings_ = strings_; - LOG(INFO) << StringPrintf("hprof: dumping heap strings to \"%s\".", file_name_); + LOG(INFO) << StringPrintf("hprof: dumping heap strings to \"%s\".", file_name_.c_str()); headCtx.DumpStrings(); headCtx.DumpClasses(); @@ -575,9 +574,9 @@ bool Hprof::Finish() { // continue to fail-handler below } } else { - outFd = open(file_name_, O_WRONLY|O_CREAT|O_TRUNC, 0644); + outFd = open(file_name_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644); if (outFd < 0) { - LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_, strerror(errno)); + LOG(ERROR) << StringPrintf("can't open %s: %s", headCtx.file_name_.c_str(), strerror(errno)); // continue to fail-handler below } } @@ -607,7 +606,6 @@ Hprof::~Hprof() { fclose(mem_fp_); } free(current_record_.body_); - free(file_name_); free(file_data_ptr_); } diff --git a/src/hprof/hprof.h b/src/hprof/hprof.h index e999dced54..7c1180e3fe 100644 --- a/src/hprof/hprof.h +++ b/src/hprof/hprof.h @@ -212,7 +212,7 @@ class Hprof { // Otherwise, "file_name_" must be valid, though if "fd" >= 0 it will // only be used for debug messages. bool direct_to_ddms_; - char* file_name_; + std::string file_name_; char* file_data_ptr_; // for open_memstream size_t file_data_size_; // for open_memstream FILE *mem_fp_; diff --git a/src/jdwp/jdwp_bits.h b/src/jdwp/jdwp_bits.h index 344d2de9f3..5536c52f69 100644 --- a/src/jdwp/jdwp_bits.h +++ b/src/jdwp/jdwp_bits.h @@ -67,19 +67,15 @@ static inline uint64_t Read8BE(unsigned char const** ppSrc) { } /* - * Read a UTF-8 string into newly-allocated storage, and null-terminate it. - * - * Returns the string and its length. (The latter is probably unnecessary - * for the way we're using UTF8.) + * Reads a UTF-8 string into a std::string. */ -static inline char* ReadNewUtf8String(unsigned char const** ppSrc, size_t* pLength) { +static inline std::string ReadNewUtf8String(unsigned char const** ppSrc) { uint32_t length = Read4BE(ppSrc); - char* buf = (char*) malloc(length+1); - memcpy(buf, *ppSrc, length); - buf[length] = '\0'; + std::string s; + s.resize(length); + memcpy(&s[0], *ppSrc, length); (*ppSrc) += length; - *pLength = length; - return buf; + return s; } static inline void Append1BE(std::vector<uint8_t>& bytes, uint8_t value) { diff --git a/src/jdwp/jdwp_constants.cc b/src/jdwp/jdwp_constants.cc index 7110eed2ce..ab4e841f83 100644 --- a/src/jdwp/jdwp_constants.cc +++ b/src/jdwp/jdwp_constants.cc @@ -40,6 +40,8 @@ const char* ErrorStr(JdwpError error) { return "THREAD_NOT_SUSPENDED"; case ERR_THREAD_SUSPENDED: return "THREAD_SUSPENDED"; + case ERR_THREAD_NOT_ALIVE: + return "THREAD_NOT_ALIVE"; case ERR_INVALID_OBJECT: return "INVALID_OBJEC"; case ERR_INVALID_CLASS: @@ -157,7 +159,7 @@ const char* EventKindStr(JdwpEventKind kind) { case EK_EXCEPTION: return "EXCEPTION"; case EK_USER_DEFINED: return "USER_DEFINED"; case EK_THREAD_START: return "THREAD_START"; - /*case EK_THREAD_END: return "THREAD_END";*/ + case EK_THREAD_DEATH: return "THREAD_DEATH"; case EK_CLASS_PREPARE: return "CLASS_PREPARE"; case EK_CLASS_UNLOAD: return "CLASS_UNLOAD"; case EK_CLASS_LOAD: return "CLASS_LOAD"; @@ -166,11 +168,14 @@ const char* EventKindStr(JdwpEventKind kind) { case EK_EXCEPTION_CATCH: return "EXCEPTION_CATCH"; case EK_METHOD_ENTRY: return "METHOD_ENTRY"; case EK_METHOD_EXIT: return "METHOD_EXIT"; - case EK_VM_INIT: return "VM_INIT"; + case EK_METHOD_EXIT_WITH_RETURN_VALUE: return "METHOD_EXIT_WITH_RETURN_VALUE"; + case EK_MONITOR_CONTENDED_ENTER: return "MONITOR_CONTENDED_ENTER"; + case EK_MONITOR_CONTENDED_ENTERED: return "MONITOR_CONTENDED_ENTERED"; + case EK_MONITOR_WAIT: return "MONITOR_WAIT"; + case EK_MONITOR_WAITED: return "MONITOR_WAITED"; + case EK_VM_START: return "VM_START"; case EK_VM_DEATH: return "VM_DEATH"; case EK_VM_DISCONNECTED: return "VM_DISCONNECTED"; - /*case EK_VM_START: return "VM_START";*/ - case EK_THREAD_DEATH: return "THREAD_DEATH"; default: return "?UNKNOWN?"; } } @@ -179,24 +184,24 @@ std::ostream& operator<<(std::ostream& os, const JdwpEventKind& value) { return os; } -const char* ModKindStr(JdwpModKind kind) { - switch (kind) { - case MK_COUNT: return "COUNT"; - case MK_CONDITIONAL: return "CONDITIONAL"; - case MK_THREAD_ONLY: return "THREAD_ONLY"; - case MK_CLASS_ONLY: return "CLASS_ONLY"; - case MK_CLASS_MATCH: return "CLASS_MATCH"; - case MK_CLASS_EXCLUDE: return "CLASS_EXCLUDE"; - case MK_LOCATION_ONLY: return "LOCATION_ONLY"; - case MK_EXCEPTION_ONLY: return "EXCEPTION_ONLY"; - case MK_FIELD_ONLY: return "FIELD_ONLY"; - case MK_STEP: return "STEP"; - case MK_INSTANCE_ONLY: return "INSTANCE_ONLY"; - default: return "?UNKNOWN?"; - } -} std::ostream& operator<<(std::ostream& os, const JdwpModKind& value) { - os << ModKindStr(value); + switch (value) { + case MK_COUNT: os << "COUNT"; break; + case MK_CONDITIONAL: os << "CONDITIONAL"; break; + case MK_THREAD_ONLY: os << "THREAD_ONLY"; break; + case MK_CLASS_ONLY: os << "CLASS_ONLY"; break; + case MK_CLASS_MATCH: os << "CLASS_MATCH"; break; + case MK_CLASS_EXCLUDE: os << "CLASS_EXCLUDE"; break; + case MK_LOCATION_ONLY: os << "LOCATION_ONLY"; break; + case MK_EXCEPTION_ONLY: os << "EXCEPTION_ONLY"; break; + case MK_FIELD_ONLY: os << "FIELD_ONLY"; break; + case MK_STEP: os << "STEP"; break; + case MK_INSTANCE_ONLY: os << "INSTANCE_ONLY"; break; + case MK_SOURCE_NAME_MATCH: os << "SOURCE_NAME_MATCH"; break; + default: + os << "JdwpModKind[" << static_cast<int>(value) << "]"; + break; + } return os; } diff --git a/src/jdwp/jdwp_constants.h b/src/jdwp/jdwp_constants.h index 6d550f2551..14dc6cfa6a 100644 --- a/src/jdwp/jdwp_constants.h +++ b/src/jdwp/jdwp_constants.h @@ -35,6 +35,7 @@ enum JdwpError { ERR_INVALID_PRIORITY = 12, ERR_THREAD_NOT_SUSPENDED = 13, ERR_THREAD_SUSPENDED = 14, + ERR_THREAD_NOT_ALIVE = 15, ERR_INVALID_OBJECT = 20, ERR_INVALID_CLASS = 21, ERR_CLASS_NOT_PREPARED = 22, @@ -110,7 +111,7 @@ enum JdwpEventKind { EK_EXCEPTION = 4, EK_USER_DEFINED = 5, EK_THREAD_START = 6, - EK_THREAD_END = 7, + EK_THREAD_DEATH = 7, // Formerly known as THREAD_END. EK_CLASS_PREPARE = 8, EK_CLASS_UNLOAD = 9, EK_CLASS_LOAD = 10, @@ -119,11 +120,14 @@ enum JdwpEventKind { EK_EXCEPTION_CATCH = 30, EK_METHOD_ENTRY = 40, EK_METHOD_EXIT = 41, - EK_VM_INIT = 90, + EK_METHOD_EXIT_WITH_RETURN_VALUE = 42, + EK_MONITOR_CONTENDED_ENTER = 43, + EK_MONITOR_CONTENDED_ENTERED = 44, + EK_MONITOR_WAIT = 45, + EK_MONITOR_WAITED = 46, + EK_VM_START = 90, // Formerly known as VM_INIT. EK_VM_DEATH = 99, - EK_VM_DISCONNECTED = 100, /* "Never sent across JDWP */ - EK_VM_START = EK_VM_INIT, - EK_THREAD_DEATH = EK_THREAD_END, + EK_VM_DISCONNECTED = 100, // "Never sent across JDWP". }; std::ostream& operator<<(std::ostream& os, const JdwpEventKind& value); @@ -142,6 +146,7 @@ enum JdwpModKind { MK_FIELD_ONLY = 9, MK_STEP = 10, MK_INSTANCE_ONLY = 11, + MK_SOURCE_NAME_MATCH = 12, // Since Java 6. }; std::ostream& operator<<(std::ostream& os, const JdwpModKind& value); diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc index 22d3c248e5..a405c9b4ff 100644 --- a/src/jdwp/jdwp_event.cc +++ b/src/jdwp/jdwp_event.cc @@ -128,7 +128,7 @@ static void dumpEvent(const JdwpEvent* pEvent) { for (int i = 0; i < pEvent->modCount; i++) { const JdwpEventMod* pMod = &pEvent->mods[i]; - LOG(INFO) << " " << static_cast<JdwpModKind>(pMod->modKind); + LOG(INFO) << " " << pMod->modKind; /* TODO - show details */ } } @@ -451,8 +451,7 @@ static bool ModsMatch(JdwpEvent* pEvent, ModBasket* basket) { } break; default: - LOG(ERROR) << "unhandled mod kind " << pMod->modKind; - CHECK(false); + LOG(FATAL) << "unknown mod kind " << pMod->modKind; break; } } @@ -544,7 +543,6 @@ void JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspendPolicy) { SetWaitForEventThread(Dbg::GetThreadSelfId()); /* leave pReq->invoke_needed_ raised so we can check reentrancy */ - LOG(VERBOSE) << "invoking method..."; Dbg::ExecuteMethod(pReq); pReq->error = ERR_NONE; diff --git a/src/jdwp/jdwp_event.h b/src/jdwp/jdwp_event.h index 5f18595024..e8f633f2a5 100644 --- a/src/jdwp/jdwp_event.h +++ b/src/jdwp/jdwp_event.h @@ -30,54 +30,54 @@ namespace JDWP { * Event modifiers. A JdwpEvent may have zero or more of these. */ union JdwpEventMod { - uint8_t modKind; /* JdwpModKind */ + JdwpModKind modKind; struct { - uint8_t modKind; + JdwpModKind modKind; int count; } count; struct { - uint8_t modKind; + JdwpModKind modKind; uint32_t exprId; } conditional; struct { - uint8_t modKind; + JdwpModKind modKind; ObjectId threadId; } threadOnly; struct { - uint8_t modKind; + JdwpModKind modKind; RefTypeId refTypeId; } classOnly; struct { - uint8_t modKind; + JdwpModKind modKind; char* classPattern; } classMatch; struct { - uint8_t modKind; + JdwpModKind modKind; char* classPattern; } classExclude; struct { - uint8_t modKind; + JdwpModKind modKind; JdwpLocation loc; } locationOnly; struct { - uint8_t modKind; + JdwpModKind modKind; uint8_t caught; uint8_t uncaught; RefTypeId refTypeId; } exceptionOnly; struct { - uint8_t modKind; + JdwpModKind modKind; RefTypeId refTypeId; FieldId fieldId; } fieldOnly; struct { - uint8_t modKind; + JdwpModKind modKind; ObjectId threadId; int size; /* JdwpStepSize */ int depth; /* JdwpStepDepth */ } step; struct { - uint8_t modKind; + JdwpModKind modKind; ObjectId objectId; } instanceOnly; }; diff --git a/src/jdwp/jdwp_handler.cc b/src/jdwp/jdwp_handler.cc index a11c8056f9..9f23af1a62 100644 --- a/src/jdwp/jdwp_handler.cc +++ b/src/jdwp/jdwp_handler.cc @@ -194,8 +194,7 @@ static JdwpError handleVM_Version(JdwpState* state, const uint8_t* buf, int data * been loaded by multiple class loaders. */ static JdwpError handleVM_ClassesBySignature(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { - size_t strLen; - char* classDescriptor = ReadNewUtf8String(&buf, &strLen); + std::string classDescriptor(ReadNewUtf8String(&buf)); LOG(VERBOSE) << " Req for class by signature '" << classDescriptor << "'"; std::vector<RefTypeId> ids; @@ -207,15 +206,15 @@ static JdwpError handleVM_ClassesBySignature(JdwpState* state, const uint8_t* bu // Get class vs. interface and status flags. JDWP::JdwpTypeTag typeTag; uint32_t status; - Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL); + if (!Dbg::GetClassInfo(ids[i], &typeTag, &status, NULL)) { + return ERR_INVALID_CLASS; + } expandBufAdd1(pReply, typeTag); expandBufAddRefTypeId(pReply, ids[i]); expandBufAdd4BE(pReply, status); } - free(classDescriptor); - return ERR_NONE; } @@ -324,16 +323,12 @@ static JdwpError handleVM_Exit(JdwpState* state, const uint8_t* buf, int dataLen * string "java.util.Arrays".) */ static JdwpError handleVM_CreateString(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { - size_t strLen; - char* str = ReadNewUtf8String(&buf, &strLen); - + std::string str(ReadNewUtf8String(&buf)); LOG(VERBOSE) << " Req to create string '" << str << "'"; - ObjectId stringId = Dbg::CreateString(str); if (stringId == 0) { return ERR_OUT_OF_MEMORY; } - expandBufAddObjectId(pReply, stringId); return ERR_NONE; } @@ -425,30 +420,27 @@ static JdwpError handleVM_CapabilitiesNew(JdwpState* state, const uint8_t* buf, * Cough up the complete list of classes. */ static JdwpError handleVM_AllClassesWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { - uint32_t numClasses = 0; - RefTypeId* classRefBuf = NULL; + std::vector<JDWP::RefTypeId> classes; + Dbg::GetClassList(classes); - Dbg::GetClassList(&numClasses, &classRefBuf); + expandBufAdd4BE(pReply, classes.size()); - expandBufAdd4BE(pReply, numClasses); - - for (uint32_t i = 0; i < numClasses; i++) { + for (size_t i = 0; i < classes.size(); ++i) { static const char genericSignature[1] = ""; JDWP::JdwpTypeTag refTypeTag; std::string descriptor; uint32_t status; - - Dbg::GetClassInfo(classRefBuf[i], &refTypeTag, &status, &descriptor); + if (!Dbg::GetClassInfo(classes[i], &refTypeTag, &status, &descriptor)) { + return ERR_INVALID_CLASS; + } expandBufAdd1(pReply, refTypeTag); - expandBufAddRefTypeId(pReply, classRefBuf[i]); + expandBufAddRefTypeId(pReply, classes[i]); expandBufAddUtf8String(pReply, descriptor); expandBufAddUtf8String(pReply, genericSignature); expandBufAdd4BE(pReply, status); } - free(classRefBuf); - return ERR_NONE; } @@ -460,9 +452,11 @@ static JdwpError handleRT_Signature(JdwpState* state, const uint8_t* buf, int da RefTypeId refTypeId = ReadRefTypeId(&buf); LOG(VERBOSE) << StringPrintf(" Req for signature of refTypeId=0x%llx", refTypeId); - std::string signature(Dbg::GetSignature(refTypeId)); + std::string signature; + if (!Dbg::GetSignature(refTypeId, signature)) { + return ERR_INVALID_CLASS; + } expandBufAddUtf8String(pReply, signature); - return ERR_NONE; } @@ -471,8 +465,11 @@ static JdwpError handleRT_Signature(JdwpState* state, const uint8_t* buf, int da */ static JdwpError handleRT_Modifiers(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId refTypeId = ReadRefTypeId(&buf); - uint32_t modBits = Dbg::GetAccessFlags(refTypeId); - expandBufAdd4BE(pReply, modBits); + uint32_t access_flags; + if (!Dbg::GetAccessFlags(refTypeId, access_flags)) { + return ERR_INVALID_CLASS; + } + expandBufAdd4BE(pReply, access_flags); return ERR_NONE; } @@ -512,11 +509,11 @@ static JdwpError handleRT_SourceFile(JdwpState* state, const uint8_t* buf, int d */ static JdwpError handleRT_Status(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId refTypeId = ReadRefTypeId(&buf); - - /* get status flags */ JDWP::JdwpTypeTag typeTag; uint32_t status; - Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL); + if (!Dbg::GetClassInfo(refTypeId, &typeTag, &status, NULL)) { + return ERR_INVALID_CLASS; + } expandBufAdd4BE(pReply, status); return ERR_NONE; } @@ -526,12 +523,8 @@ static JdwpError handleRT_Status(JdwpState* state, const uint8_t* buf, int dataL */ static JdwpError handleRT_Interfaces(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId refTypeId = ReadRefTypeId(&buf); - LOG(VERBOSE) << StringPrintf(" Req for interfaces in %llx (%s)", refTypeId, Dbg::GetClassDescriptor(refTypeId).c_str()); - - Dbg::OutputDeclaredInterfaces(refTypeId, pReply); - - return ERR_NONE; + return Dbg::OutputDeclaredInterfaces(refTypeId, pReply) ? ERR_NONE : ERR_INVALID_CLASS; } /* @@ -539,12 +532,12 @@ static JdwpError handleRT_Interfaces(JdwpState* state, const uint8_t* buf, int d */ static JdwpError handleRT_ClassObject(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId refTypeId = ReadRefTypeId(&buf); - ObjectId classObjId = Dbg::GetClassObject(refTypeId); - - LOG(VERBOSE) << StringPrintf(" RefTypeId %llx -> ObjectId %llx", refTypeId, classObjId); - - expandBufAddObjectId(pReply, classObjId); - + ObjectId classObjectId; + if (!Dbg::GetClassObject(refTypeId, classObjectId)) { + return ERR_INVALID_CLASS; + } + LOG(VERBOSE) << StringPrintf(" RefTypeId %llx -> ObjectId %llx", refTypeId, classObjectId); + expandBufAddObjectId(pReply, classObjectId); return ERR_NONE; } @@ -567,8 +560,8 @@ static JdwpError handleRT_SignatureWithGeneric(JdwpState* state, const uint8_t* RefTypeId refTypeId = ReadRefTypeId(&buf); LOG(VERBOSE) << StringPrintf(" Req for signature of refTypeId=0x%llx", refTypeId); - std::string signature(Dbg::GetSignature(refTypeId)); - if (signature != NULL) { + std::string signature; + if (Dbg::GetSignature(refTypeId, signature)) { expandBufAddUtf8String(pReply, signature); } else { LOG(WARNING) << StringPrintf("No signature for refTypeId=0x%llx", refTypeId); @@ -591,16 +584,27 @@ static JdwpError handleRT_ClassLoader(JdwpState* state, const uint8_t* buf, int return ERR_NONE; } +static std::string Describe(const RefTypeId& refTypeId) { + std::string signature("unknown"); + Dbg::GetSignature(refTypeId, signature); + return StringPrintf("refTypeId=0x%llx (%s)", refTypeId, signature.c_str()); +} + /* * Given a referenceTypeId, return a block of stuff that describes the * fields declared by a class. */ static JdwpError handleRT_FieldsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId refTypeId = ReadRefTypeId(&buf); - LOG(VERBOSE) << StringPrintf(" Req for fields in refTypeId=0x%llx", refTypeId); - LOG(VERBOSE) << StringPrintf(" --> '%s'", Dbg::GetSignature(refTypeId).c_str()); - Dbg::OutputDeclaredFields(refTypeId, true, pReply); - return ERR_NONE; + LOG(VERBOSE) << " Req for fields in " << Describe(refTypeId); + return Dbg::OutputDeclaredFields(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS; +} + +// Obsolete equivalent of FieldsWithGeneric, without the generic type information. +static JdwpError handleRT_Fields(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { + RefTypeId refTypeId = ReadRefTypeId(&buf); + LOG(VERBOSE) << " Req for fields in " << Describe(refTypeId); + return Dbg::OutputDeclaredFields(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS; } /* @@ -609,13 +613,15 @@ static JdwpError handleRT_FieldsWithGeneric(JdwpState* state, const uint8_t* buf */ static JdwpError handleRT_MethodsWithGeneric(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId refTypeId = ReadRefTypeId(&buf); + LOG(VERBOSE) << " Req for methods in " << Describe(refTypeId); + return Dbg::OutputDeclaredMethods(refTypeId, true, pReply) ? ERR_NONE : ERR_INVALID_CLASS; +} - LOG(VERBOSE) << StringPrintf(" Req for methods in refTypeId=0x%llx", refTypeId); - LOG(VERBOSE) << StringPrintf(" --> '%s'", Dbg::GetSignature(refTypeId).c_str()); - - Dbg::OutputDeclaredMethods(refTypeId, true, pReply); - - return ERR_NONE; +// Obsolete equivalent of MethodsWithGeneric, without the generic type information. +static JdwpError handleRT_Methods(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { + RefTypeId refTypeId = ReadRefTypeId(&buf); + LOG(VERBOSE) << " Req for methods in " << Describe(refTypeId); + return Dbg::OutputDeclaredMethods(refTypeId, false, pReply) ? ERR_NONE : ERR_INVALID_CLASS; } /* @@ -623,11 +629,11 @@ static JdwpError handleRT_MethodsWithGeneric(JdwpState* state, const uint8_t* bu */ static JdwpError handleCT_Superclass(JdwpState* state, const uint8_t* buf, int dataLen, ExpandBuf* pReply) { RefTypeId classId = ReadRefTypeId(&buf); - - RefTypeId superClassId = Dbg::GetSuperclass(classId); - + RefTypeId superClassId; + if (!Dbg::GetSuperclass(classId, superClassId)) { + return ERR_INVALID_CLASS; + } expandBufAddRefTypeId(pReply, superClassId); - return ERR_NONE; } @@ -680,7 +686,10 @@ static JdwpError handleCT_NewInstance(JdwpState* state, const uint8_t* buf, int MethodId methodId = ReadMethodId(&buf); LOG(VERBOSE) << "Creating instance of " << Dbg::GetClassDescriptor(classId); - ObjectId objectId = Dbg::CreateObject(classId); + ObjectId objectId; + if (!Dbg::CreateObject(classId, objectId)) { + return ERR_INVALID_CLASS; + } if (objectId == 0) { return ERR_OUT_OF_MEMORY; } @@ -695,7 +704,10 @@ static JdwpError handleAT_newInstance(JdwpState* state, const uint8_t* buf, int uint32_t length = Read4BE(&buf); LOG(VERBOSE) << StringPrintf("Creating array %s[%u]", Dbg::GetClassDescriptor(arrayTypeId).c_str(), length); - ObjectId objectId = Dbg::CreateArrayObject(arrayTypeId, length); + ObjectId objectId; + if (!Dbg::CreateArrayObject(arrayTypeId, length, objectId)) { + return ERR_INVALID_CLASS; + } if (objectId == 0) { return ERR_OUT_OF_MEMORY; } @@ -860,7 +872,7 @@ static JdwpError handleSR_Value(JdwpState* state, const uint8_t* buf, int dataLe ObjectId stringObject = ReadObjectId(&buf); std::string str(Dbg::StringToUtf8(stringObject)); - LOG(VERBOSE) << StringPrintf(" Req for str %llx --> '%s'", stringObject, str.c_str()); + LOG(VERBOSE) << StringPrintf(" Req for str %llx --> '%s'", stringObject, PrintableString(str).c_str()); expandBufAddUtf8String(pReply, str); @@ -1248,7 +1260,7 @@ static JdwpError handleER_Set(JdwpState* state, const uint8_t* buf, int dataLen, * mods in JDWP doc). */ for (uint32_t idx = 0; idx < modifierCount; idx++) { - uint8_t modKind = Read1(&buf); + JdwpModKind modKind = static_cast<JdwpModKind>(Read1(&buf)); pEvent->mods[idx].modKind = modKind; @@ -1286,25 +1298,17 @@ static JdwpError handleER_Set(JdwpState* state, const uint8_t* buf, int dataLen, break; case MK_CLASS_MATCH: /* restrict events to matching classes */ { - char* pattern; - size_t strLen; - - pattern = ReadNewUtf8String(&buf, &strLen); - LOG(VERBOSE) << StringPrintf(" ClassMatch: '%s'", pattern); + std::string pattern(ReadNewUtf8String(&buf)); + LOG(VERBOSE) << StringPrintf(" ClassMatch: '%s'", pattern.c_str()); /* pattern is "java.foo.*", we want "java/foo/ *" */ - pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern); - free(pattern); + pEvent->mods[idx].classMatch.classPattern = dvmDotToSlash(pattern.c_str()); } break; case MK_CLASS_EXCLUDE: /* restrict events to non-matching classes */ { - char* pattern; - size_t strLen; - - pattern = ReadNewUtf8String(&buf, &strLen); - LOG(VERBOSE) << StringPrintf(" ClassExclude: '%s'", pattern); - pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern); - free(pattern); + std::string pattern(ReadNewUtf8String(&buf)); + LOG(VERBOSE) << StringPrintf(" ClassExclude: '%s'", pattern.c_str()); + pEvent->mods[idx].classExclude.classPattern = dvmDotToSlash(pattern.c_str()); } break; case MK_LOCATION_ONLY: /* restrict certain events based on loc */ @@ -1496,12 +1500,12 @@ static JdwpError handleCOR_ReflectedType(JdwpState* state, const uint8_t* buf, i LOG(VERBOSE) << StringPrintf(" Req for refTypeId for class=%llx (%s)", classObjectId, Dbg::GetClassDescriptor(classObjectId).c_str()); - /* just hand the type back to them */ - if (Dbg::IsInterface(classObjectId)) { - expandBufAdd1(pReply, TT_INTERFACE); - } else { - expandBufAdd1(pReply, TT_CLASS); + bool is_interface; + if (!Dbg::IsInterface(classObjectId, is_interface)) { + return ERR_INVALID_CLASS; } + + expandBufAdd1(pReply, is_interface ? TT_INTERFACE : TT_CLASS); expandBufAddRefTypeId(pReply, classObjectId); return ERR_NONE; @@ -1587,8 +1591,8 @@ static const JdwpHandlerMap gHandlerMap[] = { { 2, 1, handleRT_Signature, "ReferenceType.Signature" }, { 2, 2, handleRT_ClassLoader, "ReferenceType.ClassLoader" }, { 2, 3, handleRT_Modifiers, "ReferenceType.Modifiers" }, - { 2, 4, NULL, "ReferenceType.Fields" }, - { 2, 5, NULL, "ReferenceType.Methods" }, + { 2, 4, handleRT_Fields, "ReferenceType.Fields" }, + { 2, 5, handleRT_Methods, "ReferenceType.Methods" }, { 2, 6, handleRT_GetValues, "ReferenceType.GetValues" }, { 2, 7, handleRT_SourceFile, "ReferenceType.SourceFile" }, { 2, 8, NULL, "ReferenceType.NestedTypes" }, diff --git a/src/object.h b/src/object.h index ddba9db290..eb379876e1 100644 --- a/src/object.h +++ b/src/object.h @@ -1370,7 +1370,7 @@ class MANAGED Class : public StaticStorageBase { Class* GetSuperClass() const { // Can only get super class for loaded classes (hack for when runtime is // initializing) - DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()); + DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded(); return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false); } @@ -1908,8 +1908,8 @@ inline void Field::SetDeclaringClass(Class *new_declaring_class) { inline Class* Method::GetDeclaringClass() const { Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), false); - DCHECK(result != NULL); - DCHECK(result->IsIdxLoaded() || result->IsErroneous()); + DCHECK(result != NULL) << this; + DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this; return result; } |