Index: cmake/LLDBDependencies.cmake =================================================================== --- cmake/LLDBDependencies.cmake +++ cmake/LLDBDependencies.cmake @@ -23,6 +23,7 @@ lldbPluginCPlusPlusLanguage lldbPluginGoLanguage + lldbPluginJavaLanguage lldbPluginObjCLanguage lldbPluginObjCPlusPlusLanguage @@ -50,6 +51,7 @@ lldbPluginAppleObjCRuntime lldbPluginRenderScriptRuntime lldbPluginLanguageRuntimeGo + lldbPluginLanguageRuntimeJava lldbPluginCXXItaniumABI lldbPluginABIMacOSX_arm lldbPluginABIMacOSX_arm64 Index: include/lldb/Symbol/JavaASTContext.h =================================================================== --- /dev/null +++ include/lldb/Symbol/JavaASTContext.h @@ -0,0 +1,385 @@ +//===-- JavaASTContext.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_JavaASTContext_h_ +#define liblldb_JavaASTContext_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Symbol/TypeSystem.h" + +namespace lldb_private +{ + +class JavaASTContext : public TypeSystem +{ +public: + class JavaType; + typedef std::map> JavaTypeMap; + + JavaASTContext(const ArchSpec &arch); + ~JavaASTContext() override; + + //------------------------------------------------------------------ + // PluginInterface functions + //------------------------------------------------------------------ + ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + static ConstString + GetPluginNameStatic(); + + static lldb::TypeSystemSP + CreateInstance(lldb::LanguageType language, Module *module, Target *target); + + static void + EnumerateSupportedLanguages(std::set &languages_for_types, + std::set &languages_for_expressions); + + static void + Initialize(); + + static void + Terminate(); + + DWARFASTParser * + GetDWARFParser() override; + + uint32_t + GetPointerByteSize() override; + + //---------------------------------------------------------------------- + // CompilerDecl functions + //---------------------------------------------------------------------- + ConstString + DeclGetName(void *opaque_decl) override; + + lldb::VariableSP + DeclGetVariable(void *opaque_decl) override; + + void + DeclLinkToObject(void *opaque_decl, std::shared_ptr object) override; + + //---------------------------------------------------------------------- + // CompilerDeclContext functions + //---------------------------------------------------------------------- + + std::vector + DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) override; + + bool + DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override; + + ConstString + DeclContextGetName(void *opaque_decl_ctx) override; + + bool + DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, bool *is_instance_method_ptr, + ConstString *language_object_name_ptr) override; + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + bool + IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, + bool *is_incomplete) override; + + bool + IsAggregateType(lldb::opaque_compiler_type_t type) override; + + bool + IsCharType(lldb::opaque_compiler_type_t type) override; + + bool + IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) override; + + bool + IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr = nullptr) override; + + size_t + GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) override; + + bool + IsFunctionPointerType(lldb::opaque_compiler_type_t type) override; + + bool + IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) override; + + bool + IsPossibleDynamicType(lldb::opaque_compiler_type_t type, CompilerType *target_type, bool check_cplusplus, + bool check_objc) override; + + bool + IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type = nullptr) override; + + bool + IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type = nullptr, + bool *is_rvalue = nullptr) override; + + bool + IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type = nullptr) override; + + bool + IsScalarType(lldb::opaque_compiler_type_t type) override; + + bool + IsVoidType(lldb::opaque_compiler_type_t type) override; + + bool + IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) override; + + bool + IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override; + + bool + IsTypedefType(lldb::opaque_compiler_type_t type) override; + + bool + IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) override; + + bool + IsPolymorphicClass(lldb::opaque_compiler_type_t type) override; + + bool + IsCompleteType(lldb::opaque_compiler_type_t type) override; + + bool + IsConst(lldb::opaque_compiler_type_t type) override; + + bool + IsBeingDefined(lldb::opaque_compiler_type_t type) override; + + bool + IsDefined(lldb::opaque_compiler_type_t type) override; + + uint32_t + IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) override; + + bool + SupportsLanguage(lldb::LanguageType language) override; + + bool + GetCompleteType(lldb::opaque_compiler_type_t type) override; + + ConstString + GetTypeName(lldb::opaque_compiler_type_t type) override; + + uint32_t + GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type = nullptr) override; + + lldb::TypeClass + GetTypeClass(lldb::opaque_compiler_type_t type) override; + + lldb::LanguageType + GetMinimumLanguage(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride = nullptr) override; + + CompilerType + GetPointeeType(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetPointerType(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetCanonicalType(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetNonReferenceType(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetTypedefedType(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetBasicTypeFromAST(lldb::BasicType basic_type) override; + + CompilerType + GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) override; + + size_t + GetTypeBitAlign(lldb::opaque_compiler_type_t type) override; + + lldb::BasicType + GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override; + + uint64_t + GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) override; + + lldb::Encoding + GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) override; + + lldb::Format + GetFormat(lldb::opaque_compiler_type_t type) override; + + unsigned + GetTypeQualifiers(lldb::opaque_compiler_type_t type) override; + + size_t + GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind) override; + + int + GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) override; + + CompilerType + GetFunctionReturnType(lldb::opaque_compiler_type_t type) override; + + size_t + GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override; + + TypeMemberFunctionImpl + GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) override; + + uint32_t + GetNumFields(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) override; + + uint32_t + GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) override; + + uint32_t + GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override; + + uint32_t + GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override; + + CompilerType + GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) override; + + CompilerType + GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) override; + + size_t + ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size) override; + + void + DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, bool show_types, bool show_summary, bool verbose, uint32_t depth) override; + + bool + DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data, + lldb::offset_t data_offset, size_t data_byte_size, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) override; + + void + DumpTypeDescription(lldb::opaque_compiler_type_t type) override; + + void + DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) override; + + void + DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data, + lldb::offset_t data_offset, size_t data_byte_size) override; + + CompilerType + GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, bool ignore_array_bounds, + std::string &child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, + uint64_t &language_flags) override; + + uint32_t + GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) override; + + size_t + GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes, + std::vector &child_indexes) override; + + CompilerType + GetLValueReferenceType(lldb::opaque_compiler_type_t type) override; + + ConstString + DeclContextGetScopeQualifiedName(lldb::opaque_compiler_type_t opaque_decl_ctx) override; + + CompilerType + CreateBaseType(const ConstString &name); + + CompilerType + CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size); + + CompilerType + CreateArrayType(const CompilerType &element_type, const DWARFExpression &length_expression, + const lldb::addr_t data_offset); + + CompilerType + CreateReferenceType(const CompilerType &pointee_type); + + void + CompleteObjectType(const CompilerType &object_type); + + void + AddBaseClassToObject(const CompilerType &object_type, const CompilerType &member_type, uint32_t member_offset); + + void + AddMemberToObject(const CompilerType &object_type, const ConstString &name, const CompilerType &member_type, + uint32_t member_offset); + + void + SetDynamicTypeId(const CompilerType &type, const DWARFExpression &type_id); + + static bool + IsJavaString(const CompilerType &type); + + static uint64_t + CalculateDynamicTypeId(ExecutionContext *exe_ctx, const CompilerType &type, ValueObject &in_value); + + static ConstString + GetLinkageName(const CompilerType &type); + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool + classof(const TypeSystem *ts) + { + return ts->getKind() == TypeSystem::eKindJava; + } + +private: + uint32_t m_pointer_byte_size; + std::unique_ptr m_dwarf_ast_parser_ap; + JavaTypeMap m_array_type_map; + JavaTypeMap m_base_type_map; + JavaTypeMap m_reference_type_map; + JavaTypeMap m_object_type_map; + + JavaASTContext(const JavaASTContext &) = delete; + const JavaASTContext & + operator=(const JavaASTContext &) = delete; +}; +} +#endif // liblldb_JavaASTContext_h_ Index: include/lldb/Symbol/TypeSystem.h =================================================================== --- include/lldb/Symbol/TypeSystem.h +++ include/lldb/Symbol/TypeSystem.h @@ -74,6 +74,7 @@ eKindClang, eKindSwift, eKindGo, + eKindJava, kNumKinds }; Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -26,6 +26,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/JavaASTContext.h" #include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h" #include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h" @@ -46,12 +47,14 @@ #include "Plugins/JITLoader/GDB/JITLoaderGDB.h" #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Language/Go/GoLanguage.h" +#include "Plugins/Language/Java/JavaLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h" #include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h" #include "Plugins/LanguageRuntime/Go/GoLanguageRuntime.h" +#include "Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h" #include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h" #include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h" #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" @@ -272,6 +275,7 @@ ClangASTContext::Initialize(); GoASTContext::Initialize(); + JavaASTContext::Initialize(); ABIMacOSX_i386::Initialize(); ABIMacOSX_arm::Initialize(); @@ -308,9 +312,11 @@ SystemRuntimeMacOSX::Initialize(); RenderScriptRuntime::Initialize(); GoLanguageRuntime::Initialize(); + JavaLanguageRuntime::Initialize(); CPlusPlusLanguage::Initialize(); GoLanguage::Initialize(); + JavaLanguage::Initialize(); ObjCLanguage::Initialize(); ObjCPlusPlusLanguage::Initialize(); @@ -391,6 +397,7 @@ ClangASTContext::Terminate(); GoASTContext::Terminate(); + JavaASTContext::Terminate(); ABIMacOSX_i386::Terminate(); ABIMacOSX_arm::Terminate(); @@ -425,9 +432,11 @@ AppleObjCRuntimeV1::Terminate(); SystemRuntimeMacOSX::Terminate(); RenderScriptRuntime::Terminate(); + JavaLanguageRuntime::Terminate(); CPlusPlusLanguage::Terminate(); GoLanguage::Terminate(); + JavaLanguage::Terminate(); ObjCLanguage::Terminate(); ObjCPlusPlusLanguage::Terminate(); Index: source/Plugins/Language/CMakeLists.txt =================================================================== --- source/Plugins/Language/CMakeLists.txt +++ source/Plugins/Language/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(CPlusPlus) add_subdirectory(Go) +add_subdirectory(Java) add_subdirectory(ObjC) add_subdirectory(ObjCPlusPlus) Index: source/Plugins/Language/Java/CMakeLists.txt =================================================================== --- /dev/null +++ source/Plugins/Language/Java/CMakeLists.txt @@ -0,0 +1,4 @@ +add_lldb_library(lldbPluginJavaLanguage + JavaFormatterFunctions.cpp + JavaLanguage.cpp +) Index: source/Plugins/Language/Java/JavaFormatterFunctions.h =================================================================== --- /dev/null +++ source/Plugins/Language/Java/JavaFormatterFunctions.h @@ -0,0 +1,30 @@ +//===-- JavaFormatterFunctions.h---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_JavaFormatterFunctions_h_ +#define liblldb_JavaFormatterFunctions_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" + +namespace lldb_private +{ +namespace formatters +{ + +bool +JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); + +} // namespace formatters +} // namespace lldb_private + +#endif // liblldb_JavaFormatterFunctions_h_ Index: source/Plugins/Language/Java/JavaFormatterFunctions.cpp =================================================================== --- /dev/null +++ source/Plugins/Language/Java/JavaFormatterFunctions.cpp @@ -0,0 +1,71 @@ +//===-- JavaFormatterFunctions.cpp-------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "JavaFormatterFunctions.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) +{ + if (valobj.IsPointerOrReferenceType()) + { + Error error; + ValueObjectSP deref = valobj.Dereference(error); + if (error.Fail()) + return false; + return JavaStringSummaryProvider(*deref, stream, opts); + } + + ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + return false; + + ConstString data_name("value"); + ConstString length_name("count"); + + ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true); + ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true); + if (!data_sp || !length_sp) + return false; + + bool success = false; + uint64_t length = length_sp->GetValueAsUnsigned(0, &success); + if (!success) + return false; + + if (length == 0) + { + stream.Printf("\"\""); + return true; + } + lldb::addr_t valobj_addr = data_sp->GetAddressOf(); + + StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(valobj_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetSourceSize(length); + options.SetNeedsZeroTermination(false); + options.SetLanguage(eLanguageTypeJava); + + if (StringPrinter::ReadStringAndDumpToStream(options)) + return true; + + stream.Printf("Summary Unavailable"); + return true; +} Index: source/Plugins/Language/Java/JavaLanguage.h =================================================================== --- /dev/null +++ source/Plugins/Language/Java/JavaLanguage.h @@ -0,0 +1,64 @@ +//===-- JavaLanguage.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_JavaLanguage_h_ +#define liblldb_JavaLanguage_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Target/Language.h" +#include "lldb/lldb-private.h" + +namespace lldb_private +{ + +class JavaLanguage : public Language +{ +public: + lldb::LanguageType + GetLanguageType() const override + { + return lldb::eLanguageTypeJava; + } + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::Language * + CreateInstance(lldb::LanguageType language); + + static lldb_private::ConstString + GetPluginNameStatic(); + + ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + bool + IsNilReference(ValueObject &valobj) override; + + HardcodedFormatters::HardcodedSummaryFinder + GetHardcodedSummaries() override; +}; + +} // namespace lldb_private + +#endif // liblldb_JavaLanguage_h_ Index: source/Plugins/Language/Java/JavaLanguage.cpp =================================================================== --- /dev/null +++ source/Plugins/Language/Java/JavaLanguage.cpp @@ -0,0 +1,104 @@ +//===-- JavaLanguage.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "JavaFormatterFunctions.h" +#include "JavaLanguage.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/JavaASTContext.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +void +JavaLanguage::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java Language", CreateInstance); +} + +void +JavaLanguage::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString +JavaLanguage::GetPluginNameStatic() +{ + static ConstString g_name("Java"); + return g_name; +} + +lldb_private::ConstString +JavaLanguage::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +JavaLanguage::GetPluginVersion() +{ + return 1; +} + +Language * +JavaLanguage::CreateInstance(lldb::LanguageType language) +{ + if (language == eLanguageTypeJava) + return new JavaLanguage(); + return nullptr; +} + +bool +JavaLanguage::IsNilReference(ValueObject &valobj) +{ + if (!valobj.GetCompilerType().IsReferenceType()) + return false; + + // If we failed to read the value then it is not a nil reference. + return valobj.GetValueAsUnsigned(UINT64_MAX) == 0; +} + +HardcodedFormatters::HardcodedSummaryFinder +JavaLanguage::GetHardcodedSummaries() +{ + static std::once_flag g_initialize; + static HardcodedFormatters::HardcodedSummaryFinder g_formatters; + + std::call_once(g_initialize, []() -> void { + g_formatters.push_back([](lldb_private::ValueObject &valobj, lldb::DynamicValueType, + FormatManager &) -> TypeSummaryImpl::SharedPointer { + static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat( + TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaStringSummaryProvider, + "Java string summary provider")); + + CompilerType compiler_type = valobj.GetCompilerType(); + if (JavaASTContext::IsJavaString(compiler_type)) + return formatter_sp; + + CompilerType pointee_type; + if (compiler_type.IsReferenceType(&pointee_type) && JavaASTContext::IsJavaString(pointee_type)) + return formatter_sp; + return nullptr; + }); + }); + return g_formatters; +} Index: source/Plugins/LanguageRuntime/CMakeLists.txt =================================================================== --- source/Plugins/LanguageRuntime/CMakeLists.txt +++ source/Plugins/LanguageRuntime/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(CPlusPlus) add_subdirectory(ObjC) add_subdirectory(Go) +add_subdirectory(Java) add_subdirectory(RenderScript) Index: source/Plugins/LanguageRuntime/Java/CMakeLists.txt =================================================================== --- /dev/null +++ source/Plugins/LanguageRuntime/Java/CMakeLists.txt @@ -0,0 +1,3 @@ +add_lldb_library(lldbPluginLanguageRuntimeJava + JavaLanguageRuntime.cpp + ) Index: source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h =================================================================== --- /dev/null +++ source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h @@ -0,0 +1,90 @@ +//===-- JavaLanguageRuntime.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_JavaLanguageRuntime_h_ +#define liblldb_JavaLanguageRuntime_h_ + +// C Includes +// C++ Includes +#include +// Other libraries and framework includes +// Project includes +#include "lldb/Core/PluginInterface.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-private.h" + +namespace lldb_private +{ + +class JavaLanguageRuntime : public LanguageRuntime +{ +public: + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::LanguageRuntime * + CreateInstance(Process *process, lldb::LanguageType language); + + static lldb_private::ConstString + GetPluginNameStatic(); + + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + lldb::LanguageType + GetLanguageType() const override + { + return lldb::eLanguageTypeJava; + } + + bool + GetObjectDescription(Stream &str, ValueObject &object) override + { + return false; + } + + bool + GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override + { + return false; + } + + lldb::BreakpointResolverSP + CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override + { + return nullptr; + } + + TypeAndOrName + FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override; + + bool + CouldHaveDynamicValue(ValueObject &in_value) override; + + bool + GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &address, + Value::ValueType &value_type) override; + +protected: + JavaLanguageRuntime(Process *process); + +private: + DISALLOW_COPY_AND_ASSIGN(JavaLanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_JavaLanguageRuntime_h_ Index: source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp =================================================================== --- /dev/null +++ source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp @@ -0,0 +1,176 @@ +//===-- JavaLanguageRuntime.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaLanguageRuntime.h" + +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/JavaASTContext.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/Target.h" +#include "llvm/ADT/StringRef.h" + +using namespace lldb; +using namespace lldb_private; + +JavaLanguageRuntime::JavaLanguageRuntime(Process *process) : LanguageRuntime(process) +{ +} + +LanguageRuntime * +JavaLanguageRuntime::CreateInstance(Process *process, lldb::LanguageType language) +{ + if (language == eLanguageTypeJava) + return new JavaLanguageRuntime(process); + return nullptr; +} + +void +JavaLanguageRuntime::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java language runtime", CreateInstance); +} + +void +JavaLanguageRuntime::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString +JavaLanguageRuntime::GetPluginNameStatic() +{ + static ConstString g_name("java"); + return g_name; +} + +lldb_private::ConstString +JavaLanguageRuntime::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +JavaLanguageRuntime::GetPluginVersion() +{ + return 1; +} + +bool +JavaLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) +{ + return true; +} + +static ConstString +GetDynamicTypeId(ExecutionContext *exe_ctx, Target *target, ValueObject &in_value) +{ + SymbolContext sc; + TypeList class_types; + llvm::DenseSet searched_symbol_files; + size_t num_matches = target->GetImages().FindTypes(sc, ConstString("Object"), + true, // name_is_fully_qualified + UINT32_MAX, searched_symbol_files, class_types); + for (size_t i = 0; i < num_matches; ++i) + { + TypeSP type_sp = class_types.GetTypeAtIndex(i); + CompilerType compiler_type = type_sp->GetFullCompilerType(); + + if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava || + compiler_type.GetTypeName() != ConstString("java::lang::Object")) + continue; + + if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) + { + uint64_t type_id = JavaASTContext::CalculateDynamicTypeId(exe_ctx, compiler_type, in_value); + if (type_id != UINT64_MAX) + { + char id[32]; + snprintf(id, sizeof(id), "0x%" PRIX64, type_id); + return ConstString(id); + } + } + } + return ConstString(); +} + +bool +JavaLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &dynamic_address, + Value::ValueType &value_type) +{ + class_type_or_name.Clear(); + + // null references don't have a dynamic type + if (in_value.IsNilReference()) + return false; + + ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); + Target *target = exe_ctx.GetTargetPtr(); + if (!target) + return false; + + ConstString linkage_name; + CompilerType in_type = in_value.GetCompilerType(); + if (in_type.IsPossibleDynamicType(nullptr, false, false)) + linkage_name = GetDynamicTypeId(&exe_ctx, target, in_value); + else + linkage_name = JavaASTContext::GetLinkageName(in_type); + + if (!linkage_name) + return false; + + class_type_or_name.SetName(in_type.GetNonReferenceType().GetTypeName()); + + SymbolContext sc; + TypeList class_types; + llvm::DenseSet searched_symbol_files; + size_t num_matches = target->GetImages().FindTypes(sc, linkage_name, + true, // name_is_fully_qualified + UINT32_MAX, searched_symbol_files, class_types); + + for (size_t i = 0; i < num_matches; ++i) + { + TypeSP type_sp = class_types.GetTypeAtIndex(i); + CompilerType compiler_type = type_sp->GetFullCompilerType(); + + if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava) + continue; + + if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) + { + class_type_or_name.SetTypeSP(type_sp); + + Value &value = in_value.GetValue(); + value_type = value.GetValueType(); + dynamic_address.SetRawAddress(value.GetScalar().ULongLong(0)); + return true; + } + } + return false; +} + +TypeAndOrName +JavaLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) +{ + CompilerType static_type(static_value.GetCompilerType()); + + TypeAndOrName ret(type_and_or_name); + if (type_and_or_name.HasType()) + { + CompilerType orig_type = type_and_or_name.GetCompilerType(); + if (static_type.IsReferenceType()) + ret.SetCompilerType(orig_type.GetLValueReferenceType()); + } + return ret; +} Index: source/Plugins/SymbolFile/DWARF/CMakeLists.txt =================================================================== --- source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -3,6 +3,7 @@ DWARFAbbreviationDeclaration.cpp DWARFASTParserClang.cpp DWARFASTParserGo.cpp + DWARFASTParserJava.cpp DWARFAttribute.cpp DWARFCompileUnit.cpp DWARFDataExtractor.cpp Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h @@ -0,0 +1,78 @@ +//===-- DWARFASTParserJava.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParserJava_h_ +#define SymbolFileDWARF_DWARFASTParserJava_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +// Project includes +#include "DWARFASTParser.h" +#include "DWARFDIE.h" +#include "DWARFDefines.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/JavaASTContext.h" + +class DWARFDebugInfoEntry; +class DWARFDIECollection; + +class DWARFASTParserJava : public DWARFASTParser +{ +public: + DWARFASTParserJava(lldb_private::JavaASTContext &ast); + ~DWARFASTParserJava() override; + + lldb::TypeSP + ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log, + bool *type_is_new_ptr) override; + + lldb_private::Function * + ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die) override; + + bool + CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + lldb_private::CompilerType &java_type) override; + + lldb_private::CompilerDeclContext + GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override + { + return lldb_private::CompilerDeclContext(); + } + + lldb_private::CompilerDeclContext + GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override + { + return lldb_private::CompilerDeclContext(); + } + + lldb_private::CompilerDecl + GetDeclForUIDFromDWARF(const DWARFDIE &die) override + { + return lldb_private::CompilerDecl(); + } + + std::vector + GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) override + { + return std::vector(); + } + + void + ParseChildMembers(const DWARFDIE &parent_die, lldb_private::CompilerType &class_compiler_type); + +private: + lldb_private::JavaASTContext &m_ast; +}; + +#endif // SymbolFileDWARF_DWARFASTParserJava_h_ Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp =================================================================== --- /dev/null +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp @@ -0,0 +1,518 @@ +//===-- DWARFASTParserJava.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserJava.h" +#include "DWARFAttribute.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDeclContext.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/TypeList.h" + +using namespace lldb; +using namespace lldb_private; + +DWARFASTParserJava::DWARFASTParserJava(JavaASTContext &ast) : m_ast(ast) +{ +} + +DWARFASTParserJava::~DWARFASTParserJava() +{ +} + +lldb::TypeSP +DWARFASTParserJava::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, + lldb_private::Log *log, bool *type_is_new_ptr) +{ + if (type_is_new_ptr) + *type_is_new_ptr = false; + + if (!die) + return nullptr; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + + Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); + if (type_ptr == DIE_IS_BEING_PARSED) + return nullptr; + if (type_ptr != nullptr) + return type_ptr->shared_from_this(); + + TypeSP type_sp; + if (type_is_new_ptr) + *type_is_new_ptr = true; + + switch (die.Tag()) + { + case DW_TAG_base_type: + { + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ConstString type_name; + uint64_t byte_size = 0; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name.SetCString(form_value.AsCString()); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_encoding: + break; + default: + assert(false && "Unsupported attribute for DW_TAG_base_type"); + } + } + } + + Declaration decl; + CompilerType compiler_type = m_ast.CreateBaseType(type_name); + type_sp.reset(new Type(die.GetID(), dwarf, type_name, byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, compiler_type, Type::eResolveStateFull)); + break; + } + case DW_TAG_array_type: + { + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ConstString linkage_name; + lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; + lldb::addr_t data_offset = LLDB_INVALID_ADDRESS; + DWARFExpression length_expression(die.GetCU()); + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_linkage_name: + linkage_name.SetCString(form_value.AsCString()); + break; + case DW_AT_type: + type_die_offset = form_value.Reference(); + break; + case DW_AT_data_member_location: + data_offset = form_value.Unsigned(); + break; + case DW_AT_declaration: + break; + default: + assert(false && "Unsupported attribute for DW_TAG_array_type"); + } + } + } + + for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); child_die = child_die.GetSibling()) + { + if (child_die.Tag() == DW_TAG_subrange_type) + { + DWARFAttributes attributes; + const size_t num_attributes = child_die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_count: + if (form_value.BlockData()) + length_expression.CopyOpcodeData(form_value.BlockData(), form_value.Unsigned(), + child_die.GetCU()->GetByteOrder(), + child_die.GetCU()->GetAddressByteSize()); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_subrange_type"); + } + } + } + } + else + { + assert(false && "Unsupported child for DW_TAG_array_type"); + } + } + + Type *element_type = dwarf->ResolveTypeUID(type_die_offset); + if (element_type) + { + CompilerType element_compiler_type = element_type->GetForwardCompilerType(); + CompilerType array_compiler_type = + m_ast.CreateArrayType(element_compiler_type, length_expression, data_offset); + + Declaration decl; + type_sp.reset(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(), -1, nullptr, + dwarf->MakeUserID(type_die_offset), Type::eEncodingIsUID, &decl, + array_compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(element_type); + } + + break; + } + case DW_TAG_class_type: + { + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + Declaration decl; + ConstString name; + ConstString linkage_name; + bool is_forward_declaration = false; + uint32_t byte_size = 0; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + name.SetCString(form_value.AsCString()); + break; + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_linkage_name: + linkage_name.SetCString(form_value.AsCString()); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_class_type"); + } + } + } + + UniqueDWARFASTType unique_ast_entry; + if (name) + { + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + { + name.SetCString(qualified_name.c_str()); + if (dwarf->GetUniqueDWARFASTTypeMap().Find(name, die, Declaration(), -1, unique_ast_entry)) + { + if (unique_ast_entry.m_type_sp) + { + dwarf->GetDIEToType()[die.GetDIE()] = unique_ast_entry.m_type_sp.get(); + return unique_ast_entry.m_type_sp; + } + } + } + } + + if (is_forward_declaration) + { + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + if (type_sp) + { + // We found a real definition for this type elsewhere so lets use it + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } + + CompilerType compiler_type(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!compiler_type) + compiler_type = m_ast.CreateObjectType(name, linkage_name, byte_size); + + type_sp.reset(new Type(die.GetID(), dwarf, name, + -1, // byte size isn't specified + nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateForward)); + + // Add our type to the unique type map + unique_ast_entry.m_type_sp = type_sp; + unique_ast_entry.m_die = die; + unique_ast_entry.m_declaration = decl; + unique_ast_entry.m_byte_size = -1; + dwarf->GetUniqueDWARFASTTypeMap().Insert(name, unique_ast_entry); + + if (!is_forward_declaration) + { + // Leave this as a forward declaration until we need to know the details of the type + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = compiler_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie()[compiler_type.GetOpaqueQualType()] = die.GetDIERef(); + } + + break; + } + case DW_TAG_reference_type: + { + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + Declaration decl; + lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_type: + type_die_offset = form_value.Reference(); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_array_type"); + } + } + } + + Type *pointee_type = dwarf->ResolveTypeUID(type_die_offset); + if (pointee_type) + { + CompilerType pointee_compiler_type = pointee_type->GetForwardCompilerType(); + CompilerType reference_compiler_type = m_ast.CreateReferenceType(pointee_compiler_type); + type_sp.reset(new Type(die.GetID(), dwarf, reference_compiler_type.GetTypeName(), -1, nullptr, + dwarf->MakeUserID(type_die_offset), Type::eEncodingIsUID, &decl, + reference_compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(pointee_type); + } + break; + } + } + + if (!type_sp) + return nullptr; + + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = nullptr; + if (sc_parent_tag == DW_TAG_compile_unit) + { + symbol_context_scope = sc.comp_unit; + } + else if (sc.function != nullptr && sc_parent_die) + { + symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == nullptr) + symbol_context_scope = sc.function; + } + + if (symbol_context_scope != nullptr) + type_sp->SetSymbolContextScope(symbol_context_scope); + + dwarf->GetTypeList()->Insert(type_sp); + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + + return type_sp; +} + +lldb_private::Function * +DWARFASTParserJava::ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die) +{ + assert(die.Tag() == DW_TAG_subprogram); + + const char *name = nullptr; + const char *mangled = nullptr; + int decl_file = 0; + int decl_line = 0; + int decl_column = 0; + int call_file = 0; + int call_line = 0; + int call_column = 0; + DWARFRangeList func_ranges; + DWARFExpression frame_base(die.GetCU()); + + if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, + call_column, &frame_base)) + { + // Union of all ranges in the function DIE (if the function is discontiguous) + AddressRange func_range; + lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0); + lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0); + if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) + { + ModuleSP module_sp(die.GetModule()); + func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList()); + if (func_range.GetBaseAddress().IsValid()) + func_range.SetByteSize(highest_func_addr - lowest_func_addr); + } + + if (func_range.GetBaseAddress().IsValid()) + { + std::unique_ptr decl_ap; + if (decl_file != 0 || decl_line != 0 || decl_column != 0) + decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, + decl_column)); + + if (die.GetDWARF()->FixupAddress(func_range.GetBaseAddress())) + { + FunctionSP func_sp(new Function(sc.comp_unit, die.GetID(), die.GetID(), + Mangled(ConstString(name), false), + nullptr, // No function types in java + func_range)); + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + + return func_sp.get(); + } + } + } + return nullptr; +} + +bool +DWARFASTParserJava::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + lldb_private::CompilerType &java_type) +{ + switch (die.Tag()) + { + case DW_TAG_class_type: + { + if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 0) + { + if (die.HasChildren()) + ParseChildMembers(die, java_type); + m_ast.CompleteObjectType(java_type); + return java_type.IsValid(); + } + } + default: + assert(false && "Not a forward java type declaration!"); + break; + } + return false; +} + +void +DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die, CompilerType &compiler_type) +{ + DWARFCompileUnit *dwarf_cu = parent_die.GetCU(); + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + switch (die.Tag()) + { + case DW_TAG_member: + { + const char *name = nullptr; + lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + uint32_t member_byte_offset = UINT32_MAX; + DWARFExpression member_location_expression(dwarf_cu); + bool artificial = true; + + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attributes.AttributeAtIndex(i)) + { + case DW_AT_name: + name = form_value.AsCString(); + break; + case DW_AT_type: + encoding_uid = form_value.Reference(); + break; + case DW_AT_data_member_location: + if (form_value.BlockData()) + member_location_expression.CopyOpcodeData( + form_value.BlockData(), form_value.Unsigned(), dwarf_cu->GetByteOrder(), + dwarf_cu->GetAddressByteSize()); + else + member_byte_offset = form_value.Unsigned(); + break; + case DW_AT_artificial: + artificial = form_value.Boolean(); + break; + case DW_AT_accessibility: + // TODO: Handle when needed + break; + default: + assert(false && "Unhandled attribute for DW_TAG_member"); + break; + } + } + } + + if (strcmp(name, ".dynamic_type") == 0) + m_ast.SetDynamicTypeId(compiler_type, member_location_expression); + else + { + if (Type *member_type = die.ResolveTypeUID(encoding_uid)) + m_ast.AddMemberToObject(compiler_type, ConstString(name), member_type->GetFullCompilerType(), + member_byte_offset); + } + break; + } + case DW_TAG_inheritance: + { + lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + uint32_t member_byte_offset = UINT32_MAX; + + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attributes.AttributeAtIndex(i)) + { + case DW_AT_type: + encoding_uid = form_value.Reference(); + break; + case DW_AT_data_member_location: + member_byte_offset = form_value.Unsigned(); + break; + case DW_AT_accessibility: + // In java all base class is public so we can ignore this attribute + break; + default: + assert(false && "Unhandled attribute for DW_TAG_member"); + break; + } + } + } + if (Type *base_type = die.ResolveTypeUID(encoding_uid)) + m_ast.AddBaseClassToObject(compiler_type, base_type->GetFullCompilerType(), member_byte_offset); + break; + } + default: + break; + } + } +} \ No newline at end of file Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -59,6 +59,8 @@ void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, DWARFDebugAranges* debug_aranges); + lldb::ByteOrder + GetByteOrder() const; lldb_private::TypeSystem * GetTypeSystem(); Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -1024,10 +1024,10 @@ case DW_TAG_union_type: case DW_TAG_typedef: case DW_TAG_unspecified_type: - if (name && is_declaration == false) - { + if (name && !is_declaration) types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); - } + if (mangled_cstr && !is_declaration) + types.Insert (ConstString(mangled_cstr), DIERef(cu_offset, die.GetOffset())); break; case DW_TAG_namespace: @@ -1259,3 +1259,9 @@ m_addr_base = addr_base; m_base_obj_offset = base_obj_offset; } + +lldb::ByteOrder +DWARFCompileUnit::GetByteOrder() const +{ + return m_dwarf2Data->GetObjectFile()->GetByteOrder(); +} Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -70,6 +70,7 @@ friend class DWARFCompileUnit; friend class DWARFASTParserClang; friend class DWARFASTParserGo; + friend class DWARFASTParserJava; //------------------------------------------------------------------ // Static Functions Index: source/Symbol/CMakeLists.txt =================================================================== --- source/Symbol/CMakeLists.txt +++ source/Symbol/CMakeLists.txt @@ -16,6 +16,7 @@ Function.cpp FuncUnwinders.cpp GoASTContext.cpp + JavaASTContext.cpp LineEntry.cpp LineTable.cpp ObjectFile.cpp Index: source/Symbol/JavaASTContext.cpp =================================================================== --- /dev/null +++ source/Symbol/JavaASTContext.cpp @@ -0,0 +1,1526 @@ +//===-- JavaASTContext.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/JavaASTContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/Target.h" + +#include "Plugins/SymbolFile/DWARF/DWARFASTParserJava.h" + +using namespace lldb; +using namespace lldb_private; + +namespace lldb_private +{ + +class JavaASTContext::JavaType +{ +public: + enum LLVMCastKind + { + eKindPrimitive, + eKindObject, + eKindReference, + eKindArray, + kNumKinds + }; + + JavaType(LLVMCastKind kind) : m_kind(kind) {} + + virtual ~JavaType() = default; + + virtual ConstString + GetName() = 0; + + virtual void + Dump(Stream *s) = 0; + + virtual bool + IsCompleteType() = 0; + + LLVMCastKind + getKind() const + { + return m_kind; + } + +private: + LLVMCastKind m_kind; +}; + +} // end of namespace lldb_private + +namespace +{ + +class JavaPrimitiveType : public JavaASTContext::JavaType +{ +public: + enum TypeKind + { + eTypeByte, + eTypeShort, + eTypeInt, + eTypeLong, + eTypeFloat, + eTypeDouble, + eTypeBoolean, + eTypeChar, + }; + + JavaPrimitiveType(TypeKind type_kind) : JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {} + + ConstString + GetName() override + { + switch (m_type_kind) + { + case eTypeByte: + return ConstString("byte"); + case eTypeShort: + return ConstString("short"); + case eTypeInt: + return ConstString("int"); + case eTypeLong: + return ConstString("long"); + case eTypeFloat: + return ConstString("float"); + case eTypeDouble: + return ConstString("double"); + case eTypeBoolean: + return ConstString("boolean"); + case eTypeChar: + return ConstString("char"); + } + return ConstString(); + } + + TypeKind + GetTypeKind() + { + return m_type_kind; + } + + void + Dump(Stream *s) override + { + s->Printf("%s\n", GetName().GetCString()); + } + + bool + IsCompleteType() override + { + return true; + } + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindPrimitive; + } + +private: + const TypeKind m_type_kind; +}; + +class JavaObjectType : public JavaASTContext::JavaType +{ +public: + struct Field + { + ConstString m_name; + CompilerType m_type; + uint32_t m_offset; + }; + + JavaObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) + : JavaType(JavaType::eKindObject), + m_name(name), + m_linkage_name(linkage_name), + m_byte_size(byte_size), + m_base_class_offset(0), + m_is_complete(false), + m_dynamic_type_id(nullptr) + { + } + + ConstString + GetName() override + { + return m_name; + } + + ConstString + GetLinkageName() const + { + return m_linkage_name; + } + + uint32_t + GetByteSize() const + { + return m_byte_size; + } + + uint32_t + GetNumFields() + { + return m_fields.size(); + } + + void + Dump(Stream *s) override + { + if (m_base_class.IsValid()) + s->Printf("%s : %s\n", GetName().GetCString(), m_base_class.GetTypeName().GetCString()); + else + s->Printf("%s\n", GetName().GetCString()); + + s->IndentMore(); + for (const Field &f : m_fields) + s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(), f.m_name.GetCString()); + s->IndentLess(); + } + + Field * + GetFieldAtIndex(size_t idx) + { + if (idx < m_fields.size()) + return &m_fields[idx]; + return nullptr; + } + + CompilerType + GetBaseClass() + { + return m_base_class; + } + + uint32_t + GetBaseClassOffset() + { + return m_base_class_offset; + } + + uint32_t + GetNumInterfaces() + { + return m_interfaces.size(); + } + + CompilerType + GetInterfaceAtIndex(uint32_t idx) + { + if (m_interfaces.size() < idx) + return m_interfaces[idx]; + return CompilerType(); + } + + bool + IsCompleteType() override + { + return m_is_complete; + } + + void + SetCompleteType(bool is_complete) + { + m_is_complete = is_complete; + if (m_byte_size == 0) + { + // Try to calcualte the size of the object based on it's values + for (const Field &field : m_fields) + { + uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr); + if (field_end > m_byte_size) + m_byte_size = field_end; + } + } + } + + void + AddBaseClass(const CompilerType &type, uint32_t offset) + { + // TODO: Check if type is an interface and add it to the interface list in that case + m_base_class = type; + m_base_class_offset = offset; + } + + void + AddField(const ConstString &name, const CompilerType &type, uint32_t offset) + { + m_fields.push_back({name, type, offset}); + } + + void + SetDynamicTypeId(const DWARFExpression &type_id) + { + m_dynamic_type_id = type_id; + } + + uint64_t + CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj) + { + if (!m_dynamic_type_id.IsValid()) + return UINT64_MAX; + + Value obj_load_address = value_obj.GetValue(); + obj_load_address.ResolveValue(exe_ctx); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); + + Value result; + if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address, + nullptr, result, nullptr)) + { + Error error; + + lldb::addr_t type_id_addr = result.GetScalar().UInt(); + lldb::ProcessSP process_sp = exe_ctx->GetProcessSP(); + if (process_sp) + return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(), + UINT64_MAX, error); + } + + return UINT64_MAX; + } + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindObject; + } + +private: + ConstString m_name; + ConstString m_linkage_name; + uint32_t m_byte_size; + CompilerType m_base_class; + uint32_t m_base_class_offset; + std::vector m_interfaces; + std::vector m_fields; + bool m_is_complete; + DWARFExpression m_dynamic_type_id; +}; + +class JavaReferenceType : public JavaASTContext::JavaType +{ +public: + JavaReferenceType(CompilerType pointee_type) : JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {} + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindReference; + } + + CompilerType + GetPointeeType() + { + return m_pointee_type; + } + + ConstString + GetName() override + { + ConstString pointee_type_name = static_cast(GetPointeeType().GetOpaqueQualType())->GetName(); + return ConstString(std::string(pointee_type_name.AsCString()) + "&"); + } + + void + Dump(Stream *s) override + { + static_cast(m_pointee_type.GetOpaqueQualType())->Dump(s); + } + + bool + IsCompleteType() override + { + return m_pointee_type.IsCompleteType(); + } + +private: + CompilerType m_pointee_type; +}; + +class JavaArrayType : public JavaASTContext::JavaType +{ +public: + JavaArrayType(CompilerType element_type, const DWARFExpression &length_expression, const lldb::addr_t data_offset) + : JavaType(JavaType::eKindArray), + m_element_type(element_type), + m_length_expression(length_expression), + m_data_offset(data_offset) + { + } + + static bool + classof(const JavaType *jt) + { + return jt->getKind() == JavaType::eKindArray; + } + + CompilerType + GetElementType() + { + return m_element_type; + } + + ConstString + GetName() override + { + ConstString element_type_name = static_cast(GetElementType().GetOpaqueQualType())->GetName(); + return ConstString(std::string(element_type_name.AsCString()) + "[]"); + } + + void + Dump(Stream *s) override + { + s->Printf("%s\n", GetName().GetCString()); + } + + bool + IsCompleteType() override + { + return m_length_expression.IsValid(); + } + + uint32_t + GetNumElements(const ValueObject *value_obj) + { + if (!m_length_expression.IsValid()) + return false; + + Value obj_load_address = value_obj->GetValue(); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); + + Value result; + if (m_length_expression.Evaluate(nullptr, nullptr, nullptr, nullptr, 0, nullptr, &obj_load_address, result, + nullptr)) + return result.GetScalar().UInt(); + + return 0; + } + +private: + CompilerType m_element_type; + DWARFExpression m_length_expression; + lldb::addr_t m_data_offset; +}; + +} // end of anonymous namespace + +ConstString +JavaASTContext::GetPluginNameStatic() +{ + return ConstString("java"); +} + +ConstString +JavaASTContext::GetPluginName() +{ + return JavaASTContext::GetPluginNameStatic(); +} + +uint32_t +JavaASTContext::GetPluginVersion() +{ + return 1; +} + +lldb::TypeSystemSP +JavaASTContext::CreateInstance(lldb::LanguageType language, Module *module, Target *target) +{ + if (language == eLanguageTypeJava) + { + if (module) + return std::make_shared(module->GetArchitecture()); + if (target) + return std::make_shared(target->GetArchitecture()); + assert(false && "Either a module or a target has to be specifed to create a JavaASTContext"); + } + return lldb::TypeSystemSP(); +} + +void +JavaASTContext::EnumerateSupportedLanguages(std::set &languages_for_types, + std::set &languages_for_expressions) +{ + static std::vector s_languages_for_types({lldb::eLanguageTypeJava}); + static std::vector s_languages_for_expressions({}); + + languages_for_types.insert(s_languages_for_types.begin(), s_languages_for_types.end()); + languages_for_expressions.insert(s_languages_for_expressions.begin(), s_languages_for_expressions.end()); +} + +void +JavaASTContext::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", CreateInstance, + EnumerateSupportedLanguages); +} + +void +JavaASTContext::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +JavaASTContext::JavaASTContext(const ArchSpec &arch) + : TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize()) +{ +} + +JavaASTContext::~JavaASTContext() +{ +} + +uint32_t +JavaASTContext::GetPointerByteSize() +{ + return m_pointer_byte_size; +} + +DWARFASTParser * +JavaASTContext::GetDWARFParser() +{ + if (!m_dwarf_ast_parser_ap) + m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this)); + return m_dwarf_ast_parser_ap.get(); +} + +ConstString +JavaASTContext::DeclGetName(void *opaque_decl) +{ + return ConstString(); +} + +lldb::VariableSP +JavaASTContext::DeclGetVariable(void *opaque_decl) +{ + return lldb::VariableSP(); +} + +void +JavaASTContext::DeclLinkToObject(void *opaque_decl, std::shared_ptr object) +{ +} + +std::vector +JavaASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) +{ + return std::vector(); +} + +bool +JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) +{ + return false; +} + +ConstString +JavaASTContext::DeclContextGetName(void *opaque_decl_ctx) +{ + return ConstString(); +} + +bool +JavaASTContext::DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, ConstString *language_object_name_ptr) +{ + return false; +} + +bool +JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, + bool *is_incomplete) +{ + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + + if (JavaArrayType *array = llvm::dyn_cast(static_cast(type))) + { + if (element_type) + *element_type = array->GetElementType(); + return true; + } + return false; +} + +bool +JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) +{ + return llvm::isa(static_cast(type)); +} + +bool +JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar; + return false; +} + +bool +JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) +{ + is_complex = true; + + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + count = 1; + return true; + default: + break; + } + } + + count = 0; + return false; +} + +bool +JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) +{ + if (is_variadic_ptr) + *is_variadic_ptr = false; + return false; +} + +size_t +JavaASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +CompilerType +JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) +{ + return CompilerType(); +} + +bool +JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + is_signed = true; + return true; + default: + break; + } + } + + is_signed = false; + return false; +} + +bool +JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, CompilerType *target_type, + bool check_cplusplus, bool check_objc) +{ + return llvm::isa(static_cast(type)); +} + +bool +JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) +{ + if (pointee_type) + pointee_type->Clear(); + return false; +} + +bool +JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue) +{ + if (is_rvalue) + *is_rvalue = false; + + if (JavaReferenceType *ref = llvm::dyn_cast(static_cast(type))) + { + if (pointee_type) + *pointee_type = ref->GetPointeeType(); + return true; + } + + if (pointee_type) + pointee_type->Clear(); + return false; +} + +bool +JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type) +{ + return llvm::isa(static_cast(type)) || + llvm::isa(static_cast(type)); +} + +bool +JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type) +{ + return false; // TODO: Implement if we introduce the void type +} + +bool +JavaASTContext::SupportsLanguage(lldb::LanguageType language) +{ + return language == lldb::eLanguageTypeJava; +} + +bool +JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) +{ + return true; +} + +bool +JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) +{ + return IsPointerType(type, pointee_type) || IsReferenceType(type, pointee_type); +} + +bool +JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) +{ + return false; // TODO: Implement it if we need it for string literals +} + +bool +JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) +{ + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + return false; +} + +bool +JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) +{ + return llvm::isa(static_cast(type)); +} + +uint32_t +JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) +{ + return false; +} + +bool +JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) +{ + return static_cast(type)->IsCompleteType(); +} + +bool +JavaASTContext::IsConst(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) +{ + return false; +} + +bool +JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type) +{ + return type != nullptr; +} + +bool +JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) +{ + if (IsCompleteType(type)) + return true; + + if (JavaArrayType *array = llvm::dyn_cast(static_cast(type))) + return GetCompleteType(array->GetElementType().GetOpaqueQualType()); + + if (JavaReferenceType *reference = llvm::dyn_cast(static_cast(type))) + return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType()); + + if (llvm::isa(static_cast(type))) + { + SymbolFile *symbol_file = GetSymbolFile(); + if (!symbol_file) + return false; + + CompilerType object_type(this, type); + return symbol_file->CompleteType(object_type); + } + return false; +} + +ConstString +JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type) +{ + if (type) + return static_cast(type)->GetName(); + return ConstString(); +} + +uint32_t +JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) +{ + if (pointee_or_element_compiler_type) + pointee_or_element_compiler_type->Clear(); + if (!type) + return 0; + + if (IsReferenceType(type, pointee_or_element_compiler_type)) + return eTypeHasChildren | eTypeHasValue | eTypeIsReference; + if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr)) + return eTypeHasChildren | eTypeIsArray; + if (llvm::isa(static_cast(type))) + return eTypeHasChildren | eTypeIsClass; + + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | eTypeIsSigned; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat | eTypeIsSigned; + case JavaPrimitiveType::eTypeBoolean: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; + case JavaPrimitiveType::eTypeChar: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; + } + } + return 0; +} + +lldb::TypeClass +JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) +{ + if (!type) + return eTypeClassInvalid; + if (llvm::isa(static_cast(type))) + return eTypeClassReference; + if (llvm::isa(static_cast(type))) + return eTypeClassArray; + if (llvm::isa(static_cast(type))) + return eTypeClassClass; + if (llvm::isa(static_cast(type))) + return eTypeClassBuiltin; + assert(false && "Java type with unhandled type class"); + return eTypeClassInvalid; +} + +lldb::LanguageType +JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) +{ + return lldb::eLanguageTypeJava; +} + +CompilerType +JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) +{ + if (stride) + *stride = 0; + + CompilerType element_type; + if (IsArrayType(type, &element_type, nullptr, nullptr)) + return element_type; + return CompilerType(); +} + +CompilerType +JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) +{ + CompilerType pointee_type; + if (IsPointerType(type, &pointee_type)) + return pointee_type; + return CompilerType(); +} + +CompilerType +JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(); // No pointer types in java +} + +CompilerType +JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(this, type); +} + +CompilerType +JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(this, type); +} + +CompilerType +JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) +{ + CompilerType pointee_type; + if (IsReferenceType(type, &pointee_type)) + return pointee_type; + return CompilerType(this, type); +} + +CompilerType +JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(); +} + +CompilerType +JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) +{ + return CompilerType(); +} + +CompilerType +JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) +{ + return CompilerType(); +} + +size_t +JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +lldb::BasicType +JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + return eBasicTypeOther; + case JavaPrimitiveType::eTypeShort: + return eBasicTypeShort; + case JavaPrimitiveType::eTypeInt: + return eBasicTypeInt; + case JavaPrimitiveType::eTypeLong: + return eBasicTypeLong; + case JavaPrimitiveType::eTypeFloat: + return eBasicTypeFloat; + case JavaPrimitiveType::eTypeDouble: + return eBasicTypeDouble; + case JavaPrimitiveType::eTypeBoolean: + return eBasicTypeBool; + case JavaPrimitiveType::eTypeChar: + return eBasicTypeChar; + } + } + return eBasicTypeInvalid; +} + +uint64_t +JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + return 8; + case JavaPrimitiveType::eTypeShort: + return 16; + case JavaPrimitiveType::eTypeInt: + return 32; + case JavaPrimitiveType::eTypeLong: + return 64; + case JavaPrimitiveType::eTypeFloat: + return 32; + case JavaPrimitiveType::eTypeDouble: + return 64; + case JavaPrimitiveType::eTypeBoolean: + return 1; + case JavaPrimitiveType::eTypeChar: + return 16; + } + } + else if (llvm::isa(static_cast(type))) + { + return 32; // References are always 4 byte long in java + } + else if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + return obj->GetByteSize() * 8; + } + return 0; +} + +lldb::Encoding +JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) +{ + count = 1; + + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eEncodingSint; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eEncodingIEEE754; + case JavaPrimitiveType::eTypeBoolean: + case JavaPrimitiveType::eTypeChar: + return eEncodingUint; + } + } + if (IsReferenceType(type)) + return eEncodingUint; + return eEncodingInvalid; +} + +lldb::Format +JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type) +{ + if (JavaPrimitiveType *ptype = llvm::dyn_cast(static_cast(type))) + { + switch (ptype->GetTypeKind()) + { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eFormatDecimal; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eFormatFloat; + case JavaPrimitiveType::eTypeBoolean: + return eFormatBoolean; + case JavaPrimitiveType::eTypeChar: + return eFormatUnicode16; + } + } + if (IsReferenceType(type)) + return eFormatHex; + return eFormatDefault; +} + +unsigned +JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +size_t +JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, + size_t dst_size) +{ + assert(false && "Not implemented"); + return 0; +} + +size_t +JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +CompilerType +JavaASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind) +{ + return CompilerType(); +} + +uint32_t +JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + return obj->GetNumFields(); + } + return 0; +} + +CompilerType +JavaASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, + uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) +{ + if (bit_offset_ptr) + *bit_offset_ptr = 0; + if (bitfield_bit_size_ptr) + *bitfield_bit_size_ptr = 0; + if (is_bitfield_ptr) + *is_bitfield_ptr = false; + + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + + JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); + if (!field) + return CompilerType(); + name = field->m_name.AsCString(); + if (bit_offset_ptr) + *bit_offset_ptr = field->m_offset * 8; + return field->m_type; + } + return CompilerType(); +} + +uint32_t +JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) +{ + GetCompleteType(type); + + if (JavaReferenceType *ref = llvm::dyn_cast(static_cast(type))) + return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes); + + if (llvm::isa(static_cast(type))) + return GetNumFields(type) + GetNumDirectBaseClasses(type); + + return 0; +} + +uint32_t +JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0); + } + return 0; +} + +uint32_t +JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + return obj->GetNumInterfaces(); + } + return 0; +} + +CompilerType +JavaASTContext::GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + + if (CompilerType base_class = obj->GetBaseClass()) + { + if (idx == 0) + return base_class; + else + --idx; + } + return obj->GetInterfaceAtIndex(idx); + } + return CompilerType(); +} + +CompilerType +JavaASTContext::GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + return obj->GetInterfaceAtIndex(idx); + } + return CompilerType(); +} + +void +JavaASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, + bool verbose, uint32_t depth) +{ + assert(false && "Not implemented"); +} + +bool +JavaASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) +{ + if (IsScalarType(type)) + { + return data.Dump(s, data_offset, format, data_byte_size, + 1, // count + UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope); + } + return false; +} + +void +JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) +{ + StreamFile s(stdout, false); + DumpTypeDescription(type, &s); +} + +void +JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) +{ + static_cast(type)->Dump(s); +} + +void +JavaASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, + const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size) +{ + assert(false && "Not implemented"); +} + +int +JavaASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +CompilerType +JavaASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) +{ + return CompilerType(); +} + +CompilerType +JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) +{ + return CompilerType(); +} + +size_t +JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) +{ + return 0; +} + +TypeMemberFunctionImpl +JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) +{ + return TypeMemberFunctionImpl(); +} + +CompilerType +JavaASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string &child_name, + uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, + ValueObject *valobj, uint64_t &language_flags) +{ + child_name.clear(); + child_byte_size = 0; + child_byte_offset = 0; + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + child_is_deref_of_parent = false; + language_flags = 0; + + ExecutionContextScope *exec_ctx_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + + if (CompilerType base_class = obj->GetBaseClass()) + { + if (idx == 0) + { + JavaType *base_class_type = static_cast(base_class.GetOpaqueQualType()); + child_name = base_class_type->GetName().GetCString(); + child_byte_size = base_class.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); + child_byte_offset = obj->GetBaseClassOffset(); + child_is_base_class = true; + return base_class; + } + idx -= 1; + } + + JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); + if (!field) + return CompilerType(); + + child_name = field->m_name.AsCString(); + child_byte_size = field->m_type.GetByteSize(exec_ctx_scope); + child_byte_offset = field->m_offset; + return field->m_type; + } + else if (JavaReferenceType *ref = llvm::dyn_cast(static_cast(type))) + { + CompilerType pointee_type = ref->GetPointeeType(); + + if (transparent_pointers) + return pointee_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, + child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, valobj, language_flags); + + if (idx != 0) + return CompilerType(); + + if (valobj && valobj->GetName()) + child_name = valobj->GetName().GetCString(); + child_is_deref_of_parent = true; + child_byte_offset = 0; + child_byte_size = pointee_type.GetByteSize(exec_ctx_scope); + return pointee_type; + } + return CompilerType(); +} + +uint32_t +JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + + uint32_t index_offset = 0; + if (CompilerType base_class = obj->GetBaseClass()) + { + if (base_class.GetTypeName() == ConstString(name)) + return 0; + index_offset = 1; + } + for (uint32_t i = 0; i < obj->GetNumFields(); ++i) + { + if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) + return i + index_offset; + } + } + else if (JavaReferenceType *ref = llvm::dyn_cast(static_cast(type))) + { + return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes); + } + return UINT_MAX; +} + +size_t +JavaASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector &child_indexes) +{ + child_indexes.clear(); + + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) + { + GetCompleteType(type); + + uint32_t index_offset = 0; + if (CompilerType base_class = obj->GetBaseClass()) + { + if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name, omit_empty_base_classes, + child_indexes) != 0) + { + child_indexes.insert(child_indexes.begin(), 0); + return child_indexes.size(); + } + index_offset = 1; + } + + for (uint32_t i = 0; i < obj->GetNumFields(); ++i) + { + if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) + { + child_indexes.push_back(i + index_offset); + return child_indexes.size(); + } + } + } + else if (JavaReferenceType *ref = llvm::dyn_cast(static_cast(type))) + { + return GetIndexOfChildMemberWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes, + child_indexes); + } + return 0; +} + +CompilerType +JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) +{ + return CreateReferenceType(CompilerType(this, type)); +} + +ConstString +JavaASTContext::DeclContextGetScopeQualifiedName(lldb::opaque_compiler_type_t opaque_decl_ctx) +{ + return GetTypeName(opaque_decl_ctx); +} + +static void +AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map, JavaPrimitiveType::TypeKind type_kind) +{ + JavaPrimitiveType *type = new JavaPrimitiveType(type_kind); + type_map.emplace(type->GetName(), std::unique_ptr(type)); +} + +CompilerType +JavaASTContext::CreateBaseType(const ConstString &name) +{ + if (m_base_type_map.empty()) + { + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar); + } + auto it = m_base_type_map.find(name); + if (it != m_base_type_map.end()) + return CompilerType(this, it->second.get()); + return CompilerType(); +} + +CompilerType +JavaASTContext::CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) +{ + auto it = m_object_type_map.find(name); + if (it == m_object_type_map.end()) + { + std::unique_ptr object_type(new JavaObjectType(name, linkage_name, byte_size)); + it = m_object_type_map.emplace(name, std::move(object_type)).first; + } + return CompilerType(this, it->second.get()); +} + +CompilerType +JavaASTContext::CreateArrayType(const CompilerType &element_type, const DWARFExpression &length_expression, + const lldb::addr_t data_offset) +{ + ConstString name = element_type.GetTypeName(); + auto it = m_array_type_map.find(name); + if (it == m_array_type_map.end()) + { + std::unique_ptr array_type(new JavaArrayType(element_type, length_expression, data_offset)); + it = m_array_type_map.emplace(name, std::move(array_type)).first; + } + return CompilerType(this, it->second.get()); +} + +CompilerType +JavaASTContext::CreateReferenceType(const CompilerType &pointee_type) +{ + ConstString name = pointee_type.GetTypeName(); + auto it = m_reference_type_map.find(name); + if (it == m_reference_type_map.end()) + it = m_reference_type_map.emplace(name, std::unique_ptr(new JavaReferenceType(pointee_type))).first; + return CompilerType(this, it->second.get()); +} + +void +JavaASTContext::CompleteObjectType(const CompilerType &object_type) +{ + JavaObjectType *obj = llvm::dyn_cast(static_cast(object_type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::CompleteObjectType called with not a JavaObjectType"); + obj->SetCompleteType(true); +} + +void +JavaASTContext::AddBaseClassToObject(const CompilerType &object_type, const CompilerType &member_type, + uint32_t member_offset) +{ + JavaObjectType *obj = llvm::dyn_cast(static_cast(object_type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); + obj->AddBaseClass(member_type, member_offset); +} + +void +JavaASTContext::AddMemberToObject(const CompilerType &object_type, const ConstString &name, + const CompilerType &member_type, uint32_t member_offset) +{ + JavaObjectType *obj = llvm::dyn_cast(static_cast(object_type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); + obj->AddField(name, member_type, member_offset); +} + +void +JavaASTContext::SetDynamicTypeId(const CompilerType &type, const DWARFExpression &type_id) +{ + JavaObjectType *obj = llvm::dyn_cast(static_cast(type.GetOpaqueQualType())); + assert(obj && "JavaASTContext::SetDynamicTypeId called with not a JavaObjectType"); + obj->SetDynamicTypeId(type_id); +} + +bool +JavaASTContext::IsJavaString(const CompilerType &type) +{ + return type.GetTypeName() == ConstString("java::lang::String"); +} + +uint64_t +JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx, const CompilerType &type, ValueObject &in_value) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type.GetOpaqueQualType()))) + return obj->CalculateDynamicTypeId(exe_ctx, in_value); + return UINT64_MAX; +} + +ConstString +JavaASTContext::GetLinkageName(const CompilerType &type) +{ + if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type.GetOpaqueQualType()))) + return obj->GetLinkageName(); + return ConstString(); +}