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());
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()) {
266 dw_addr_t file_addr = ranges.begin()->LowPC;
271 if (ranges.empty() || name ==
nullptr || mangled ==
nullptr) {
274 die.GetDIE()->GetDIENamesAndRanges(die.GetCU(), name, mangled, ranges,
275 decl_file, decl_line, decl_column,
276 call_file, call_line, call_column);
280 return !ranges.empty();
289 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> &seen,
291 assert(!worklist.empty() &&
"Need at least one DIE to visit.");
292 assert(seen.size() >= 1 &&
293 "Need to have seen at least the currently visited entry.");
295 DWARFDIE current = worklist.pop_back_val();
297 const auto *cu = current.
GetCU();
300 const auto *entry = current.
GetDIE();
303 const auto *abbrevDecl =
304 entry->GetAbbreviationDeclarationPtr(current.
GetCU());
311 const bool is_first_die = seen.size() == 1;
313 for (
const auto &attribute : abbrevDecl->attributes()) {
323 case DW_AT_declaration:
332 attributes.
Append(form_value, offset, attr);
336 if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
339 if (seen.insert(spec_die.GetDIE()).second)
340 worklist.push_back(spec_die);
345 std::optional<uint8_t> fixed_skip_size =
348 offset += *fixed_skip_size;
364 llvm::SmallVector<DWARFDIE, 3> worklist;
365 worklist.emplace_back(cu,
this);
370 llvm::SmallPtrSet<DWARFDebugInfoEntry const *, 3> seen;
378 }
while (!worklist.empty() && recurse == Recurse::yes);
391 dw_offset_t *end_attr_offset_ptr,
bool check_elaborating_dies)
const {
393 std::optional<uint32_t> attr_idx = abbrevDecl->findAttributeIndex(attr);
400 while (idx < *attr_idx)
406 form_value.
SetForm(abbrevDecl->getFormByIndex(idx));
407 if (abbrevDecl->getAttrIsImplicitConstByIndex(idx))
408 form_value.
SetValue(abbrevDecl->getAttrImplicitConstValueByIndex(idx));
411 if (end_attr_offset_ptr)
412 *end_attr_offset_ptr = offset;
418 if (check_elaborating_dies) {
420 {DW_AT_specification, DW_AT_abstract_origin, DW_AT_signature}) {
427 die.
GetCU(), attr, form_value, end_attr_offset_ptr,
false);
443 bool check_elaborating_dies)
const {
455 bool check_elaborating_dies)
const {
462std::optional<uint64_t>
465 bool check_elaborating_dies)
const {
478 bool check_elaborating_dies)
const {
487 bool check_elaborating_dies)
const {
503 bool check_elaborating_dies)
const {
506 check_elaborating_dies)) {
508 if (form == DW_FORM_addr || form == DW_FORM_addrx ||
509 form == DW_FORM_GNU_addr_index)
513 return lo_pc + form_value.
Unsigned();
526 uint64_t fail_value,
bool check_elaborating_dies)
const {
528 check_elaborating_dies);
529 if (lo_pc != fail_value) {
531 if (hi_pc != fail_value)
539llvm::Expected<llvm::DWARFAddressRangesVector>
541 DWARFUnit *cu,
bool check_hi_lo_pc,
bool check_elaborating_dies)
const {
547 if (check_hi_lo_pc) {
551 check_elaborating_dies) &&
553 return llvm::DWARFAddressRangesVector{{lo_pc, hi_pc}};
555 return llvm::createStringError(
"DIE has no address range information");
572 bool substitute_name_allowed)
const {
573 const char *name =
nullptr;
583 if (!substitute_name_allowed)
595 const char *name =
nullptr;
621 if (
m_tag == DW_TAG_subprogram &&
623 if (llvm::Expected<llvm::DWARFAddressRangesVector> ranges =
625 for (
const auto &r : *ranges)
644const llvm::DWARFAbbreviationDeclaration *
649 const llvm::DWARFAbbreviationDeclarationSet *abbrev_set =
654 return abbrev_set->getAbbreviationDeclaration(
m_abbr_idx);
658 if (
Tag() != DW_TAG_variable &&
Tag() != DW_TAG_member)
661 while (parent_die !=
nullptr) {
662 switch (parent_die->
Tag()) {
663 case DW_TAG_subprogram:
664 case DW_TAG_lexical_block:
665 case DW_TAG_inlined_subroutine:
668 case DW_TAG_compile_unit:
669 case DW_TAG_partial_unit:
688 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)
#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.
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