forked from OSchip/llvm-project
Add a TypeSystem for Go
Add GoASTContext and DWARFASTParserGo to support go. Differential Revision: http://reviews.llvm.org/D12585 llvm-svn: 247629
This commit is contained in:
parent
3e13005031
commit
57bee1edfc
|
@ -1119,7 +1119,8 @@ protected:
|
|||
lldb::SymbolVendorUP m_symfile_ap; ///< A pointer to the symbol vendor for this module.
|
||||
std::vector<lldb::SymbolVendorUP> m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and changes the symbol file,
|
||||
///< we need to keep all old symbol files around in case anyone has type references to them
|
||||
lldb::ClangASTContextUP m_ast; ///< The AST context for this module.
|
||||
lldb::ClangASTContextUP m_ast; ///< The Clang AST context for this module.
|
||||
lldb::GoASTContextUP m_go_ast; ///< The Go AST context for this module.
|
||||
PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are
|
||||
lldb::SectionListUP m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info
|
||||
|
||||
|
|
|
@ -485,7 +485,6 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
// TypeSystem methods
|
||||
//------------------------------------------------------------------
|
||||
|
||||
DWARFASTParser *
|
||||
GetDWARFParser () override;
|
||||
|
||||
|
|
|
@ -318,7 +318,6 @@ public:
|
|||
|
||||
static lldb::BasicType
|
||||
GetBasicTypeEnumeration (const ConstString &name);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// If this type is an enumeration, iterate through all of its enumerators
|
||||
// using a callback. If the callback returns true, keep iterating, else
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
//===-- GoASTContext.h ------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __lldb__GoASTContext__
|
||||
#define __lldb__GoASTContext__
|
||||
|
||||
#include <map>
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Symbol/TypeSystem.h"
|
||||
#include "lldb/Symbol/CompilerType.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
|
||||
class Declaration;
|
||||
class GoType;
|
||||
|
||||
class GoASTContext : public TypeSystem
|
||||
{
|
||||
public:
|
||||
GoASTContext();
|
||||
~GoASTContext();
|
||||
|
||||
DWARFASTParser *GetDWARFParser() override;
|
||||
|
||||
void
|
||||
SetAddressByteSize(int byte_size)
|
||||
{
|
||||
m_pointer_byte_size = byte_size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// llvm casting support
|
||||
//------------------------------------------------------------------
|
||||
static bool classof(const TypeSystem *ts)
|
||||
{
|
||||
return ts->getKind() == TypeSystem::eKindGo;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// CompilerDeclContext functions
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual bool
|
||||
DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ConstString
|
||||
DeclContextGetName(void *opaque_decl_ctx) override
|
||||
{
|
||||
return ConstString();
|
||||
}
|
||||
|
||||
virtual bool
|
||||
DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, bool *is_instance_method_ptr,
|
||||
ConstString *language_object_name_ptr) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Creating Types
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
CompilerType CreateArrayType(const ConstString &name, const CompilerType &element_type, int64_t length);
|
||||
|
||||
CompilerType CreateBaseType(int go_kind, const ConstString &type_name_const_str, uint64_t byte_size);
|
||||
|
||||
// For interface, map, chan.
|
||||
CompilerType CreateTypedef(int kind, const ConstString &name, CompilerType impl);
|
||||
|
||||
CompilerType CreateVoidType(const ConstString &name);
|
||||
CompilerType CreateFunctionType(const lldb_private::ConstString &name, CompilerType *params, size_t params_count,
|
||||
bool is_variadic);
|
||||
|
||||
CompilerType CreateStructType(int kind, const ConstString &name, uint32_t byte_size);
|
||||
|
||||
void CompleteStructType(const CompilerType &type);
|
||||
|
||||
void AddFieldToStruct(const CompilerType &struct_type, const ConstString &name, const CompilerType &field_type,
|
||||
uint32_t byte_offset);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Tests
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
static bool IsGoString(const CompilerType &type);
|
||||
static bool IsGoSlice(const CompilerType &type);
|
||||
static bool IsGoInterface(const CompilerType &type);
|
||||
static bool IsDirectIface(uint8_t kind);
|
||||
static bool IsPointerKind(uint8_t kind);
|
||||
|
||||
virtual bool IsArrayType(void *type, CompilerType *element_type, uint64_t *size, bool *is_incomplete) override;
|
||||
|
||||
virtual bool IsAggregateType(void *type) override;
|
||||
|
||||
virtual bool IsCharType(void *type) override;
|
||||
|
||||
virtual bool IsCompleteType(void *type) override;
|
||||
|
||||
virtual bool IsDefined(void *type) override;
|
||||
|
||||
virtual bool IsFloatingPointType(void *type, uint32_t &count, bool &is_complex) override;
|
||||
|
||||
virtual bool IsFunctionType(void *type, bool *is_variadic_ptr = NULL) override;
|
||||
|
||||
virtual size_t GetNumberOfFunctionArguments(void *type) override;
|
||||
|
||||
virtual CompilerType GetFunctionArgumentAtIndex(void *type, const size_t index) override;
|
||||
|
||||
virtual bool IsFunctionPointerType(void *type) override;
|
||||
|
||||
virtual bool IsIntegerType(void *type, bool &is_signed) override;
|
||||
|
||||
virtual bool IsPossibleDynamicType(void *type,
|
||||
CompilerType *target_type, // Can pass NULL
|
||||
bool check_cplusplus, bool check_objc) override;
|
||||
|
||||
virtual bool IsPointerType(void *type, CompilerType *pointee_type = NULL) override;
|
||||
|
||||
virtual bool IsScalarType(void *type) override;
|
||||
|
||||
virtual bool IsVoidType(void *type) override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Type Completion
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual bool GetCompleteType(void *type) override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// AST related queries
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual uint32_t GetPointerByteSize() override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Accessors
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual ConstString GetTypeName(void *type) override;
|
||||
|
||||
virtual uint32_t GetTypeInfo(void *type, CompilerType *pointee_or_element_clang_type = NULL) override;
|
||||
|
||||
virtual lldb::LanguageType GetMinimumLanguage(void *type) override;
|
||||
|
||||
virtual lldb::TypeClass GetTypeClass(void *type) override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Creating related types
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual CompilerType GetArrayElementType(void *type, uint64_t *stride = nullptr) override;
|
||||
|
||||
virtual CompilerType GetCanonicalType(void *type) override;
|
||||
|
||||
// Returns -1 if this isn't a function of if the function doesn't have a prototype
|
||||
// Returns a value >= 0 if there is a prototype.
|
||||
virtual int GetFunctionArgumentCount(void *type) override;
|
||||
|
||||
virtual CompilerType GetFunctionArgumentTypeAtIndex(void *type, size_t idx) override;
|
||||
|
||||
virtual CompilerType GetFunctionReturnType(void *type) override;
|
||||
|
||||
virtual size_t GetNumMemberFunctions(void *type) override;
|
||||
|
||||
virtual TypeMemberFunctionImpl GetMemberFunctionAtIndex(void *type, size_t idx) override;
|
||||
|
||||
virtual CompilerType GetPointeeType(void *type) override;
|
||||
|
||||
virtual CompilerType GetPointerType(void *type) override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Exploring the type
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual uint64_t GetBitSize(void *type, ExecutionContextScope *exe_scope) override;
|
||||
|
||||
virtual lldb::Encoding GetEncoding(void *type, uint64_t &count) override;
|
||||
|
||||
virtual lldb::Format GetFormat(void *type) override;
|
||||
|
||||
virtual uint32_t GetNumChildren(void *type, bool omit_empty_base_classes) override;
|
||||
|
||||
virtual lldb::BasicType GetBasicTypeEnumeration(void *type) override;
|
||||
virtual CompilerType GetIntTypeFromBitSize (size_t bit_size, bool is_signed) override;
|
||||
virtual CompilerType GetFloatTypeFromBitSize (size_t bit_size) override;
|
||||
|
||||
|
||||
virtual uint32_t GetNumFields(void *type) override;
|
||||
|
||||
virtual CompilerType GetFieldAtIndex(void *type, size_t idx, std::string &name, uint64_t *bit_offset_ptr,
|
||||
uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) override;
|
||||
|
||||
virtual uint32_t
|
||||
GetNumDirectBaseClasses(void *type) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual uint32_t
|
||||
GetNumVirtualBaseClasses(void *type) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual CompilerType
|
||||
GetDirectBaseClassAtIndex(void *type, size_t idx, uint32_t *bit_offset_ptr) override
|
||||
{
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
virtual CompilerType
|
||||
GetVirtualBaseClassAtIndex(void *type, size_t idx, uint32_t *bit_offset_ptr) override
|
||||
{
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
virtual CompilerType GetChildClangTypeAtIndex(void *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) override;
|
||||
|
||||
// Lookup a child given a name. This function will match base class names
|
||||
// and member member names in "clang_type" only, not descendants.
|
||||
virtual uint32_t GetIndexOfChildWithName(void *type, const char *name, bool omit_empty_base_classes) override;
|
||||
|
||||
// Lookup a child member given a name. This function will match member names
|
||||
// only and will descend into "clang_type" children in search for the first
|
||||
// member in this class, or any base class that matches "name".
|
||||
// TODO: Return all matches for a given name by returning a vector<vector<uint32_t>>
|
||||
// so we catch all names that match a given child name, not just the first.
|
||||
virtual size_t GetIndexOfChildMemberWithName(void *type, const char *name, bool omit_empty_base_classes,
|
||||
std::vector<uint32_t> &child_indexes) override;
|
||||
|
||||
virtual size_t
|
||||
GetNumTemplateArguments(void *type) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual CompilerType
|
||||
GetTemplateArgument(void *type, size_t idx, lldb::TemplateArgumentKind &kind) override
|
||||
{
|
||||
return CompilerType();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Dumping types
|
||||
//----------------------------------------------------------------------
|
||||
virtual void DumpValue(void *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;
|
||||
|
||||
virtual bool DumpTypeValue(void *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;
|
||||
|
||||
virtual void DumpTypeDescription(void *type) override; // Dump to stdout
|
||||
|
||||
virtual void DumpTypeDescription(void *type, Stream *s) override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// TODO: These methods appear unused. Should they be removed?
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual bool IsRuntimeGeneratedType(void *type) override;
|
||||
|
||||
virtual void DumpSummary(void *type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data,
|
||||
lldb::offset_t data_offset, size_t data_byte_size) override;
|
||||
|
||||
// Converts "s" to a floating point value and place resulting floating
|
||||
// point bytes in the "dst" buffer.
|
||||
virtual size_t ConvertStringToFloatValue(void *type, const char *s, uint8_t *dst, size_t dst_size) override;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// TODO: Determine if these methods should move to ClangASTContext.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual bool IsPointerOrReferenceType(void *type, CompilerType *pointee_type = NULL) override;
|
||||
|
||||
virtual unsigned GetTypeQualifiers(void *type) override;
|
||||
|
||||
virtual bool IsCStringType(void *type, uint32_t &length) override;
|
||||
|
||||
virtual size_t GetTypeBitAlign(void *type) override;
|
||||
|
||||
virtual CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
|
||||
|
||||
virtual bool IsBeingDefined(void *type) override;
|
||||
|
||||
virtual bool IsConst(void *type) override;
|
||||
|
||||
virtual uint32_t IsHomogeneousAggregate(void *type, CompilerType *base_type_ptr) override;
|
||||
|
||||
virtual bool IsPolymorphicClass(void *type) override;
|
||||
|
||||
virtual bool IsTypedefType(void *type) override;
|
||||
|
||||
// If the current object represents a typedef type, get the underlying type
|
||||
virtual CompilerType GetTypedefedType(void *type) override;
|
||||
|
||||
virtual bool IsVectorType(void *type, CompilerType *element_type, uint64_t *size) override;
|
||||
|
||||
virtual CompilerType GetFullyUnqualifiedType(void *type) override;
|
||||
|
||||
virtual CompilerType GetNonReferenceType(void *type) override;
|
||||
|
||||
virtual bool IsReferenceType(void *type, CompilerType *pointee_type = nullptr, bool *is_rvalue = nullptr) override;
|
||||
|
||||
private:
|
||||
typedef std::map<ConstString, std::unique_ptr<GoType>> TypeMap;
|
||||
int m_pointer_byte_size;
|
||||
int m_int_byte_size;
|
||||
std::unique_ptr<TypeMap> m_types;
|
||||
std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
|
||||
|
||||
GoASTContext(const GoASTContext &) = delete;
|
||||
const GoASTContext &operator=(const GoASTContext &) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* defined(__lldb__GoASTContext__) */
|
|
@ -99,6 +99,7 @@ class File;
|
|||
class FileSpec;
|
||||
class FileSpecList;
|
||||
class Flags;
|
||||
class GoASTContext;
|
||||
class TypeCategoryImpl;
|
||||
class FormatManager;
|
||||
class FormattersMatchCandidate;
|
||||
|
@ -326,6 +327,7 @@ namespace lldb {
|
|||
typedef std::shared_ptr<lldb_private::File> FileSP;
|
||||
typedef std::shared_ptr<lldb_private::Function> FunctionSP;
|
||||
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
|
||||
typedef std::unique_ptr<lldb_private::GoASTContext> GoASTContextUP;
|
||||
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
|
||||
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
|
||||
typedef std::shared_ptr<lldb_private::InstrumentationRuntime> InstrumentationRuntimeSP;
|
||||
|
|
|
@ -814,6 +814,8 @@
|
|||
9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; };
|
||||
9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; };
|
||||
A36FF33C17D8E94600244D40 /* OptionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A36FF33B17D8E94600244D40 /* OptionParser.cpp */; };
|
||||
AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */; };
|
||||
AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */; };
|
||||
AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEEA34041AC88A7400AB639D /* TypeSystem.cpp */; };
|
||||
AF061F87182C97ED00B6A19C /* RegisterContextHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */; };
|
||||
AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0C112718580CD800C4C45B /* QueueItem.cpp */; };
|
||||
|
@ -2611,8 +2613,12 @@
|
|||
9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBBreakpointLocation.cpp; path = source/API/SBBreakpointLocation.cpp; sourceTree = "<group>"; };
|
||||
A36FF33B17D8E94600244D40 /* OptionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionParser.cpp; sourceTree = "<group>"; };
|
||||
A36FF33D17D8E98800244D40 /* OptionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionParser.h; path = include/lldb/Host/OptionParser.h; sourceTree = "<group>"; };
|
||||
AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserGo.cpp; sourceTree = "<group>"; };
|
||||
AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserGo.h; sourceTree = "<group>"; };
|
||||
AEEA33F61AC74FE700AB639D /* TypeSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TypeSystem.h; path = include/lldb/Symbol/TypeSystem.h; sourceTree = "<group>"; };
|
||||
AEEA34041AC88A7400AB639D /* TypeSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSystem.cpp; path = source/Symbol/TypeSystem.cpp; sourceTree = "<group>"; };
|
||||
AEEA340F1ACA08A000AB639D /* GoASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoASTContext.h; path = include/lldb/Symbol/GoASTContext.h; sourceTree = "<group>"; };
|
||||
AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoASTContext.cpp; path = source/Symbol/GoASTContext.cpp; sourceTree = "<group>"; };
|
||||
AF061F85182C97ED00B6A19C /* RegisterContextHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextHistory.cpp; path = Utility/RegisterContextHistory.cpp; sourceTree = "<group>"; };
|
||||
AF061F86182C97ED00B6A19C /* RegisterContextHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextHistory.h; path = Utility/RegisterContextHistory.h; sourceTree = "<group>"; };
|
||||
AF061F89182C980000B6A19C /* HistoryThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryThread.h; path = Utility/HistoryThread.h; sourceTree = "<group>"; };
|
||||
|
@ -3124,6 +3130,8 @@
|
|||
269DDD451B8FD01A00D0DBD8 /* DWARFASTParser.h */,
|
||||
269DDD491B8FD1C300D0DBD8 /* DWARFASTParserClang.h */,
|
||||
269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */,
|
||||
AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */,
|
||||
AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */,
|
||||
260C89B610F57C5600BB2B04 /* DWARFAttribute.h */,
|
||||
266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */,
|
||||
260C89B710F57C5600BB2B04 /* DWARFCompileUnit.cpp */,
|
||||
|
@ -4208,6 +4216,8 @@
|
|||
26BC7F1810F1B8EC00F91463 /* Function.cpp */,
|
||||
269FF07D12494F7D00225026 /* FuncUnwinders.h */,
|
||||
961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */,
|
||||
AEEA340F1ACA08A000AB639D /* GoASTContext.h */,
|
||||
AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */,
|
||||
26BC7C5B10F1B6E900F91463 /* LineEntry.h */,
|
||||
26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */,
|
||||
26BC7C5C10F1B6E900F91463 /* LineTable.h */,
|
||||
|
@ -6314,6 +6324,7 @@
|
|||
2689007C13353E1A00698AC0 /* Symbols.cpp in Sources */,
|
||||
2689007D13353E2200698AC0 /* Args.cpp in Sources */,
|
||||
2689007F13353E2200698AC0 /* CommandCompletions.cpp in Sources */,
|
||||
AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */,
|
||||
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */,
|
||||
26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
|
||||
2689008013353E2200698AC0 /* CommandInterpreter.cpp in Sources */,
|
||||
|
@ -6630,6 +6641,7 @@
|
|||
260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */,
|
||||
49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */,
|
||||
260CC64D15D0440D002BF2E0 /* OptionValueEnumeration.cpp in Sources */,
|
||||
AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */,
|
||||
260CC64E15D0440D002BF2E0 /* OptionValueFileSpec.cpp in Sources */,
|
||||
AF2BCA6C18C7EFDE005B4526 /* JITLoaderGDB.cpp in Sources */,
|
||||
260CC64F15D0440D002BF2E0 /* OptionValueFileSpecLIst.cpp in Sources */,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "lldb/Interpreter/ScriptInterpreter.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
#include "lldb/Symbol/CompileUnit.h"
|
||||
#include "lldb/Symbol/GoASTContext.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/SymbolContext.h"
|
||||
#include "lldb/Symbol/SymbolVendor.h"
|
||||
|
@ -148,6 +149,7 @@ Module::Module (const ModuleSpec &module_spec) :
|
|||
m_objfile_sp (),
|
||||
m_symfile_ap (),
|
||||
m_ast (new ClangASTContext),
|
||||
m_go_ast(),
|
||||
m_source_mappings (),
|
||||
m_sections_ap(),
|
||||
m_did_load_objfile (false),
|
||||
|
@ -252,6 +254,7 @@ Module::Module(const FileSpec& file_spec,
|
|||
m_objfile_sp (),
|
||||
m_symfile_ap (),
|
||||
m_ast (new ClangASTContext),
|
||||
m_go_ast(),
|
||||
m_source_mappings (),
|
||||
m_sections_ap(),
|
||||
m_did_load_objfile (false),
|
||||
|
@ -298,6 +301,7 @@ Module::Module () :
|
|||
m_objfile_sp (),
|
||||
m_symfile_ap (),
|
||||
m_ast (new ClangASTContext),
|
||||
m_go_ast(),
|
||||
m_source_mappings (),
|
||||
m_sections_ap(),
|
||||
m_did_load_objfile (false),
|
||||
|
@ -420,7 +424,22 @@ Module::GetUUID()
|
|||
TypeSystem *
|
||||
Module::GetTypeSystemForLanguage (LanguageType language)
|
||||
{
|
||||
if (language != eLanguageTypeSwift)
|
||||
if (language == eLanguageTypeGo)
|
||||
{
|
||||
Mutex::Locker locker (m_mutex);
|
||||
if (!m_go_ast)
|
||||
{
|
||||
ObjectFile * objfile = GetObjectFile();
|
||||
ArchSpec object_arch;
|
||||
if (objfile && objfile->GetArchitecture(object_arch))
|
||||
{
|
||||
m_go_ast.reset(new GoASTContext);
|
||||
m_go_ast->SetAddressByteSize(object_arch.GetAddressByteSize());
|
||||
}
|
||||
}
|
||||
return m_go_ast.get();
|
||||
}
|
||||
else if (language != eLanguageTypeSwift)
|
||||
{
|
||||
// For now assume all languages except swift use the ClangASTContext for types
|
||||
return &GetClangASTContext();
|
||||
|
|
|
@ -2,6 +2,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF
|
|||
DIERef.cpp
|
||||
DWARFAbbreviationDeclaration.cpp
|
||||
DWARFASTParserClang.cpp
|
||||
DWARFASTParserGo.cpp
|
||||
DWARFAttribute.cpp
|
||||
DWARFCompileUnit.cpp
|
||||
DWARFDataExtractor.cpp
|
||||
|
|
|
@ -0,0 +1,828 @@
|
|||
//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DWARFASTParserGo.h"
|
||||
|
||||
#include "DWARFASTParserGo.h"
|
||||
#include "DWARFCompileUnit.h"
|
||||
#include "DWARFDebugInfo.h"
|
||||
#include "DWARFDeclContext.h"
|
||||
#include "DWARFDefines.h"
|
||||
#include "DWARFDIE.h"
|
||||
#include "DWARFDIECollection.h"
|
||||
#include "SymbolFileDWARF.h"
|
||||
#include "SymbolFileDWARFDebugMap.h"
|
||||
#include "UniqueDWARFASTType.h"
|
||||
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/Value.h"
|
||||
#include "lldb/Symbol/CompileUnit.h"
|
||||
#include "lldb/Symbol/Function.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/TypeList.h"
|
||||
|
||||
//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
|
||||
|
||||
#ifdef ENABLE_DEBUG_PRINTF
|
||||
#include <stdio.h>
|
||||
#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define DW_AT_go_kind 0x2900
|
||||
#define DW_AT_go_key 0x2901
|
||||
#define DW_AT_go_elem 0x2902
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast)
|
||||
: m_ast(ast)
|
||||
{
|
||||
}
|
||||
|
||||
DWARFASTParserGo::~DWARFASTParserGo()
|
||||
{
|
||||
}
|
||||
|
||||
TypeSP
|
||||
DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
|
||||
bool *type_is_new_ptr)
|
||||
{
|
||||
TypeSP type_sp;
|
||||
|
||||
if (type_is_new_ptr)
|
||||
*type_is_new_ptr = false;
|
||||
|
||||
if (die)
|
||||
{
|
||||
SymbolFileDWARF *dwarf = die.GetDWARF();
|
||||
if (log)
|
||||
{
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessage(
|
||||
log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(),
|
||||
DW_TAG_value_to_name(die.Tag()), die.GetName());
|
||||
}
|
||||
|
||||
Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
|
||||
TypeList *type_list = dwarf->GetTypeList();
|
||||
if (type_ptr == NULL)
|
||||
{
|
||||
if (type_is_new_ptr)
|
||||
*type_is_new_ptr = true;
|
||||
|
||||
const dw_tag_t tag = die.Tag();
|
||||
|
||||
bool is_forward_declaration = false;
|
||||
DWARFAttributes attributes;
|
||||
const char *type_name_cstr = NULL;
|
||||
ConstString type_name_const_str;
|
||||
Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
|
||||
uint64_t byte_size = 0;
|
||||
uint64_t go_kind = 0;
|
||||
Declaration decl;
|
||||
|
||||
Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
|
||||
CompilerType clang_type;
|
||||
DWARFFormValue form_value;
|
||||
|
||||
dw_attr_t attr;
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_base_type:
|
||||
case DW_TAG_pointer_type:
|
||||
case DW_TAG_typedef:
|
||||
case DW_TAG_unspecified_type:
|
||||
{
|
||||
// Set a bit that lets us know that we are currently parsing this
|
||||
dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
|
||||
|
||||
const size_t num_attributes = die.GetAttributes(attributes);
|
||||
uint32_t encoding = 0;
|
||||
lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
|
||||
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_attributes; ++i)
|
||||
{
|
||||
attr = attributes.AttributeAtIndex(i);
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_name:
|
||||
type_name_cstr = form_value.AsCString();
|
||||
if (type_name_cstr)
|
||||
type_name_const_str.SetCString(type_name_cstr);
|
||||
break;
|
||||
case DW_AT_byte_size:
|
||||
byte_size = form_value.Unsigned();
|
||||
break;
|
||||
case DW_AT_encoding:
|
||||
encoding = form_value.Unsigned();
|
||||
break;
|
||||
case DW_AT_type:
|
||||
encoding_uid = form_value.Reference();
|
||||
break;
|
||||
case DW_AT_go_kind:
|
||||
go_kind = form_value.Unsigned();
|
||||
break;
|
||||
default:
|
||||
// Do we care about DW_AT_go_key or DW_AT_go_elem?
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()),
|
||||
DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case DW_TAG_unspecified_type:
|
||||
resolve_state = Type::eResolveStateFull;
|
||||
clang_type = m_ast.CreateVoidType(type_name_const_str);
|
||||
break;
|
||||
|
||||
case DW_TAG_base_type:
|
||||
resolve_state = Type::eResolveStateFull;
|
||||
clang_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
|
||||
break;
|
||||
|
||||
case DW_TAG_pointer_type:
|
||||
encoding_data_type = Type::eEncodingIsPointerUID;
|
||||
break;
|
||||
case DW_TAG_typedef:
|
||||
encoding_data_type = Type::eEncodingIsTypedefUID;
|
||||
CompilerType impl;
|
||||
Type *type = dwarf->ResolveTypeUID(encoding_uid);
|
||||
if (type)
|
||||
{
|
||||
if (go_kind == 0 && type->GetName() == type_name_const_str)
|
||||
{
|
||||
// Go emits extra typedefs as a forward declaration. Ignore these.
|
||||
dwarf->m_die_to_type[die.GetDIE()] = type;
|
||||
return type->shared_from_this();
|
||||
}
|
||||
impl = type->GetForwardCompilerType();
|
||||
clang_type = m_ast.CreateTypedef(go_kind, type_name_const_str, impl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
|
||||
NULL, encoding_uid, encoding_data_type, &decl, clang_type, resolve_state));
|
||||
|
||||
dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_TAG_structure_type:
|
||||
{
|
||||
// Set a bit that lets us know that we are currently parsing this
|
||||
dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
|
||||
bool byte_size_valid = false;
|
||||
|
||||
const size_t num_attributes = die.GetAttributes(attributes);
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_attributes; ++i)
|
||||
{
|
||||
attr = attributes.AttributeAtIndex(i);
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_name:
|
||||
type_name_cstr = form_value.AsCString();
|
||||
type_name_const_str.SetCString(type_name_cstr);
|
||||
break;
|
||||
|
||||
case DW_AT_byte_size:
|
||||
byte_size = form_value.Unsigned();
|
||||
byte_size_valid = true;
|
||||
break;
|
||||
|
||||
case DW_AT_go_kind:
|
||||
go_kind = form_value.Unsigned();
|
||||
break;
|
||||
|
||||
// TODO: Should we use SLICETYPE's DW_AT_go_elem?
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(ribrdb): Do we need this?
|
||||
|
||||
// UniqueDWARFASTType is large, so don't create a local variables on the
|
||||
// stack, put it on the heap. This function is often called recursively
|
||||
// and clang isn't good and sharing the stack space for variables in different blocks.
|
||||
std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
|
||||
|
||||
// Only try and unique the type if it has a name.
|
||||
if (type_name_const_str &&
|
||||
dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
|
||||
byte_size_valid ? byte_size : -1, *unique_ast_entry_ap))
|
||||
{
|
||||
// We have already parsed this type or from another
|
||||
// compile unit. GCC loves to use the "one definition
|
||||
// rule" which can result in multiple definitions
|
||||
// of the same class over and over in each compile
|
||||
// unit.
|
||||
type_sp = unique_ast_entry_ap->m_type_sp;
|
||||
if (type_sp)
|
||||
{
|
||||
dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
|
||||
return type_sp;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
|
||||
DW_TAG_value_to_name(tag), type_name_cstr);
|
||||
|
||||
bool clang_type_was_created = false;
|
||||
clang_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
|
||||
if (!clang_type)
|
||||
{
|
||||
clang_type_was_created = true;
|
||||
clang_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
|
||||
}
|
||||
|
||||
type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
|
||||
NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, clang_type,
|
||||
Type::eResolveStateForward));
|
||||
|
||||
// Add our type to the unique type map so we don't
|
||||
// end up creating many copies of the same type over
|
||||
// and over in the ASTContext for our module
|
||||
unique_ast_entry_ap->m_type_sp = type_sp;
|
||||
unique_ast_entry_ap->m_die = die;
|
||||
unique_ast_entry_ap->m_declaration = decl;
|
||||
unique_ast_entry_ap->m_byte_size = byte_size;
|
||||
dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap);
|
||||
|
||||
if (!is_forward_declaration)
|
||||
{
|
||||
// Always start the definition for a class type so that
|
||||
// if the class has child classes or types that require
|
||||
// the class to be created for use as their decl contexts
|
||||
// the class will be ready to accept these child definitions.
|
||||
if (die.HasChildren() == false)
|
||||
{
|
||||
// No children for this struct/union/class, lets finish it
|
||||
m_ast.CompleteStructType(clang_type);
|
||||
}
|
||||
else if (clang_type_was_created)
|
||||
{
|
||||
// Leave this as a forward declaration until we need
|
||||
// to know the details of the type. lldb_private::Type
|
||||
// will automatically call the SymbolFile virtual function
|
||||
// "SymbolFileDWARF::CompleteType(Type *)"
|
||||
// When the definition needs to be defined.
|
||||
dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = clang_type.GetOpaqueQualType();
|
||||
dwarf->m_forward_decl_clang_type_to_die[clang_type.GetOpaqueQualType()] = die.GetDIERef();
|
||||
// SetHasExternalStorage (clang_type.GetOpaqueQualType(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_TAG_subprogram:
|
||||
case DW_TAG_subroutine_type:
|
||||
{
|
||||
// Set a bit that lets us know that we are currently parsing this
|
||||
dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
|
||||
|
||||
bool is_variadic = false;
|
||||
clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern
|
||||
|
||||
const size_t num_attributes = die.GetAttributes(attributes);
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_attributes; ++i)
|
||||
{
|
||||
attr = attributes.AttributeAtIndex(i);
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_name:
|
||||
type_name_cstr = form_value.AsCString();
|
||||
type_name_const_str.SetCString(type_name_cstr);
|
||||
break;
|
||||
|
||||
case DW_AT_external:
|
||||
if (form_value.Unsigned())
|
||||
{
|
||||
if (storage == clang::SC_None)
|
||||
storage = clang::SC_Extern;
|
||||
else
|
||||
storage = clang::SC_PrivateExtern;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_AT_high_pc:
|
||||
case DW_AT_low_pc:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
|
||||
DW_TAG_value_to_name(tag), type_name_cstr);
|
||||
|
||||
std::vector<CompilerType> function_param_types;
|
||||
|
||||
// Parse the function children for the parameters
|
||||
|
||||
if (die.HasChildren())
|
||||
{
|
||||
ParseChildParameters(sc, die, is_variadic, function_param_types);
|
||||
}
|
||||
|
||||
// clang_type will get the function prototype clang type after this call
|
||||
clang_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(),
|
||||
function_param_types.size(), is_variadic);
|
||||
|
||||
type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL,
|
||||
LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, clang_type,
|
||||
Type::eResolveStateFull));
|
||||
assert(type_sp.get());
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_TAG_array_type:
|
||||
{
|
||||
// Set a bit that lets us know that we are currently parsing this
|
||||
dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
|
||||
|
||||
lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
|
||||
int64_t first_index = 0;
|
||||
uint32_t byte_stride = 0;
|
||||
uint32_t bit_stride = 0;
|
||||
const size_t num_attributes = die.GetAttributes(attributes);
|
||||
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_attributes; ++i)
|
||||
{
|
||||
attr = attributes.AttributeAtIndex(i);
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_name:
|
||||
type_name_cstr = form_value.AsCString();
|
||||
type_name_const_str.SetCString(type_name_cstr);
|
||||
break;
|
||||
|
||||
case DW_AT_type:
|
||||
type_die_offset = form_value.Reference();
|
||||
break;
|
||||
case DW_AT_byte_size:
|
||||
break; // byte_size = form_value.Unsigned(); break;
|
||||
case DW_AT_go_kind:
|
||||
go_kind = form_value.Unsigned();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
|
||||
DW_TAG_value_to_name(tag), type_name_cstr);
|
||||
|
||||
Type *element_type = dwarf->ResolveTypeUID(type_die_offset);
|
||||
|
||||
if (element_type)
|
||||
{
|
||||
std::vector<uint64_t> element_orders;
|
||||
ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
|
||||
if (byte_stride == 0)
|
||||
byte_stride = element_type->GetByteSize();
|
||||
CompilerType array_element_type = element_type->GetForwardCompilerType();
|
||||
if (element_orders.size() > 0)
|
||||
{
|
||||
if (element_orders.size() > 1)
|
||||
printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr);
|
||||
clang_type =
|
||||
m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
clang_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0);
|
||||
}
|
||||
type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str,
|
||||
byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl,
|
||||
clang_type, Type::eResolveStateFull));
|
||||
type_sp->SetEncodingType(element_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), "
|
||||
"please file a bug and attach the file at the "
|
||||
"start of this error message",
|
||||
die.GetOffset(), tag, DW_TAG_value_to_name(tag));
|
||||
break;
|
||||
}
|
||||
|
||||
if (type_sp.get())
|
||||
{
|
||||
DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
|
||||
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
|
||||
|
||||
SymbolContextScope *symbol_context_scope = NULL;
|
||||
if (sc_parent_tag == DW_TAG_compile_unit)
|
||||
{
|
||||
symbol_context_scope = sc.comp_unit;
|
||||
}
|
||||
else if (sc.function != NULL && sc_parent_die)
|
||||
{
|
||||
symbol_context_scope =
|
||||
sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset()));
|
||||
if (symbol_context_scope == NULL)
|
||||
symbol_context_scope = sc.function;
|
||||
}
|
||||
|
||||
if (symbol_context_scope != NULL)
|
||||
{
|
||||
type_sp->SetSymbolContextScope(symbol_context_scope);
|
||||
}
|
||||
|
||||
// We are ready to put this type into the uniqued list up at the module level
|
||||
type_list->Insert(type_sp);
|
||||
|
||||
dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
|
||||
}
|
||||
}
|
||||
else if (type_ptr != DIE_IS_BEING_PARSED)
|
||||
{
|
||||
type_sp = type_ptr->shared_from_this();
|
||||
}
|
||||
}
|
||||
return type_sp;
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc,
|
||||
|
||||
const DWARFDIE &parent_die, bool &is_variadic,
|
||||
std::vector<CompilerType> &function_param_types)
|
||||
{
|
||||
if (!parent_die)
|
||||
return 0;
|
||||
|
||||
size_t arg_idx = 0;
|
||||
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
|
||||
{
|
||||
|
||||
dw_tag_t tag = die.Tag();
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_formal_parameter:
|
||||
{
|
||||
DWARFAttributes attributes;
|
||||
const size_t num_attributes = die.GetAttributes(attributes);
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
const char *name = NULL;
|
||||
Declaration decl;
|
||||
dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_attributes; ++i)
|
||||
{
|
||||
const dw_attr_t attr = attributes.AttributeAtIndex(i);
|
||||
DWARFFormValue form_value;
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_name:
|
||||
name = form_value.AsCString();
|
||||
break;
|
||||
case DW_AT_type:
|
||||
param_type_die_offset = form_value.Reference();
|
||||
break;
|
||||
case DW_AT_location:
|
||||
// if (form_value.BlockData())
|
||||
// {
|
||||
// const DWARFDataExtractor& debug_info_data =
|
||||
// debug_info();
|
||||
// uint32_t block_length = form_value.Unsigned();
|
||||
// DWARFDataExtractor location(debug_info_data,
|
||||
// form_value.BlockData() - debug_info_data.GetDataStart(),
|
||||
// block_length);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type *type = parent_die.ResolveTypeUID(param_type_die_offset);
|
||||
if (type)
|
||||
{
|
||||
function_param_types.push_back(type->GetForwardCompilerType());
|
||||
}
|
||||
}
|
||||
arg_idx++;
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_TAG_unspecified_parameters:
|
||||
is_variadic = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return arg_idx;
|
||||
}
|
||||
|
||||
void
|
||||
DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
|
||||
std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
|
||||
uint32_t &bit_stride)
|
||||
{
|
||||
if (!parent_die)
|
||||
return;
|
||||
|
||||
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
|
||||
{
|
||||
const dw_tag_t tag = die.Tag();
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_subrange_type:
|
||||
{
|
||||
DWARFAttributes attributes;
|
||||
const size_t num_child_attributes = die.GetAttributes(attributes);
|
||||
if (num_child_attributes > 0)
|
||||
{
|
||||
uint64_t num_elements = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_child_attributes; ++i)
|
||||
{
|
||||
const dw_attr_t attr = attributes.AttributeAtIndex(i);
|
||||
DWARFFormValue form_value;
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case DW_AT_count:
|
||||
num_elements = form_value.Unsigned();
|
||||
break;
|
||||
|
||||
default:
|
||||
case DW_AT_type:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
element_orders.push_back(num_elements);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &clang_type)
|
||||
{
|
||||
if (!die)
|
||||
return false;
|
||||
|
||||
const dw_tag_t tag = die.Tag();
|
||||
|
||||
SymbolFileDWARF *dwarf = die.GetDWARF();
|
||||
Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
|
||||
if (log)
|
||||
dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
|
||||
log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", dwarf->MakeUserID(die.GetOffset()),
|
||||
DW_TAG_value_to_name(tag), type->GetName().AsCString());
|
||||
assert(clang_type);
|
||||
DWARFAttributes attributes;
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_structure_type:
|
||||
{
|
||||
{
|
||||
if (die.HasChildren())
|
||||
{
|
||||
SymbolContext sc(die.GetLLDBCompileUnit());
|
||||
|
||||
ParseChildMembers(sc, die, clang_type);
|
||||
}
|
||||
}
|
||||
m_ast.CompleteStructType(clang_type);
|
||||
return (bool)clang_type;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false && "not a forward go type decl!");
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_clang_type)
|
||||
{
|
||||
size_t count = 0;
|
||||
uint32_t member_idx = 0;
|
||||
|
||||
ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
|
||||
GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_clang_type.GetTypeSystem());
|
||||
if (ast == nullptr)
|
||||
return 0;
|
||||
|
||||
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
|
||||
{
|
||||
dw_tag_t tag = die.Tag();
|
||||
|
||||
switch (tag)
|
||||
{
|
||||
case DW_TAG_member:
|
||||
{
|
||||
DWARFAttributes attributes;
|
||||
const size_t num_attributes = die.GetAttributes(attributes);
|
||||
if (num_attributes > 0)
|
||||
{
|
||||
Declaration decl;
|
||||
const char *name = NULL;
|
||||
|
||||
lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
|
||||
uint32_t member_byte_offset = UINT32_MAX;
|
||||
uint32_t i;
|
||||
for (i = 0; i < num_attributes; ++i)
|
||||
{
|
||||
const dw_attr_t attr = attributes.AttributeAtIndex(i);
|
||||
DWARFFormValue form_value;
|
||||
if (attributes.ExtractFormValueAtIndex(i, form_value))
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
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())
|
||||
{
|
||||
Value initialValue(0);
|
||||
Value memberOffset(0);
|
||||
const DWARFDataExtractor &debug_info_data =
|
||||
die.GetDWARF()->get_debug_info_data();
|
||||
uint32_t block_length = form_value.Unsigned();
|
||||
uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
|
||||
if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
|
||||
NULL, // ClangExpressionVariableList *
|
||||
NULL, // ClangExpressionDeclMap *
|
||||
NULL, // RegisterContext *
|
||||
module_sp, debug_info_data, die.GetCU(),
|
||||
block_offset, block_length, eRegisterKindDWARF,
|
||||
&initialValue, memberOffset, NULL))
|
||||
{
|
||||
member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// With DWARF 3 and later, if the value is an integer constant,
|
||||
// this form value is the offset in bytes from the beginning
|
||||
// of the containing entity.
|
||||
member_byte_offset = form_value.Unsigned();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Type *member_type = die.ResolveTypeUID(encoding_uid);
|
||||
if (member_type)
|
||||
{
|
||||
CompilerType member_go_type = member_type->GetFullCompilerType();
|
||||
ConstString name_const_str(name);
|
||||
m_ast.AddFieldToStruct(class_clang_type, name_const_str, member_go_type, member_byte_offset);
|
||||
}
|
||||
}
|
||||
++member_idx;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
Function *
|
||||
DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die)
|
||||
{
|
||||
DWARFRangeList func_ranges;
|
||||
const char *name = NULL;
|
||||
const char *mangled = NULL;
|
||||
int decl_file = 0;
|
||||
int decl_line = 0;
|
||||
int decl_column = 0;
|
||||
int call_file = 0;
|
||||
int call_line = 0;
|
||||
int call_column = 0;
|
||||
DWARFExpression frame_base(die.GetCU());
|
||||
|
||||
assert(die.Tag() == DW_TAG_subprogram);
|
||||
|
||||
if (die.Tag() != DW_TAG_subprogram)
|
||||
return NULL;
|
||||
|
||||
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())
|
||||
{
|
||||
Mangled func_name;
|
||||
func_name.SetValue(ConstString(name), false);
|
||||
|
||||
FunctionSP func_sp;
|
||||
std::unique_ptr<Declaration> 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));
|
||||
|
||||
SymbolFileDWARF *dwarf = die.GetDWARF();
|
||||
// Supply the type _only_ if it has already been parsed
|
||||
Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
|
||||
|
||||
assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
|
||||
|
||||
if (dwarf->FixupAddress(func_range.GetBaseAddress()))
|
||||
{
|
||||
const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset());
|
||||
func_sp.reset(new Function(sc.comp_unit,
|
||||
dwarf->MakeUserID(func_user_id), // UserID is the DIE offset
|
||||
dwarf->MakeUserID(func_user_id), func_name, func_type,
|
||||
func_range)); // first address range
|
||||
|
||||
if (func_sp.get() != NULL)
|
||||
{
|
||||
if (frame_base.IsValid())
|
||||
func_sp->GetFrameBaseExpression() = frame_base;
|
||||
sc.comp_unit->AddFunction(func_sp);
|
||||
return func_sp.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//===-- DWARFASTParserGo.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_DWARFASTParserGo_h_
|
||||
#define SymbolFileDWARF_DWARFASTParserGo_h_
|
||||
|
||||
#include "DWARFDefines.h"
|
||||
#include "DWARFASTParser.h"
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Symbol/GoASTContext.h"
|
||||
|
||||
class DWARFDebugInfoEntry;
|
||||
class DWARFDIECollection;
|
||||
|
||||
class DWARFASTParserGo : public DWARFASTParser
|
||||
{
|
||||
public:
|
||||
DWARFASTParserGo(lldb_private::GoASTContext &ast);
|
||||
|
||||
virtual ~DWARFASTParserGo();
|
||||
|
||||
lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
|
||||
bool *type_is_new_ptr) override;
|
||||
|
||||
virtual lldb_private::Function *ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
|
||||
const DWARFDIE &die) override;
|
||||
|
||||
virtual bool CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
|
||||
lldb_private::CompilerType &go_type) override;
|
||||
|
||||
virtual lldb_private::CompilerDeclContext
|
||||
GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override
|
||||
{
|
||||
return lldb_private::CompilerDeclContext();
|
||||
}
|
||||
|
||||
virtual lldb_private::CompilerDeclContext
|
||||
GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override
|
||||
{
|
||||
return lldb_private::CompilerDeclContext();
|
||||
}
|
||||
|
||||
private:
|
||||
size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic,
|
||||
std::vector<lldb_private::CompilerType> &function_param_types);
|
||||
void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
|
||||
std::vector<uint64_t> &element_orders, uint32_t &byte_stride, uint32_t &bit_stride);
|
||||
|
||||
size_t ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
|
||||
lldb_private::CompilerType &class_clang_type);
|
||||
|
||||
lldb_private::GoASTContext &m_ast;
|
||||
};
|
||||
|
||||
#endif // SymbolFileDWARF_DWARFASTParserGo_h_
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
#include "lldb/Symbol/Block.h"
|
||||
#include "lldb/Symbol/CompileUnit.h"
|
||||
#include "lldb/Symbol/GoASTContext.h"
|
||||
#include "lldb/Symbol/LineTable.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/SymbolVendor.h"
|
||||
|
@ -507,10 +508,18 @@ TypeSystem *
|
|||
SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language)
|
||||
{
|
||||
SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
|
||||
TypeSystem *type_system;
|
||||
if (debug_map_symfile)
|
||||
return debug_map_symfile->GetTypeSystemForLanguage (language);
|
||||
{
|
||||
type_system = debug_map_symfile->GetTypeSystemForLanguage(language);
|
||||
}
|
||||
else
|
||||
return m_obj_file->GetModule()->GetTypeSystemForLanguage (language);
|
||||
{
|
||||
type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
|
||||
if (type_system)
|
||||
type_system->SetSymbolFile(this);
|
||||
}
|
||||
return type_system;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
friend class DebugMapModule;
|
||||
friend class DWARFCompileUnit;
|
||||
friend class DWARFASTParserClang;
|
||||
friend class DWARFASTParserGo;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Static Functions
|
||||
|
|
|
@ -12,6 +12,7 @@ add_lldb_library(lldbSymbol
|
|||
DWARFCallFrameInfo.cpp
|
||||
Function.cpp
|
||||
FuncUnwinders.cpp
|
||||
GoASTContext.cpp
|
||||
LineEntry.cpp
|
||||
LineTable.cpp
|
||||
ObjectFile.cpp
|
||||
|
|
|
@ -3021,7 +3021,7 @@ ClangASTContext::IsObjCClassType (const CompilerType& type)
|
|||
bool
|
||||
ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type)
|
||||
{
|
||||
if (type)
|
||||
if (IsClangType(type))
|
||||
return GetCanonicalQualType(type)->isObjCObjectOrInterfaceType();
|
||||
return false;
|
||||
}
|
||||
|
@ -3269,12 +3269,14 @@ ClangASTContext::GetCXXClassName (const CompilerType& type, std::string &class_n
|
|||
if (type)
|
||||
{
|
||||
clang::QualType qual_type (GetCanonicalQualType(type));
|
||||
|
||||
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
if (!qual_type.isNull())
|
||||
{
|
||||
class_name.assign (cxx_record_decl->getIdentifier()->getNameStart());
|
||||
return true;
|
||||
clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl();
|
||||
if (cxx_record_decl)
|
||||
{
|
||||
class_name.assign(cxx_record_decl->getIdentifier()->getNameStart());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
class_name.clear();
|
||||
|
@ -3289,7 +3291,7 @@ ClangASTContext::IsCXXClassType (const CompilerType& type)
|
|||
return false;
|
||||
|
||||
clang::QualType qual_type (GetCanonicalQualType(type));
|
||||
if (qual_type->getAsCXXRecordDecl() != nullptr)
|
||||
if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -3313,8 +3315,8 @@ ClangASTContext::IsObjCObjectPointerType (const CompilerType& type, CompilerType
|
|||
return false;
|
||||
|
||||
clang::QualType qual_type (GetCanonicalQualType(type));
|
||||
|
||||
if (qual_type->isObjCObjectPointerType())
|
||||
|
||||
if (!qual_type.isNull() && qual_type->isObjCObjectPointerType())
|
||||
{
|
||||
if (class_type_ptr)
|
||||
{
|
||||
|
@ -3750,7 +3752,7 @@ ClangASTContext::GetTypeQualifiers(void* type)
|
|||
CompilerType
|
||||
ClangASTContext::AddConstModifier (const CompilerType& type)
|
||||
{
|
||||
if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
|
||||
if (IsClangType(type))
|
||||
{
|
||||
// Make sure this type is a clang AST type
|
||||
clang::QualType result(GetQualType(type));
|
||||
|
@ -3764,7 +3766,7 @@ ClangASTContext::AddConstModifier (const CompilerType& type)
|
|||
CompilerType
|
||||
ClangASTContext::AddRestrictModifier (const CompilerType& type)
|
||||
{
|
||||
if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
|
||||
if (IsClangType(type))
|
||||
{
|
||||
clang::QualType result(GetQualType(type));
|
||||
result.getQualifiers().setRestrict (true);
|
||||
|
@ -3776,7 +3778,7 @@ ClangASTContext::AddRestrictModifier (const CompilerType& type)
|
|||
CompilerType
|
||||
ClangASTContext::AddVolatileModifier (const CompilerType& type)
|
||||
{
|
||||
if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
|
||||
if (IsClangType(type))
|
||||
{
|
||||
clang::QualType result(GetQualType(type));
|
||||
result.getQualifiers().setVolatile (true);
|
||||
|
@ -4077,11 +4079,10 @@ ClangASTContext::GetMemberFunctionAtIndex (void* type, size_t idx)
|
|||
CompilerType
|
||||
ClangASTContext::GetLValueReferenceType (const CompilerType& type)
|
||||
{
|
||||
if (type)
|
||||
if (IsClangType(type))
|
||||
{
|
||||
ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
|
||||
if (ast)
|
||||
return CompilerType(ast->getASTContext(), ast->getASTContext()->getLValueReferenceType(GetQualType(type)));
|
||||
return CompilerType(ast->getASTContext(), ast->getASTContext()->getLValueReferenceType(GetQualType(type)));
|
||||
}
|
||||
return CompilerType();
|
||||
}
|
||||
|
@ -4089,11 +4090,10 @@ ClangASTContext::GetLValueReferenceType (const CompilerType& type)
|
|||
CompilerType
|
||||
ClangASTContext::GetRValueReferenceType (const CompilerType& type)
|
||||
{
|
||||
if (type)
|
||||
if (IsClangType(type))
|
||||
{
|
||||
ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
|
||||
if (ast)
|
||||
return CompilerType(ast->getASTContext(), ast->getASTContext()->getRValueReferenceType(GetQualType(type)));
|
||||
return CompilerType(ast->getASTContext(), ast->getASTContext()->getRValueReferenceType(GetQualType(type)));
|
||||
}
|
||||
return CompilerType();
|
||||
}
|
||||
|
@ -4186,7 +4186,7 @@ ClangASTContext::GetTypedefedType (void* type)
|
|||
CompilerType
|
||||
ClangASTContext::RemoveFastQualifiers (const CompilerType& type)
|
||||
{
|
||||
if (type && llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()))
|
||||
if (IsClangType(type))
|
||||
{
|
||||
clang::QualType qual_type(GetQualType(type));
|
||||
qual_type.getQualifiers().removeFastQualifiers();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -93,7 +93,10 @@ SymbolFile::GetClangASTContext ()
|
|||
TypeSystem *
|
||||
SymbolFile::GetTypeSystemForLanguage (lldb::LanguageType language)
|
||||
{
|
||||
return m_obj_file->GetModule()->GetTypeSystemForLanguage (language);
|
||||
TypeSystem *type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
|
||||
if (type_system)
|
||||
type_system->SetSymbolFile(this);
|
||||
return type_system;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
"""Test the go DWARF type parsing."""
|
||||
|
||||
import os, time
|
||||
import unittest2
|
||||
import lldb
|
||||
import lldbutil
|
||||
from lldbtest import *
|
||||
|
||||
class TestGoASTContext(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@python_api_test
|
||||
@skipUnlessGoInstalled
|
||||
def test_with_dsym_and_python_api(self):
|
||||
"""Test GoASTContext dwarf parsing."""
|
||||
self.buildGo()
|
||||
self.launchProcess()
|
||||
self.go_builtin_types()
|
||||
self.check_main_vars()
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
# Find the line numbers to break inside main().
|
||||
self.main_source = "main.go"
|
||||
self.break_line = line_number(self.main_source, '// Set breakpoint here.')
|
||||
|
||||
def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin):
|
||||
tl = self.target().FindTypes(name)
|
||||
self.assertEqual(1, len(tl))
|
||||
t = list(tl)[0]
|
||||
self.assertEqual(name, t.name)
|
||||
self.assertEqual(typeclass, t.type)
|
||||
if size > 0:
|
||||
self.assertEqual(size, t.size)
|
||||
|
||||
def launchProcess(self):
|
||||
exe = os.path.join(os.getcwd(), "a.out")
|
||||
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line)
|
||||
self.assertTrue(bpt, VALID_BREAKPOINT)
|
||||
|
||||
# Now launch the process, and do not stop at entry point.
|
||||
process = target.LaunchSimple (None, None, self.get_process_working_directory())
|
||||
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt)
|
||||
|
||||
# Make sure we stopped at the first breakpoint.
|
||||
self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.")
|
||||
self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.")
|
||||
|
||||
frame = thread_list[0].GetFrameAtIndex(0)
|
||||
self.assertTrue (frame, "Got a valid frame 0 frame.")
|
||||
|
||||
def go_builtin_types(self):
|
||||
address_size = self.target().GetAddressByteSize()
|
||||
self.check_builtin('bool')
|
||||
self.check_builtin('uint8', 1)
|
||||
self.check_builtin('int8', 1)
|
||||
self.check_builtin('uint16', 2)
|
||||
self.check_builtin('int16', 2)
|
||||
self.check_builtin('uint32', 4)
|
||||
self.check_builtin('int32', 4)
|
||||
self.check_builtin('uint64', 8)
|
||||
self.check_builtin('int64', 8)
|
||||
self.check_builtin('uintptr', address_size)
|
||||
self.check_builtin('int', address_size)
|
||||
self.check_builtin('uint', address_size)
|
||||
self.check_builtin('float32', 4)
|
||||
self.check_builtin('float64', 8)
|
||||
self.check_builtin('complex64', 8, lldb.eTypeClassComplexFloat)
|
||||
self.check_builtin('complex128', 16, lldb.eTypeClassComplexFloat)
|
||||
|
||||
def var(self, name):
|
||||
var = self.frame().FindVariable(name)
|
||||
self.assertTrue(var.IsValid(), "%s %s" % (VALID_VARIABLE, name))
|
||||
return var
|
||||
|
||||
def check_main_vars(self):
|
||||
v = self.var('theBool')
|
||||
self.assertEqual('true', v.value)
|
||||
|
||||
v = self.var('theInt')
|
||||
self.assertEqual('-7', v.value)
|
||||
|
||||
v = self.var('theComplex')
|
||||
self.assertEqual('1 + 2i', v.value)
|
||||
|
||||
v = self.var('thePointer')
|
||||
self.assertTrue(v.TypeIsPointerType())
|
||||
self.assertEqual('-10', v.Dereference().value)
|
||||
self.assertEqual(1, v.GetNumChildren())
|
||||
self.assertEqual('-10', v.GetChildAtIndex(0).value)
|
||||
|
||||
# print
|
||||
# print os.getpid()
|
||||
# time.sleep(60)
|
||||
v = self.var('theStruct')
|
||||
if v.TypeIsPointerType():
|
||||
v = v.Dereference()
|
||||
self.assertEqual(2, v.GetNumChildren())
|
||||
self.assertEqual('7', v.GetChildAtIndex(0).value)
|
||||
self.assertEqual('7', v.GetChildMemberWithName('myInt').value)
|
||||
self.assertEqual(v.load_addr, v.GetChildAtIndex(1).GetValueAsUnsigned())
|
||||
self.assertEqual(v.load_addr, v.GetChildMemberWithName('myPointer').GetValueAsUnsigned())
|
||||
|
||||
# Test accessing struct fields through pointers.
|
||||
v = v.GetChildMemberWithName('myPointer')
|
||||
self.assertTrue(v.TypeIsPointerType())
|
||||
self.assertEqual(2, v.GetNumChildren())
|
||||
self.assertEqual('7', v.GetChildAtIndex(0).value)
|
||||
c = v.GetChildMemberWithName('myPointer')
|
||||
self.assertTrue(c.TypeIsPointerType())
|
||||
self.assertEqual(2, c.GetNumChildren())
|
||||
self.assertEqual('7', c.GetChildAtIndex(0).value)
|
||||
|
||||
v = self.var('theArray')
|
||||
self.assertEqual(5, v.GetNumChildren())
|
||||
for i in xrange(5):
|
||||
self.assertEqual(str(i + 1), v.GetChildAtIndex(i).value)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
lldb.SBDebugger.Initialize()
|
||||
atexit.register(lambda: lldb.SBDebugger.Terminate())
|
||||
unittest2.main()
|
|
@ -0,0 +1,47 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Fooer interface {
|
||||
Foo() int
|
||||
}
|
||||
|
||||
type SomeFooer struct {
|
||||
val int
|
||||
}
|
||||
|
||||
func (s SomeFooer) Foo() int {
|
||||
return s.val
|
||||
}
|
||||
|
||||
type mystruct struct {
|
||||
myInt int
|
||||
myPointer *mystruct
|
||||
}
|
||||
|
||||
func main() {
|
||||
theBool := true
|
||||
theInt := -7
|
||||
theComplex := 1 + 2i
|
||||
pointee := -10
|
||||
thePointer := &pointee
|
||||
theStruct := &mystruct { myInt: 7}
|
||||
theStruct.myPointer = theStruct
|
||||
theArray := [5]byte{1, 2, 3, 4, 5}
|
||||
theSlice := theArray[1:2]
|
||||
theString := "abc"
|
||||
|
||||
f := SomeFooer {9}
|
||||
var theEface interface{} = f
|
||||
var theFooer Fooer = f
|
||||
|
||||
theChan := make(chan int)
|
||||
theMap := make(map[int]string)
|
||||
theMap[1] = "1"
|
||||
|
||||
fmt.Println(theBool) // Set breakpoint here.
|
||||
// Reference all the variables so the compiler is happy.
|
||||
fmt.Println(theInt, theComplex, thePointer, theStruct.myInt)
|
||||
fmt.Println(theArray[0], theSlice[0], theString)
|
||||
fmt.Println(theEface, theFooer, theChan, theMap)
|
||||
}
|
|
@ -893,6 +893,21 @@ def skipUnlessDarwin(func):
|
|||
"""Decorate the item to skip tests that should be skipped on any non Darwin platform."""
|
||||
return skipUnlessPlatform(getDarwinOSTriples())(func)
|
||||
|
||||
def skipUnlessGoInstalled(func):
|
||||
"""Decorate the item to skip tests when no Go compiler is available."""
|
||||
if isinstance(func, type) and issubclass(func, unittest2.TestCase):
|
||||
raise Exception("@skipIfGcc can only be used to decorate a test method")
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
from unittest2 import case
|
||||
self = args[0]
|
||||
compiler = self.getGoCompilerVersion()
|
||||
if not compiler:
|
||||
self.skipTest("skipping because go compiler not found")
|
||||
else:
|
||||
func(*args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
def getPlatform():
|
||||
"""Returns the target platform which the tests are running on."""
|
||||
platform = lldb.DBG.GetSelectedPlatform().GetTriple().split('-')[2]
|
||||
|
@ -1868,6 +1883,18 @@ class Base(unittest2.TestCase):
|
|||
version = m.group(1)
|
||||
return version
|
||||
|
||||
def getGoCompilerVersion(self):
|
||||
""" Returns a string that represents the go compiler version, or None if go is not found.
|
||||
"""
|
||||
compiler = which("go")
|
||||
if compiler:
|
||||
version_output = system([[compiler, "version"]])[0]
|
||||
for line in version_output.split(os.linesep):
|
||||
m = re.search('go version (devel|go\\S+)', line)
|
||||
if m:
|
||||
return m.group(1)
|
||||
return None
|
||||
|
||||
def platformIsDarwin(self):
|
||||
"""Returns true if the OS triple for the selected platform is any valid apple OS"""
|
||||
return platformIsDarwin()
|
||||
|
@ -2053,6 +2080,11 @@ class Base(unittest2.TestCase):
|
|||
if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
|
||||
raise Exception("Don't know how to build binary with dwarf")
|
||||
|
||||
def buildGo(self):
|
||||
"""Build the default go binary.
|
||||
"""
|
||||
system([[which('go'), 'build -gcflags "-N -l" -o a.out main.go']])
|
||||
|
||||
def signBinary(self, binary_path):
|
||||
if sys.platform.startswith("darwin"):
|
||||
codesign_cmd = "codesign --force --sign lldb_codesign %s" % (binary_path)
|
||||
|
|
Loading…
Reference in New Issue