| //===-- DWARFASTParser.cpp ------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "DWARFASTParser.h" | |
| #include "DWARFAttribute.h" | |
| #include "DWARFDIE.h" | |
| #include "SymbolFileDWARF.h" | |
| #include "lldb/Symbol/SymbolFile.h" | |
| #include "lldb/Target/StackFrame.h" | |
| #include "lldb/ValueObject/ValueObject.h" | |
| #include <optional> | |
| using namespace lldb; | |
| using namespace lldb_private; | |
| using namespace lldb_private::plugin::dwarf; | |
| using namespace llvm::dwarf; | |
| std::optional<SymbolFile::ArrayInfo> | |
| DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die, | |
| const ExecutionContext *exe_ctx) { | |
| SymbolFile::ArrayInfo array_info; | |
| if (!parent_die) | |
| return std::nullopt; | |
| for (DWARFDIE die : parent_die.children()) { | |
| const dw_tag_t tag = die.Tag(); | |
| if (tag != DW_TAG_subrange_type) | |
| continue; | |
| DWARFAttributes attributes = die.GetAttributes(); | |
| if (attributes.Size() == 0) | |
| continue; | |
| std::optional<uint64_t> num_elements; | |
| uint64_t lower_bound = 0; | |
| uint64_t upper_bound = 0; | |
| bool upper_bound_valid = false; | |
| for (size_t i = 0; i < attributes.Size(); ++i) { | |
| const dw_attr_t attr = attributes.AttributeAtIndex(i); | |
| DWARFFormValue form_value; | |
| if (attributes.ExtractFormValueAtIndex(i, form_value)) { | |
| switch (attr) { | |
| case DW_AT_name: | |
| break; | |
| case DW_AT_count: | |
| if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) { | |
| if (var_die.Tag() == DW_TAG_variable) | |
| if (exe_ctx) { | |
| if (auto frame = exe_ctx->GetFrameSP()) { | |
| Status error; | |
| lldb::VariableSP var_sp; | |
| auto valobj_sp = frame->GetValueForVariableExpressionPath( | |
| var_die.GetName(), eNoDynamicValues, 0, var_sp, error); | |
| if (valobj_sp) { | |
| num_elements = valobj_sp->GetValueAsUnsigned(0); | |
| break; | |
| } | |
| } | |
| } | |
| } else | |
| num_elements = form_value.Unsigned(); | |
| break; | |
| case DW_AT_bit_stride: | |
| array_info.bit_stride = form_value.Unsigned(); | |
| break; | |
| case DW_AT_byte_stride: | |
| array_info.byte_stride = form_value.Unsigned(); | |
| break; | |
| case DW_AT_lower_bound: | |
| lower_bound = form_value.Unsigned(); | |
| break; | |
| case DW_AT_upper_bound: | |
| upper_bound_valid = true; | |
| upper_bound = form_value.Unsigned(); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| } | |
| if (!num_elements || *num_elements == 0) { | |
| if (upper_bound_valid && upper_bound >= lower_bound) | |
| num_elements = upper_bound - lower_bound + 1; | |
| } | |
| array_info.element_orders.push_back(num_elements); | |
| } | |
| return array_info; | |
| } | |
| Type *DWARFASTParser::GetTypeForDIE(const DWARFDIE &die) { | |
| if (!die) | |
| return nullptr; | |
| SymbolFileDWARF *dwarf = die.GetDWARF(); | |
| if (!dwarf) | |
| return nullptr; | |
| DWARFAttributes attributes = die.GetAttributes(); | |
| if (attributes.Size() == 0) | |
| return nullptr; | |
| DWARFFormValue type_die_form; | |
| for (size_t i = 0; i < attributes.Size(); ++i) { | |
| dw_attr_t attr = attributes.AttributeAtIndex(i); | |
| DWARFFormValue form_value; | |
| if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) | |
| return dwarf->ResolveTypeUID(form_value.Reference(), true); | |
| } | |
| return nullptr; | |
| } | |
| AccessType | |
| DWARFASTParser::GetAccessTypeFromDWARF(uint32_t dwarf_accessibility) { | |
| switch (dwarf_accessibility) { | |
| case DW_ACCESS_public: | |
| return eAccessPublic; | |
| case DW_ACCESS_private: | |
| return eAccessPrivate; | |
| case DW_ACCESS_protected: | |
| return eAccessProtected; | |
| default: | |
| break; | |
| } | |
| return eAccessNone; | |
| } |