| //===-- DWARFASTParserOCaml.cpp ---------------------------------*- C++ -*-===// |
| |
| #include "DWARFASTParserOCaml.h" |
| |
| #include "lldb/Core/Module.h" |
| #include "lldb/Symbol/CompileUnit.h" |
| #include "lldb/Symbol/Function.h" |
| #include "lldb/Symbol/ObjectFile.h" |
| #include "lldb/Symbol/Type.h" |
| #include "lldb/Symbol/TypeList.h" |
| #include "lldb/Utility/Log.h" |
| #include "lldb/Utility/Status.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| DWARFASTParserOCaml::DWARFASTParserOCaml(OCamlASTContext &ast) : m_ast(ast) {} |
| |
| DWARFASTParserOCaml::~DWARFASTParserOCaml() {} |
| |
| TypeSP DWARFASTParserOCaml::ParseBaseTypeFromDIE(const DWARFDIE &die) { |
| SymbolFileDWARF *dwarf = die.GetDWARF(); |
| 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, byte_size); |
| return std::make_shared<Type>(die.GetID(), dwarf, type_name, byte_size, |
| nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, |
| decl, compiler_type, Type::eResolveStateFull); |
| } |
| |
| lldb::TypeSP DWARFASTParserOCaml::ParseTypeFromDWARF(const SymbolContext &sc, |
| const DWARFDIE &die, |
| 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: { |
| type_sp = ParseBaseTypeFromDIE(die); |
| break; |
| } |
| case DW_TAG_array_type: { |
| break; |
| } |
| case DW_TAG_class_type: { |
| break; |
| } |
| case DW_TAG_reference_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 || |
| sc_parent_tag == DW_TAG_partial_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; |
| } |
| |
| Function *DWARFASTParserOCaml::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()); |
| |
| Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); |
| |
| if (die) { |
| SymbolFileDWARF *dwarf = die.GetDWARF(); |
| if (log) { |
| dwarf->GetObjectFile()->GetModule()->LogMessage( |
| log, "DWARFASTParserOCaml::ParseFunctionFromDWARF (die = 0x%8.8x) %s " |
| "name = '%s')", |
| die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.GetName()); |
| } |
| } |
| |
| 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)) { |
| 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), true); |
| |
| 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(); |
| 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 = die.GetID(); |
| func_sp.reset(new Function(sc.comp_unit, |
| func_user_id, // UserID is the DIE offset |
| 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; |
| } |
| |
| lldb_private::CompilerDeclContext |
| DWARFASTParserOCaml::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) { |
| return CompilerDeclContext(); |
| } |
| |
| lldb_private::CompilerDeclContext |
| DWARFASTParserOCaml::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) { |
| return CompilerDeclContext(); |
| } |