21#include "llvm/ADT/STLExtras.h"
22#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/FormatAdapters.h"
25#include "llvm/Support/LEB128.h"
47 auto report_error = [&](
const char *fmt,
const auto &...vals) {
49 "[{0:x16}]: {1}, please file a bug and "
50 "attach the file at the start of this error message",
51 static_cast<uint64_t
>(
m_offset), llvm::formatv(fmt, vals...));
52 *offset_ptr = std::numeric_limits<lldb::offset_t>::max();
58 const uint64_t abbr_idx = data.
GetULEB128(offset_ptr);
59 if (abbr_idx > std::numeric_limits<uint16_t>::max())
60 return report_error(
"abbreviation code {0} too big", abbr_idx);
64 m_tag = llvm::dwarf::DW_TAG_null;
70 if (abbrevDecl ==
nullptr)
71 return report_error(
"invalid abbreviation code {0}", abbr_idx);
73 m_tag = abbrevDecl->getTag();
76 for (
const auto &attribute : abbrevDecl->attributes()) {
80 return report_error(
"Unsupported DW_FORM_{1:x}", attribute.Form);
85static llvm::Expected<llvm::DWARFAddressRangesVector>
87 return (value.
Form() == DW_FORM_rnglistx)
93 const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec,
95 attr = attr_spec.Attr;
96 form_value.
FormRef() = attr_spec.Form;
97 if (attr_spec.isImplicitConst())
98 form_value.
SetSigned(attr_spec.getImplicitConstValue());
106 DWARFUnit *cu,
const char *&name,
const char *&mangled,
107 llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file,
108 std::optional<int> &decl_line, std::optional<int> &decl_column,
109 std::optional<int> &call_file, std::optional<int> &call_line,
113 std::vector<DWARFDIE> dies;
114 bool set_frame_base_loclist_addr =
false;
126 bool do_offset =
false;
128 for (
const auto &attribute : abbrevDecl->attributes()) {
148 if (form_value.
Form() == DW_FORM_addr ||
149 form_value.
Form() == DW_FORM_addrx ||
150 form_value.
Form() == DW_FORM_GNU_addr_index) {
163 if (llvm::Expected<llvm::DWARFAddressRangesVector> r =
165 ranges = std::move(*r);
168 "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but "
169 "range extraction failed ({3}), please file a bug "
170 "and attach the file at the start of this error message",
171 GetOffset(), llvm::dwarf::FormEncodingString(form_value.
Form()),
172 form_value.
Unsigned(), fmt_consume(r.takeError()));
181 case DW_AT_MIPS_linkage_name:
182 case DW_AT_linkage_name:
183 if (mangled ==
nullptr)
187 case DW_AT_abstract_origin:
191 case DW_AT_specification:
195 case DW_AT_decl_file:
200 case DW_AT_decl_line:
205 case DW_AT_decl_column:
207 decl_column = form_value.
Unsigned();
210 case DW_AT_call_file:
215 case DW_AT_call_line:
220 case DW_AT_call_column:
222 call_column = form_value.
Unsigned();
225 case DW_AT_frame_base:
228 uint64_t block_offset =
230 uint64_t block_length = form_value.
Unsigned();
234 data, block_offset, block_length)),
246 set_frame_base_loclist_addr =
true;
262 ranges.emplace_back(lo_pc, range_hi_pc);
265 if (set_frame_base_loclist_addr && !ranges.empty()) {
267 dw_addr_t lowest_range_pc = llvm::min_element(ranges)->LowPC;
272 if (ranges.empty() || name ==
nullptr || mangled ==
nullptr) {
275 die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
276 decl_file, decl_line, decl_column,
277 call_file, call_line, call_column);
281 return !ranges.empty();
291 uint32_t curr_depth)
const {
301 for (
const auto &attribute : abbrevDecl->attributes()) {
311 case DW_AT_declaration:
312 if (curr_depth > 0) {
320 attributes.
Append(form_value, offset, attr);
324 if (recurse == Recurse::yes &&
325 ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) {
330 recurse, curr_depth + 1);
334 std::optional<uint8_t> fixed_skip_size =
337 offset += *fixed_skip_size;
352 dw_offset_t *end_attr_offset_ptr,
bool check_elaborating_dies)
const {
354 std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr);
361 while (idx < *attr_idx)
367 form_value.
SetForm(abbrevDecl->getFormByIndex(idx));
369 if (end_attr_offset_ptr)
370 *end_attr_offset_ptr = offset;
376 if (check_elaborating_dies) {
378 {DW_AT_specification, DW_AT_abstract_origin, DW_AT_signature}) {
385 die.
GetCU(), attr, form_value, end_attr_offset_ptr,
false);
401 bool check_elaborating_dies)
const {
413 bool check_elaborating_dies)
const {
420std::optional<uint64_t>
423 bool check_elaborating_dies)
const {
436 bool check_elaborating_dies)
const {
445 bool check_elaborating_dies)
const {
461 bool check_elaborating_dies)
const {
464 check_elaborating_dies)) {
466 if (form == DW_FORM_addr || form == DW_FORM_addrx ||
467 form == DW_FORM_GNU_addr_index)
471 return lo_pc + form_value.
Unsigned();
484 uint64_t fail_value,
bool check_elaborating_dies)
const {
486 check_elaborating_dies);
487 if (lo_pc != fail_value) {
489 if (hi_pc != fail_value)
497llvm::Expected<llvm::DWARFAddressRangesVector>
499 DWARFUnit *cu,
bool check_hi_lo_pc,
bool check_elaborating_dies)
const {
505 if (check_hi_lo_pc) {
509 check_elaborating_dies) &&
511 return llvm::DWARFAddressRangesVector{{lo_pc, hi_pc}};
513 return llvm::createStringError(
"DIE has no address range information");
530 bool substitute_name_allowed)
const {
531 const char *name =
nullptr;
541 if (!substitute_name_allowed)
553 const char *name =
nullptr;
576 if (
m_tag == DW_TAG_subprogram) {
577 if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
579 for (
const auto &r : *ranges)
598const llvm::DWARFAbbreviationDeclaration *
603 const llvm::DWARFAbbreviationDeclarationSet *abbrev_set =
608 return abbrev_set->getAbbreviationDeclaration(
m_abbr_idx);
612 if (
Tag() != DW_TAG_variable &&
Tag() != DW_TAG_member)
615 while (parent_die !=
nullptr) {
616 switch (parent_die->
Tag()) {
617 case DW_TAG_subprogram:
618 case DW_TAG_lexical_block:
619 case DW_TAG_inlined_subroutine:
622 case DW_TAG_compile_unit:
623 case DW_TAG_partial_unit:
642 return !(*
this == rhs);
static void ExtractAttrAndFormValue(const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec, dw_attr_t &attr, DWARFFormValue &form_value)
static llvm::Expected< llvm::DWARFAddressRangesVector > GetRanges(DWARFUnit &unit, const DWARFFormValue &value)
#define LLDB_LOG_ERROR(log, error,...)
"lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file address range to a single ...
void SetFuncFileAddress(lldb::addr_t func_file_addr)
"lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location expression and interprets it.
static bool ParseDWARFLocationList(const plugin::dwarf::DWARFUnit *dwarf_cu, const DataExtractor &data, DWARFExpressionList *loc_list)
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
ObjectFile * GetObjectFile() override
void Append(const DWARFFormValue &form_value, dw_offset_t attr_die_offset, dw_attr_t attr)
DWARFAttributes GetAttributes(Recurse recurse=Recurse::yes) const
DWARFUnit * GetCU() const
DWARFDIE GetDIE(dw_offset_t die_offset) const
void AppendRange(dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc)
DWARFDebugInfoEntry objects assume that they are living in one big vector and do pointer arithmetic o...
bool operator==(const DWARFDebugInfoEntry &rhs) const
dw_offset_t GetOffset() const
dw_tag_t m_tag
A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table.
bool GetAttributeAddressRange(const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, uint64_t fail_value, bool check_elaborating_dies=false) const
dw_addr_t GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, bool check_elaborating_dies=false) const
bool operator!=(const DWARFDebugInfoEntry &rhs) const
llvm::Expected< llvm::DWARFAddressRangesVector > GetAttributeAddressRanges(DWARFUnit *cu, bool check_hi_lo_pc, bool check_elaborating_dies=false) const
bool IsGlobalOrStaticScopeVariable() const
DWARFAttributes GetAttributes(DWARFUnit *cu, Recurse recurse=Recurse::yes) const
const char * GetMangledName(const DWARFUnit *cu, bool substitute_name_allowed=true) const
std::optional< uint64_t > GetAttributeValueAsOptionalUnsigned(const DWARFUnit *cu, const dw_attr_t attr, bool check_elaborating_dies=false) const
const llvm::DWARFAbbreviationDeclaration * GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const
DWARFDebugInfoEntry * GetSibling()
DWARFDebugInfoEntry * GetParent()
void BuildFunctionAddressRangeTable(DWARFUnit *cu, DWARFDebugAranges *debug_aranges) const
This function is builds a table very similar to the standard .debug_aranges table,...
DWARFDIE GetAttributeValueAsReference(const DWARFUnit *cu, const dw_attr_t attr, bool check_elaborating_dies=false) const
const char * GetAttributeValueAsString(const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, bool check_elaborating_dies=false) const
bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name, const char *&mangled, llvm::DWARFAddressRangesVector &rangeList, std::optional< int > &decl_file, std::optional< int > &decl_line, std::optional< int > &decl_column, std::optional< int > &call_file, std::optional< int > &call_line, std::optional< int > &call_column, DWARFExpressionList *frame_base=nullptr) const
uint64_t GetAttributeValueAsAddress(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_elaborating_dies=false) const
uint64_t GetAttributeValueAsUnsigned(const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, bool check_elaborating_dies=false) const
const char * GetPubname(const DWARFUnit *cu) const
bool Extract(const DWARFDataExtractor &data, const DWARFUnit &cu, lldb::offset_t *offset_ptr)
dw_offset_t GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, DWARFFormValue &formValue, dw_offset_t *end_attr_offset_ptr=nullptr, bool check_elaborating_dies=false) const
const char * GetName(const DWARFUnit *cu) const
DWARFDebugInfoEntry * GetFirstChild()
lldb::offset_t GetFirstAttributeOffset() const
llvm::Expected< llvm::DWARFAddressRangesVector > FindRnglistFromOffset(dw_offset_t offset)
Return a list of address ranges resulting from a (possibly encoded) range list starting at a given of...
dw_addr_t GetBaseAddress() const
SymbolFileDWARF & GetSymbolFileDWARF() const
const DWARFDataExtractor & GetData() const
Get the data that contains the DIE information for this unit.
DWARFDataExtractor GetLocationData() const
llvm::Expected< llvm::DWARFAddressRangesVector > FindRnglistFromIndex(uint32_t index)
Return a list of address ranges retrieved from an encoded range list whose offset is found via a tabl...
const llvm::DWARFAbbreviationDeclarationSet * GetAbbreviations() const
llvm::dwarf::Attribute dw_attr_t
llvm::dwarf::Form dw_form_t
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::Module > ModuleSP