forked from OSchip/llvm-project
[llvm-dwarfdump] - Fix incorrect parsing of the DW_LLE_startx_length
As was already mentioned in comments for D53364, DWARF 5 spec says about DW_LLE_startx_length: "This is a form of bounded location description that has two unsigned ULEB operands. The first value is an address index (into the .debug_addr section) that indicates the beginning of the address range over which the location is valid. The second value is the length of the range. ") Currently, the length is always parsed as U32. Patch change the behavior to parse DW_LLE_startx_length as ULEB128 for DWARF 5 and keeps it as U32 for DWARF4+(pre-DWARF5) for compatibility. Differential revision: https://reviews.llvm.org/D53564 llvm-svn: 345254
This commit is contained in:
parent
071e82218f
commit
581fc63dc0
|
@ -100,15 +100,15 @@ private:
|
||||||
bool IsLittleEndian;
|
bool IsLittleEndian;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void parse(DataExtractor data);
|
void parse(DataExtractor data, unsigned Version);
|
||||||
void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo,
|
void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo,
|
||||||
Optional<uint64_t> Offset) const;
|
Optional<uint64_t> Offset) const;
|
||||||
|
|
||||||
/// Return the location list at the given offset or nullptr.
|
/// Return the location list at the given offset or nullptr.
|
||||||
LocationList const *getLocationListAtOffset(uint64_t Offset) const;
|
LocationList const *getLocationListAtOffset(uint64_t Offset) const;
|
||||||
|
|
||||||
static Optional<LocationList> parseOneLocationList(DataExtractor Data,
|
static Optional<LocationList>
|
||||||
uint32_t *Offset);
|
parseOneLocationList(DataExtractor Data, unsigned *Offset, unsigned Version);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
|
@ -99,6 +99,7 @@ public:
|
||||||
uint32_t getHeaderOffset() const { return HeaderOffset; }
|
uint32_t getHeaderOffset() const { return HeaderOffset; }
|
||||||
uint8_t getAddrSize() const { return HeaderData.AddrSize; }
|
uint8_t getAddrSize() const { return HeaderData.AddrSize; }
|
||||||
uint32_t getLength() const { return HeaderData.Length; }
|
uint32_t getLength() const { return HeaderData.Length; }
|
||||||
|
uint16_t getVersion() const { return HeaderData.Version; }
|
||||||
StringRef getSectionName() const { return SectionName; }
|
StringRef getSectionName() const { return SectionName; }
|
||||||
StringRef getListTypeString() const { return ListTypeString; }
|
StringRef getListTypeString() const { return ListTypeString; }
|
||||||
dwarf::DwarfFormat getFormat() const { return Format; }
|
dwarf::DwarfFormat getFormat() const { return Format; }
|
||||||
|
|
|
@ -309,7 +309,7 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
|
||||||
DataExtractor LocData(Data.getData().drop_front(Offset),
|
DataExtractor LocData(Data.getData().drop_front(Offset),
|
||||||
Data.isLittleEndian(), Header.getAddrSize());
|
Data.isLittleEndian(), Header.getAddrSize());
|
||||||
|
|
||||||
Loclists.parse(LocData);
|
Loclists.parse(LocData, Header.getVersion());
|
||||||
Loclists.dump(OS, 0, MRI, DumpOffset);
|
Loclists.dump(OS, 0, MRI, DumpOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +732,10 @@ const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() {
|
||||||
// FIXME: We don't need AddressSize for split DWARF since relocatable
|
// FIXME: We don't need AddressSize for split DWARF since relocatable
|
||||||
// addresses cannot appear there. At the moment DWARFExpression requires it.
|
// addresses cannot appear there. At the moment DWARFExpression requires it.
|
||||||
DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4);
|
DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4);
|
||||||
LocDWO->parse(LocData);
|
// Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and
|
||||||
|
// that means we are parsing the new style .debug_loc (pre-standatized version
|
||||||
|
// of the .debug_loclists).
|
||||||
|
LocDWO->parse(LocData, 4 /* Version */);
|
||||||
return LocDWO.get();
|
return LocDWO.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,7 +145,8 @@ void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<DWARFDebugLoclists::LocationList>
|
Optional<DWARFDebugLoclists::LocationList>
|
||||||
DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
|
DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset,
|
||||||
|
unsigned Version) {
|
||||||
LocationList LL;
|
LocationList LL;
|
||||||
LL.Offset = *Offset;
|
LL.Offset = *Offset;
|
||||||
|
|
||||||
|
@ -158,7 +159,12 @@ DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
|
||||||
switch (Kind) {
|
switch (Kind) {
|
||||||
case dwarf::DW_LLE_startx_length:
|
case dwarf::DW_LLE_startx_length:
|
||||||
E.Value0 = Data.getULEB128(Offset);
|
E.Value0 = Data.getULEB128(Offset);
|
||||||
E.Value1 = Data.getU32(Offset);
|
// Pre-DWARF 5 has different interpretation of the length field. We have
|
||||||
|
// to support both pre- and standartized styles for the compatibility.
|
||||||
|
if (Version < 5)
|
||||||
|
E.Value1 = Data.getU32(Offset);
|
||||||
|
else
|
||||||
|
E.Value1 = Data.getULEB128(Offset);
|
||||||
break;
|
break;
|
||||||
case dwarf::DW_LLE_start_length:
|
case dwarf::DW_LLE_start_length:
|
||||||
E.Value0 = Data.getAddress(Offset);
|
E.Value0 = Data.getAddress(Offset);
|
||||||
|
@ -189,13 +195,13 @@ DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
|
||||||
return LL;
|
return LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DWARFDebugLoclists::parse(DataExtractor data) {
|
void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) {
|
||||||
IsLittleEndian = data.isLittleEndian();
|
IsLittleEndian = data.isLittleEndian();
|
||||||
AddressSize = data.getAddressSize();
|
AddressSize = data.getAddressSize();
|
||||||
|
|
||||||
uint32_t Offset = 0;
|
uint32_t Offset = 0;
|
||||||
while (data.isValidOffset(Offset)) {
|
while (data.isValidOffset(Offset)) {
|
||||||
if (auto LL = parseOneLocationList(data, &Offset))
|
if (auto LL = parseOneLocationList(data, &Offset, Version))
|
||||||
Locations.push_back(std::move(*LL));
|
Locations.push_back(std::move(*LL));
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -118,12 +118,20 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UseLocLists = !U->isDWOUnit();
|
||||||
StringRef LoclistsSectionData =
|
StringRef LoclistsSectionData =
|
||||||
U->isDWOUnit() ? U->getLocSectionData() : Obj.getLoclistsSection().Data;
|
UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData();
|
||||||
|
|
||||||
if (!LoclistsSectionData.empty()) {
|
if (!LoclistsSectionData.empty()) {
|
||||||
DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(),
|
DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(),
|
||||||
Obj.getAddressSize());
|
Obj.getAddressSize());
|
||||||
auto LL = DWARFDebugLoclists::parseOneLocationList(Data, &Offset);
|
|
||||||
|
// Old-style location list were used in DWARF v4 (.debug_loc.dwo section).
|
||||||
|
// Modern locations list (.debug_loclists) are used starting from v5.
|
||||||
|
// Ideally we should take the version from the .debug_loclists section
|
||||||
|
// header, but using CU's version for simplicity.
|
||||||
|
auto LL = DWARFDebugLoclists::parseOneLocationList(
|
||||||
|
Data, &Offset, UseLocLists ? U->getVersion() : 4);
|
||||||
|
|
||||||
uint64_t BaseAddr = 0;
|
uint64_t BaseAddr = 0;
|
||||||
if (Optional<SectionedAddress> BA = U->getBaseAddress())
|
if (Optional<SectionedAddress> BA = U->getBaseAddress())
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o
|
||||||
|
# RUN: llvm-dwarfdump -v %t.o | FileCheck %s
|
||||||
|
|
||||||
|
# DW_LLE_startx_length has different `length` encoding in pre-DWARF 5
|
||||||
|
# and final DWARF 5 versions. This test checks we are able to parse
|
||||||
|
# the final version which uses ULEB128 and not the U32.
|
||||||
|
|
||||||
|
# CHECK: .debug_loclists contents:
|
||||||
|
# CHECK-NEXT: 0x00000000: locations list header: length = 0x0000000f, version = 0x0005, addr_size = 0x08, seg_size = 0x00, offset_entry_count = 0x00000000
|
||||||
|
# CHECK-NEXT: 0x00000000:
|
||||||
|
# CHECK-NEXT: Addr idx 1 (w/ length 16): DW_OP_reg5 RDI
|
||||||
|
|
||||||
|
.section .debug_loclists,"",@progbits
|
||||||
|
.long .Ldebug_loclist_table_end0-.Ldebug_loclist_table_start0
|
||||||
|
.Ldebug_loclist_table_start0:
|
||||||
|
.short 5 # Version.
|
||||||
|
.byte 8 # Address size.
|
||||||
|
.byte 0 # Segmen selector size.
|
||||||
|
.long 0 # Offset entry count.
|
||||||
|
|
||||||
|
.byte 3 # DW_LLE_startx_length
|
||||||
|
.byte 0x01 # Index
|
||||||
|
.uleb128 0x10 # Length
|
||||||
|
.short 1 # Loc expr size
|
||||||
|
.byte 85 # DW_OP_reg5
|
||||||
|
.byte 0 # DW_LLE_end_of_list
|
||||||
|
.Ldebug_loclist_table_end0:
|
Loading…
Reference in New Issue