Skip to content

[CherryPick][DWARFVerifier] Fi x debug_str_offsets DWARF version detection (#81303) #8172

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,9 @@ class DWARFVerifier {
///
/// \returns true if the .debug_line verifies successfully, false otherwise.
bool handleDebugStrOffsets();
bool verifyDebugStrOffsets(
StringRef SectionName, const DWARFSection &Section, StringRef StrData,
void (DWARFObject::*)(function_ref<void(const DWARFSection &)>) const);
bool verifyDebugStrOffsets(std::optional<dwarf::DwarfFormat> LegacyFormat,
StringRef SectionName, const DWARFSection &Section,
StringRef StrData);
};

static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
Expand Down
45 changes: 25 additions & 20 deletions llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1697,42 +1697,47 @@ bool DWARFVerifier::handleDebugStrOffsets() {
OS << "Verifying .debug_str_offsets...\n";
const DWARFObject &DObj = DCtx.getDWARFObj();
bool Success = true;

// dwo sections may contain the legacy debug_str_offsets format (and they
// can't be mixed with dwarf 5's format). This section format contains no
// header.
// As such, check the version from debug_info and, if we are in the legacy
// mode (Dwarf <= 4), extract Dwarf32/Dwarf64.
std::optional<DwarfFormat> DwoLegacyDwarf4Format;
DObj.forEachInfoDWOSections([&](const DWARFSection &S) {
if (DwoLegacyDwarf4Format)
return;
DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
uint64_t Offset = 0;
DwarfFormat InfoFormat = DebugInfoData.getInitialLength(&Offset).second;
if (uint16_t InfoVersion = DebugInfoData.getU16(&Offset); InfoVersion <= 4)
DwoLegacyDwarf4Format = InfoFormat;
});

Success &= verifyDebugStrOffsets(
".debug_str_offsets.dwo", DObj.getStrOffsetsDWOSection(),
DObj.getStrDWOSection(), &DWARFObject::forEachInfoDWOSections);
DwoLegacyDwarf4Format, ".debug_str_offsets.dwo",
DObj.getStrOffsetsDWOSection(), DObj.getStrDWOSection());
Success &= verifyDebugStrOffsets(
".debug_str_offsets", DObj.getStrOffsetsSection(), DObj.getStrSection(),
&DWARFObject::forEachInfoSections);
/*LegacyFormat=*/std::nullopt, ".debug_str_offsets",
DObj.getStrOffsetsSection(), DObj.getStrSection());
return Success;
}

bool DWARFVerifier::verifyDebugStrOffsets(
StringRef SectionName, const DWARFSection &Section, StringRef StrData,
void (DWARFObject::*VisitInfoSections)(
function_ref<void(const DWARFSection &)>) const) {
std::optional<DwarfFormat> LegacyFormat, StringRef SectionName,
const DWARFSection &Section, StringRef StrData) {
const DWARFObject &DObj = DCtx.getDWARFObj();
uint16_t InfoVersion = 0;
DwarfFormat InfoFormat = DwarfFormat::DWARF32;
(DObj.*VisitInfoSections)([&](const DWARFSection &S) {
if (InfoVersion)
return;
DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
uint64_t Offset = 0;
InfoFormat = DebugInfoData.getInitialLength(&Offset).second;
InfoVersion = DebugInfoData.getU16(&Offset);
});

DWARFDataExtractor DA(DObj, Section, DCtx.isLittleEndian(), 0);

DataExtractor::Cursor C(0);
uint64_t NextUnit = 0;
bool Success = true;
while (C.seek(NextUnit), C.tell() < DA.getData().size()) {
DwarfFormat Format;
uint64_t Length;
uint64_t StartOffset = C.tell();
if (InfoVersion == 4) {
Format = InfoFormat;
if (LegacyFormat) {
Format = *LegacyFormat;
Length = DA.getData().size();
NextUnit = C.tell() + Length;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# RUN: yaml2obj %s -o %t.o
# RUN: llvm-dwarfdump -debug-str-offsets -verify %t.o | FileCheck %s

# CHECK: Verifying .debug_str_offsets...
# CHECK: No errors

# Check that when mixing standard DWARF 4 debug information with standard DWARF
# 5 debug information, the verifier correctly interprets the debug_str_offsets
# section as a standards-conforming DWARF 5 section.

--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
DWARF:
debug_str:
- 'cu1'
- 'cu2'
debug_str_offsets:
- Offsets:
- 0x0
debug_abbrev:
- Table:
- Code: 0x1
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Code: 0x2
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strx1
- Attribute: DW_AT_str_offsets_base
Form: DW_FORM_sec_offset
debug_info:
- Version: 4
AbbrevTableID: 0
AbbrOffset: 0x0
AddrSize: 8
Entries:
- AbbrCode: 0x1
Values:
- Value: 0x4
- Version: 5
UnitType: DW_UT_compile
AbbrOffset: 0x0
AddrSize: 8
AbbrevTableID: 0
Entries:
- AbbrCode: 0x2
Values:
- Value: 0x0
- Value: 0x8 # str offsets base
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# CHECK-NEXT: error: .debug_str_offsets: contribution 0x29: length exceeds available space (contribution offset (0x29) + length field space (0x4) + length (0x5000000) == 0x500002D > section size 0x30)
# Errors detected.

# V4: error: .debug_str_offsets: contribution 0x0: index 0x2: invalid string offset *0x8 == 0x2, is neither zero nor immediately following a null character
# V4: error: .debug_str_offsets.dwo: contribution 0x0: index 0x2: invalid string offset *0x8 == 0x2, is neither zero nor immediately following a null character


#--- v4.yaml
Expand All @@ -23,16 +23,17 @@ FileHeader:
Data: ELFDATA2LSB
Type: ET_EXEC
DWARF:
debug_str:
- 'foo'
- 'bar'
debug_info:
- Version: 4
AddrSize: 4
Sections:
- Name: '.debug_str_offsets'
- Name: '.debug_info.dwo'
Type: SHT_PROGBITS
Content: "0700000004000000000004"
- Name: '.debug_str_offsets.dwo'
Type: SHT_PROGBITS
Content: "000000000400000002000000"
- Name: 'debug_str.dwo'
Type: SHT_PROGBITS
Content: "666F6F0062617200"


#--- v5.yaml
--- !ELF
Expand Down