[LLDB] - Add support for DW_FORM_implicit_const.
LLDB does not support this DWARF5 form atm. At least gcc emits it in some cases when doing optimization for abbreviations. As far I can tell, clang does not support it yet, though the rest LLVM code already knows about it. The patch adds the support. Differential revision: https://reviews.llvm.org/D52689 llvm-svn: 344328
This commit is contained in:
parent
487780678f
commit
230adfa96c
41
lldb/lit/Breakpoint/Inputs/implicit_const_form_support.yaml
Normal file
41
lldb/lit/Breakpoint/Inputs/implicit_const_form_support.yaml
Normal file
@ -0,0 +1,41 @@
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_EXEC
|
||||
Machine: EM_X86_64
|
||||
Entry: 0x00000000004004A0
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x00000000004004A0
|
||||
AddressAlign: 0x0000000000000010
|
||||
Content: 31ED4989D15E4889E24883E4F0505449C7C01006400048C7C1A005400048C7C77E054000E8B7FFFFFFF4660F1F440000B820204000483D202040007413B8000000004885C07409BF20204000FFE06690C30F1F440000662E0F1F840000000000BE202040004881EE2020400048C1FE034889F048C1E83F4801C648D1FE7411B8000000004885C07407BF20204000FFE0C30F1F440000662E0F1F840000000000803DD91A0000007517554889E5E87EFFFFFFC605C71A0000015DC30F1F440000C30F1F440000662E0F1F840000000000EB8EB800000000C3B800000000C3554889E5534883EC08E8E6FFFFFF89C3E8E5FFFFFF01D84883C4085B5DC30F1F4000415741564189FF415541544C8D251618000055488D2D16180000534989F64989D54C29E54883EC0848C1FD03E877FEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
|
||||
- Name: .debug_frame
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000008
|
||||
Content: 14000000FFFFFFFF03000178100C0708900100000000000014000000000000007205400000000000060000000000000014000000000000007805400000000000060000000000000034000000000000007E054000000000001E0000000000000004010000000E10860204030000000D060405000000830304140000000C070800
|
||||
- Name: .debug_info
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 900000000500010800000000023A00000021310000000000000072054000000000002A0000000000000000000000039A0000000109054C0000007E054000000000001E00000000000000019C040405696E7400012C000000059F0000004C00000078054000000000000600000000000000019C018C00000001910000004C00000072054000000000000600000000000000019C00
|
||||
- Name: .debug_abbrev
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 012E003F19030E3A21013B0B3921056E0E49131101120740187A190000021101250E130B030E1B0E1101120710170000032E003F19030E3A0B3B0B390B49131101120740187C1900000424000B0B3E0B0308000000
|
||||
- Name: .debug_aranges
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 2C00000002000000000008000000000072054000000000002A0000000000000000000000000000000000000000000000
|
||||
- Name: .debug_line
|
||||
Type: SHT_PROGBITS
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 5600000002001F0000000101FB0E0D00010101010000000100000100746573742E6370700000000000050C000902720540000000000001050913050159050C22050913050159050C22050D9105167405175805012F0207000101
|
||||
- Name: .debug_str
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_MERGE, SHF_STRINGS ]
|
||||
AddressAlign: 0x0000000000000001
|
||||
Content: 2F686F6D652F756D622F74657374735F323031382F3130315F696D706C696369745F636F6E73742F6E657700666F6F3200746573742E63707000474E5520432B2B313420382E302E3120323031383033313920286578706572696D656E74616C29202D6D74756E653D67656E65726963202D6D617263683D7838362D3634202D67202D6764776172662D3500666F6F31005F5A34666F6F3176006D61696E005F5A34666F6F327600
|
||||
Symbols:
|
||||
...
|
||||
33
lldb/lit/Breakpoint/implicit_const_form_support.test
Normal file
33
lldb/lit/Breakpoint/implicit_const_form_support.test
Normal file
@ -0,0 +1,33 @@
|
||||
# RUN: yaml2obj %p/Inputs/implicit_const_form_support.yaml > %ttest
|
||||
# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
|
||||
|
||||
## The intention of the test is to check that DW_FORM_implicit_const
|
||||
## is supported and handled properly.
|
||||
|
||||
## About implicit_const_form_support.yaml:
|
||||
## The following invocation and code were used to produce the binary
|
||||
## which was converted to yaml and reduced:
|
||||
## gcc version 8.0.1 20180319 (experimental) (GCC)
|
||||
##
|
||||
## g++ test.cpp -g -gdwarf-5 -o test
|
||||
##
|
||||
## // test.cpp
|
||||
## int foo1() {
|
||||
## return 0;
|
||||
## }
|
||||
##
|
||||
## int foo2() {
|
||||
## return 0;
|
||||
## }
|
||||
##
|
||||
## int main() {
|
||||
## return foo1() + foo2();
|
||||
## }
|
||||
|
||||
b foo1
|
||||
# CHECK-LABEL: b foo1
|
||||
# CHECK: Address: {{.*}}foo1() at test.cpp:2:9
|
||||
|
||||
b foo2
|
||||
# CHECK-LABEL: b foo2
|
||||
# CHECK: Address: {{.*}}foo2() at test.cpp:6:9
|
||||
@ -41,9 +41,13 @@ bool DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor &data,
|
||||
while (data.ValidOffset(*offset_ptr)) {
|
||||
dw_attr_t attr = data.GetULEB128(offset_ptr);
|
||||
dw_form_t form = data.GetULEB128(offset_ptr);
|
||||
DWARFFormValue::ValueType val;
|
||||
|
||||
if (form == DW_FORM_implicit_const)
|
||||
val.value.sval = data.GetULEB128(offset_ptr);
|
||||
|
||||
if (attr && form)
|
||||
m_attributes.push_back(DWARFAttribute(attr, form));
|
||||
m_attributes.push_back(DWARFAttribute(attr, form, val));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
@ -35,20 +35,11 @@ public:
|
||||
dw_form_t GetFormByIndex(uint32_t idx) const {
|
||||
return m_attributes.size() > idx ? m_attributes[idx].get_form() : 0;
|
||||
}
|
||||
bool GetAttrAndFormByIndex(uint32_t idx, dw_attr_t &attr,
|
||||
dw_form_t &form) const {
|
||||
if (m_attributes.size() > idx) {
|
||||
m_attributes[idx].get(attr, form);
|
||||
return true;
|
||||
}
|
||||
attr = form = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// idx is assumed to be valid when calling GetAttrAndFormByIndexUnchecked()
|
||||
void GetAttrAndFormByIndexUnchecked(uint32_t idx, dw_attr_t &attr,
|
||||
dw_form_t &form) const {
|
||||
m_attributes[idx].get(attr, form);
|
||||
// idx is assumed to be valid when calling GetAttrAndFormByIndex()
|
||||
void GetAttrAndFormValueByIndex(uint32_t idx, dw_attr_t &attr,
|
||||
DWARFFormValue &form_value) const {
|
||||
m_attributes[idx].get(attr, form_value.FormRef(), form_value.ValueRef());
|
||||
}
|
||||
dw_form_t GetFormByIndexUnchecked(uint32_t idx) const {
|
||||
return m_attributes[idx].get_form();
|
||||
|
||||
@ -26,10 +26,10 @@ uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
void DWARFAttributes::Append(const DWARFUnit *cu,
|
||||
dw_offset_t attr_die_offset, dw_attr_t attr,
|
||||
dw_form_t form) {
|
||||
AttributeValue attr_value = {cu, attr_die_offset, {attr, form}};
|
||||
void DWARFAttributes::Append(const DWARFUnit *cu, dw_offset_t attr_die_offset,
|
||||
dw_attr_t attr, dw_form_t form) {
|
||||
AttributeValue attr_value = {
|
||||
cu, attr_die_offset, {attr, form, DWARFFormValue::ValueType()}};
|
||||
m_infos.push_back(attr_value);
|
||||
}
|
||||
|
||||
|
||||
@ -11,15 +11,17 @@
|
||||
#define SymbolFileDWARF_DWARFAttribute_h_
|
||||
|
||||
#include "DWARFDefines.h"
|
||||
#include "DWARFFormValue.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <vector>
|
||||
|
||||
class DWARFUnit;
|
||||
class DWARFFormValue;
|
||||
|
||||
class DWARFAttribute {
|
||||
public:
|
||||
DWARFAttribute(dw_attr_t attr, dw_form_t form) : m_attr(attr), m_form(form) {}
|
||||
DWARFAttribute(dw_attr_t attr, dw_form_t form,
|
||||
DWARFFormValue::ValueType value)
|
||||
: m_attr(attr), m_form(form), m_value(value) {}
|
||||
|
||||
void set(dw_attr_t attr, dw_form_t form) {
|
||||
m_attr = attr;
|
||||
@ -29,9 +31,11 @@ public:
|
||||
void set_form(dw_form_t form) { m_form = form; }
|
||||
dw_attr_t get_attr() const { return m_attr; }
|
||||
dw_form_t get_form() const { return m_form; }
|
||||
void get(dw_attr_t &attr, dw_form_t &form) const {
|
||||
void get(dw_attr_t &attr, dw_form_t &form,
|
||||
DWARFFormValue::ValueType &val) const {
|
||||
attr = m_attr;
|
||||
form = m_form;
|
||||
val = m_value;
|
||||
}
|
||||
bool operator==(const DWARFAttribute &rhs) const {
|
||||
return m_attr == rhs.m_attr && m_form == rhs.m_form;
|
||||
@ -43,6 +47,7 @@ public:
|
||||
protected:
|
||||
dw_attr_t m_attr;
|
||||
dw_form_t m_form;
|
||||
DWARFFormValue::ValueType m_value;
|
||||
};
|
||||
|
||||
class DWARFAttributes {
|
||||
|
||||
@ -174,6 +174,10 @@ bool DWARFDebugInfoEntry::FastExtract(
|
||||
debug_info_data.GetU32(&offset);
|
||||
break;
|
||||
|
||||
case DW_FORM_implicit_const:
|
||||
form_size = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
*offset_ptr = m_offset;
|
||||
return false;
|
||||
@ -233,15 +237,14 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
|
||||
|
||||
// Skip all data in the .debug_info for the attributes
|
||||
const uint32_t numAttributes = abbrevDecl->NumAttributes();
|
||||
uint32_t i;
|
||||
dw_attr_t attr;
|
||||
dw_form_t form;
|
||||
for (i = 0; i < numAttributes; ++i) {
|
||||
abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
|
||||
for (uint32_t i = 0; i < numAttributes; ++i) {
|
||||
DWARFFormValue form_value(cu);
|
||||
dw_attr_t attr;
|
||||
abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
|
||||
dw_form_t form = form_value.Form();
|
||||
|
||||
if (isCompileUnitTag &&
|
||||
((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) {
|
||||
DWARFFormValue form_value(cu, form);
|
||||
if (form_value.ExtractValue(debug_info_data, &offset)) {
|
||||
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
|
||||
const_cast<DWARFUnit *>(cu)->SetBaseAddress(
|
||||
@ -287,6 +290,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
|
||||
|
||||
// 0 sized form
|
||||
case DW_FORM_flag_present:
|
||||
case DW_FORM_implicit_const:
|
||||
form_size = 0;
|
||||
break;
|
||||
|
||||
@ -417,14 +421,13 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
|
||||
return false;
|
||||
|
||||
const uint32_t numAttributes = abbrevDecl->NumAttributes();
|
||||
uint32_t i;
|
||||
dw_attr_t attr;
|
||||
dw_form_t form;
|
||||
bool do_offset = false;
|
||||
|
||||
for (i = 0; i < numAttributes; ++i) {
|
||||
abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
|
||||
DWARFFormValue form_value(cu, form);
|
||||
for (uint32_t i = 0; i < numAttributes; ++i) {
|
||||
DWARFFormValue form_value(cu);
|
||||
dw_attr_t attr;
|
||||
abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
|
||||
|
||||
if (form_value.ExtractValue(debug_info_data, &offset)) {
|
||||
switch (attr) {
|
||||
case DW_AT_low_pc:
|
||||
@ -614,14 +617,13 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
|
||||
|
||||
// Dump all data in the .debug_info for the attributes
|
||||
const uint32_t numAttributes = abbrevDecl->NumAttributes();
|
||||
uint32_t i;
|
||||
dw_attr_t attr;
|
||||
dw_form_t form;
|
||||
for (i = 0; i < numAttributes; ++i) {
|
||||
abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
|
||||
for (uint32_t i = 0; i < numAttributes; ++i) {
|
||||
DWARFFormValue form_value(cu);
|
||||
dw_attr_t attr;
|
||||
abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
|
||||
|
||||
DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr,
|
||||
form);
|
||||
form_value);
|
||||
}
|
||||
|
||||
const DWARFDebugInfoEntry *child = GetFirstChild();
|
||||
@ -671,23 +673,21 @@ void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data,
|
||||
void DWARFDebugInfoEntry::DumpAttribute(
|
||||
SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
|
||||
const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr,
|
||||
Stream &s, dw_attr_t attr, dw_form_t form) {
|
||||
Stream &s, dw_attr_t attr, DWARFFormValue &form_value) {
|
||||
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
|
||||
|
||||
s.Printf(" ");
|
||||
s.Indent(DW_AT_value_to_name(attr));
|
||||
|
||||
if (show_form) {
|
||||
s.Printf("[%s", DW_FORM_value_to_name(form));
|
||||
s.Printf("[%s", DW_FORM_value_to_name(form_value.Form()));
|
||||
}
|
||||
|
||||
DWARFFormValue form_value(cu, form);
|
||||
|
||||
if (!form_value.ExtractValue(debug_info_data, offset_ptr))
|
||||
return;
|
||||
|
||||
if (show_form) {
|
||||
if (form == DW_FORM_indirect) {
|
||||
if (form_value.Form() == DW_FORM_indirect) {
|
||||
s.Printf(" [%s]", DW_FORM_value_to_name(form_value.Form()));
|
||||
}
|
||||
|
||||
@ -794,11 +794,11 @@ size_t DWARFDebugInfoEntry::GetAttributes(
|
||||
cu->GetAddressByteSize(), cu->IsDWARF64());
|
||||
|
||||
const uint32_t num_attributes = abbrevDecl->NumAttributes();
|
||||
uint32_t i;
|
||||
dw_attr_t attr;
|
||||
dw_form_t form;
|
||||
for (i = 0; i < num_attributes; ++i) {
|
||||
abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
|
||||
for (uint32_t i = 0; i < num_attributes; ++i) {
|
||||
DWARFFormValue form_value(cu);
|
||||
dw_attr_t attr;
|
||||
abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
|
||||
const dw_form_t form = form_value.Form();
|
||||
|
||||
// If we are tracking down DW_AT_specification or DW_AT_abstract_origin
|
||||
// attributes, the depth will be non-zero. We need to omit certain
|
||||
@ -819,7 +819,6 @@ size_t DWARFDebugInfoEntry::GetAttributes(
|
||||
}
|
||||
|
||||
if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) {
|
||||
DWARFFormValue form_value(cu, form);
|
||||
if (form_value.ExtractValue(debug_info_data, &offset)) {
|
||||
dw_offset_t die_offset = form_value.Reference();
|
||||
DWARFDIE spec_die =
|
||||
|
||||
@ -178,7 +178,7 @@ public:
|
||||
DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
|
||||
const lldb_private::DWARFDataExtractor &debug_info_data,
|
||||
lldb::offset_t *offset_ptr, lldb_private::Stream &s,
|
||||
dw_attr_t attr, dw_form_t form);
|
||||
dw_attr_t attr, DWARFFormValue &form_value);
|
||||
// This one dumps the comp unit name, objfile name and die offset for this die
|
||||
// so the stream S.
|
||||
void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
|
||||
|
||||
@ -154,6 +154,9 @@ DWARFFormValue::GetFixedFormSizesForAddressSize(uint8_t addr_size,
|
||||
|
||||
DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {}
|
||||
|
||||
DWARFFormValue::DWARFFormValue(const DWARFUnit *cu)
|
||||
: m_cu(cu), m_form(0), m_value() {}
|
||||
|
||||
DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form)
|
||||
: m_cu(cu), m_form(form), m_value() {}
|
||||
|
||||
@ -165,6 +168,9 @@ void DWARFFormValue::Clear() {
|
||||
|
||||
bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
|
||||
lldb::offset_t *offset_ptr) {
|
||||
if (m_form == DW_FORM_implicit_const)
|
||||
return true;
|
||||
|
||||
bool indirect = false;
|
||||
bool is_block = false;
|
||||
m_value.data = NULL;
|
||||
@ -366,6 +372,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
|
||||
|
||||
// 0 bytes values (implied from DW_FORM)
|
||||
case DW_FORM_flag_present:
|
||||
case DW_FORM_implicit_const:
|
||||
return true;
|
||||
|
||||
// 1 byte values
|
||||
@ -822,6 +829,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) {
|
||||
case DW_FORM_ref_sig8:
|
||||
case DW_FORM_GNU_str_index:
|
||||
case DW_FORM_GNU_addr_index:
|
||||
case DW_FORM_implicit_const:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -56,12 +56,17 @@ public:
|
||||
};
|
||||
|
||||
DWARFFormValue();
|
||||
DWARFFormValue(const DWARFUnit *cu);
|
||||
DWARFFormValue(const DWARFUnit *cu, dw_form_t form);
|
||||
const DWARFUnit *GetCompileUnit() const { return m_cu; }
|
||||
void SetCompileUnit(const DWARFUnit *cu) { m_cu = cu; }
|
||||
dw_form_t Form() const { return m_form; }
|
||||
dw_form_t& FormRef() { return m_form; }
|
||||
void SetForm(dw_form_t form) { m_form = form; }
|
||||
const ValueType &Value() const { return m_value; }
|
||||
ValueType &ValueRef() { return m_value; }
|
||||
void SetValue(const ValueType &val) { m_value = val; }
|
||||
|
||||
void Dump(lldb_private::Stream &s) const;
|
||||
bool ExtractValue(const lldb_private::DWARFDataExtractor &data,
|
||||
lldb::offset_t *offset_ptr);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user