-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb] Recurse through DW_AT_signature when looking for attributes #107241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,44 +60,45 @@ class DWARFDebugInfoEntry { | |
return attrs; | ||
} | ||
|
||
dw_offset_t | ||
GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, | ||
DWARFFormValue &formValue, | ||
dw_offset_t *end_attr_offset_ptr = nullptr, | ||
bool check_specification_or_abstract_origin = false) const; | ||
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 *GetAttributeValueAsString( | ||
const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, | ||
bool check_specification_or_abstract_origin = false) const; | ||
const char * | ||
GetAttributeValueAsString(const DWARFUnit *cu, const dw_attr_t attr, | ||
const char *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_specification_or_abstract_origin = false) const; | ||
uint64_t | ||
GetAttributeValueAsUnsigned(const DWARFUnit *cu, const dw_attr_t attr, | ||
uint64_t fail_value, | ||
bool check_elaborating_dies = false) const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of curiosity, when do we not want to recurse through the specifications/origin/signature? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of the time, I'd say. DW_AT_specification says "this DIE is an out of line definition of the function declared in ". It normally does not list the name of the function because the name is already given on the other die, but it'd perfectly reasonable for |
||
|
||
std::optional<uint64_t> GetAttributeValueAsOptionalUnsigned( | ||
const DWARFUnit *cu, const dw_attr_t attr, | ||
bool check_specification_or_abstract_origin = false) const; | ||
bool check_elaborating_dies = false) const; | ||
|
||
DWARFDIE GetAttributeValueAsReference( | ||
const DWARFUnit *cu, const dw_attr_t attr, | ||
bool check_specification_or_abstract_origin = false) const; | ||
DWARFDIE | ||
GetAttributeValueAsReference(const DWARFUnit *cu, const dw_attr_t attr, | ||
bool check_elaborating_dies = false) const; | ||
|
||
uint64_t GetAttributeValueAsAddress( | ||
const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, | ||
bool check_specification_or_abstract_origin = false) const; | ||
uint64_t | ||
GetAttributeValueAsAddress(const DWARFUnit *cu, const dw_attr_t attr, | ||
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_specification_or_abstract_origin = 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 GetAttributeAddressRange( | ||
const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, | ||
uint64_t fail_value, | ||
bool check_specification_or_abstract_origin = false) const; | ||
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; | ||
|
||
DWARFRangeList GetAttributeAddressRanges( | ||
DWARFUnit *cu, bool check_hi_lo_pc, | ||
bool check_specification_or_abstract_origin = false) const; | ||
DWARFRangeList | ||
GetAttributeAddressRanges(DWARFUnit *cu, bool check_hi_lo_pc, | ||
bool check_elaborating_dies = false) const; | ||
|
||
const char *GetName(const DWARFUnit *cu) const; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Test that we can correctly disambiguate a nested type (where the outer type | ||
// is in a type unit) from a non-nested type with the same basename. Failure to | ||
// do so can cause us to think a type is a member of itself, which caused | ||
// infinite recursion (crash) in the past. | ||
|
||
// REQUIRES: lld | ||
|
||
// RUN: %clang --target=x86_64-pc-linux -c %s -o %t-a.o -g -fdebug-types-section -flimit-debug-info -DFILE_A | ||
// RUN: %clang --target=x86_64-pc-linux -c %s -o %t-b.o -g -fdebug-types-section -flimit-debug-info -DFILE_B | ||
// RUN: ld.lld -z undefs %t-a.o %t-b.o -o %t | ||
// RUN: %lldb %t -o "target variable x" -o exit | FileCheck %s | ||
|
||
// CHECK: (lldb) target variable | ||
// CHECK-NEXT: (const X) x = { | ||
// CHECK-NEXT: NS::Outer::Struct = { | ||
// CHECK-NEXT: x = 42 | ||
// CHECK-NEXT: o = (x = 47) | ||
// CHECK-NEXT: y = 24 | ||
// CHECK-NEXT: } | ||
// CHECK-NEXT: } | ||
|
||
namespace NS { | ||
struct Struct { | ||
int x = 47; | ||
virtual void anchor(); | ||
}; | ||
} // namespace NS | ||
|
||
#ifdef FILE_A | ||
namespace NS { | ||
struct Outer { | ||
struct Struct { | ||
int x = 42; | ||
NS::Struct o; | ||
int y = 24; | ||
}; | ||
}; | ||
} // namespace NS | ||
|
||
struct X : NS::Outer::Struct {}; | ||
extern constexpr X x = {}; | ||
#endif | ||
#ifdef FILE_B | ||
void NS::Struct::anchor() {} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on why we don't need this anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because die.GetName() will now find the correct name on its own. And (unlike with DW_AT_specification) the correct context can be reconstructed by following the parent chain in the original dwarf unit. For nested structs like
Outer::Middle::Inner
we get something like this in the main dwarf unit:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh right, makes sense.
So for
DW_AT_specification
s, the referring DIE doesn't have the parent chain structure. So we must follow the DIE it referred to in order to reconstruct the context. WithDW_AT_signature
the context structure is maintained, so this now becomes redundant.