//===-- 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(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) { 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 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(); }