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"
38using namespace llvm::dwarf;
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());
105 const DWARFDIE &die,
const char *&name,
const char *&mangled,
106 llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file,
107 std::optional<int> &decl_line, std::optional<int> &decl_column,
108 std::optional<int> &call_file, std::optional<int> &call_line,
114 std::vector<DWARFDIE> dies;
115 bool set_frame_base_loclist_addr =
false;
120 if (
const auto *abbrevDecl =
121 die.
GetDIE()->GetAbbreviationDeclarationPtr(cu)) {
128 bool do_offset =
false;
130 for (
const auto &attribute : abbrevDecl->attributes()) {
150 if (form_value.
Form() == DW_FORM_addr ||
151 form_value.
Form() == DW_FORM_addrx ||
152 form_value.
Form() == DW_FORM_GNU_addr_index) {
165 if (llvm::Expected<llvm::DWARFAddressRangesVector> r =
167 ranges = std::move(*r);
170 "[{0:x16}]: DIE has DW_AT_ranges({1} {2:x16}) attribute, but "
171 "range extraction failed ({3}), please file a bug "
172 "and attach the file at the start of this error message",
174 llvm::dwarf::FormEncodingString(form_value.Form()),
175 form_value.Unsigned(), fmt_consume(r.takeError()));
184 case DW_AT_MIPS_linkage_name:
185 case DW_AT_linkage_name:
186 if (mangled ==
nullptr)
190 case DW_AT_abstract_origin:
194 case DW_AT_specification:
198 case DW_AT_decl_file:
203 case DW_AT_decl_line:
208 case DW_AT_decl_column:
210 decl_column = form_value.
Unsigned();
213 case DW_AT_call_file:
218 case DW_AT_call_line:
223 case DW_AT_call_column:
225 call_column = form_value.
Unsigned();
228 case DW_AT_frame_base:
231 uint64_t block_offset =
233 uint64_t block_length = form_value.
Unsigned();
237 data, block_offset, block_length)),
249 set_frame_base_loclist_addr =
true;
265 ranges.emplace_back(lo_pc, range_hi_pc);
268 if (set_frame_base_loclist_addr && !ranges.empty()) {
269 dw_addr_t file_addr = ranges.begin()->LowPC;
274 if (ranges.empty() || name ==
nullptr || mangled ==
nullptr) {
277 elaborating_dies.push_back(die);
287 DWARFUnit *cu,
const char *&name,
const char *&mangled,
288 llvm::DWARFAddressRangesVector &ranges, std::optional<int> &decl_file,
289 std::optional<int> &decl_line, std::optional<int> &decl_column,
290 std::optional<int> &call_file, std::optional<int> &call_line,
292 llvm::SmallVector<DWARFDIE, 3> worklist;
293 worklist.emplace_back(cu,
this);
296 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> seen;
303 while (!worklist.empty()) {
304 DWARFDIE current = worklist.pop_back_val();
306 llvm::SmallVector<DWARFDIE, 3> elaborating_dies;
308 decl_column, call_file, call_line, call_column,
309 die_frame_base, elaborating_dies);
310 die_frame_base =
nullptr;
313 for (
const DWARFDIE &die : llvm::reverse(elaborating_dies)) {
314 if (seen.insert(die.GetDIE()).second)
315 worklist.push_back(die);
319 return !ranges.empty();
328 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> &seen,
330 assert(!worklist.empty() &&
"Need at least one DIE to visit.");
331 assert(seen.size() >= 1 &&
332 "Need to have seen at least the currently visited entry.");
334 DWARFDIE current = worklist.pop_back_val();
336 const auto *cu = current.
GetCU();
339 const auto *entry = current.
GetDIE();
342 const auto *abbrevDecl =
343 entry->GetAbbreviationDeclarationPtr(current.
GetCU());
350 const bool is_first_die = seen.size() == 1;
352 for (
const auto &attribute : abbrevDecl->attributes()) {
362 case DW_AT_declaration:
371 attributes.
Append(form_value, offset, attr);
375 if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
378 if (seen.insert(spec_die.GetDIE()).second)
379 worklist.push_back(spec_die);
384 std::optional<uint8_t> fixed_skip_size =
387 offset += *fixed_skip_size;
403 llvm::SmallVector<DWARFDIE, 3> worklist;
404 worklist.emplace_back(cu,
this);
409 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> seen;
417 }
while (!worklist.empty() && recurse == Recurse::yes);
430 dw_offset_t *end_attr_offset_ptr,
bool check_elaborating_dies)
const {
432 std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr);
439 while (idx < *attr_idx)
445 form_value.
SetForm(abbrevDecl->getFormByIndex(idx));
446 if (abbrevDecl->getAttrIsImplicitConstByIndex(idx))
447 form_value.
SetValue(abbrevDecl->getAttrImplicitConstValueByIndex(idx));
450 if (end_attr_offset_ptr)
451 *end_attr_offset_ptr = offset;
457 if (check_elaborating_dies) {
459 {DW_AT_specification, DW_AT_abstract_origin, DW_AT_signature}) {
466 die.
GetCU(), attr, form_value, end_attr_offset_ptr,
false);
482 bool check_elaborating_dies)
const {
494 bool check_elaborating_dies)
const {
501std::optional<uint64_t>
504 bool check_elaborating_dies)
const {
517 bool check_elaborating_dies)
const {
526 bool check_elaborating_dies)
const {
542 bool check_elaborating_dies)
const {
545 check_elaborating_dies)) {
547 if (form == DW_FORM_addr || form == DW_FORM_addrx ||
548 form == DW_FORM_GNU_addr_index)
552 return lo_pc + form_value.
Unsigned();
565 uint64_t fail_value,
bool check_elaborating_dies)
const {
567 check_elaborating_dies);
568 if (lo_pc != fail_value) {
570 if (hi_pc != fail_value)
578llvm::Expected<llvm::DWARFAddressRangesVector>
580 DWARFUnit *cu,
bool check_hi_lo_pc,
bool check_elaborating_dies)
const {
586 if (check_hi_lo_pc) {
590 check_elaborating_dies) &&
592 return llvm::DWARFAddressRangesVector{{lo_pc, hi_pc}};
594 return llvm::createStringError(
"DIE has no address range information");
611 bool substitute_name_allowed)
const {
612 const char *name =
nullptr;
622 if (!substitute_name_allowed)
634 const char *name =
nullptr;
660 if (
m_tag == DW_TAG_subprogram &&
662 if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
664 for (
const auto &r : *ranges)
684const llvm::DWARFAbbreviationDeclaration *
689 const llvm::DWARFAbbreviationDeclarationSet *abbrev_set =
694 return abbrev_set->getAbbreviationDeclaration(
m_abbr_idx);
698 if (
Tag() != DW_TAG_variable &&
Tag() != DW_TAG_member)
701 while (parent_die !=
nullptr) {
702 switch (parent_die->
Tag()) {
703 case DW_TAG_subprogram:
704 case DW_TAG_lexical_block:
705 case DW_TAG_inlined_subroutine:
708 case DW_TAG_compile_unit:
709 case DW_TAG_partial_unit:
728 return !(*
this == rhs);
static void ExtractAttrAndFormValue(const llvm::DWARFAbbreviationDeclaration::AttributeSpec &attr_spec, dw_attr_t &attr, DWARFFormValue &form_value)
static bool GetAttributes(llvm::SmallVectorImpl< DWARFDIE > &worklist, llvm::SmallPtrSet< DWARFDebugInfoEntry const *, 3 > &seen, DWARFAttributes &attributes)
Helper for the public DWARFDebugInfoEntry::GetAttributes API.
static llvm::Expected< llvm::DWARFAddressRangesVector > GetRanges(DWARFUnit &unit, const DWARFFormValue &value)
static void GetDIENamesAndRanges(const DWARFDIE &die, const char *&name, const char *&mangled, llvm::DWARFAddressRangesVector &ranges, 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, llvm::SmallVectorImpl< DWARFDIE > &elaborating_dies)
Helper for the public DWARFDebugInfoEntry::GetDIENamesAndRanges API.
#define LLDB_LOG_ERRORV(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.
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)
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)
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
DWARFAttributes GetAttributes(const DWARFUnit *cu, Recurse recurse=Recurse::yes) const
Get all attribute values for a given DIE, optionally following any specifications and abstract origin...
bool IsGlobalOrStaticScopeVariable() 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
DWARFBaseDIE::Recurse Recurse
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...
SymbolFileDWARF & GetSymbolFileDWARF() const
dw_addr_t GetBaseAddress() const override
const DWARFDataExtractor & GetData() const
Get the data that contains the DIE information for this unit.
DWARFDataExtractor GetLocationData() const
bool ParseDWARFLocationList(const DataExtractor &data, DWARFExpressionList &loc_list) 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