Skip to content

[DWARFVerifier] Fix debug_str_offsets DWARF version detection #81210

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

Closed
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
3 changes: 2 additions & 1 deletion llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ class DWARFVerifier {
/// \returns true if the .debug_line verifies successfully, false otherwise.
bool handleDebugStrOffsets();
bool verifyDebugStrOffsets(
StringRef SectionName, const DWARFSection &Section, StringRef StrData,
uint8_t MaxVersion, StringRef SectionName, const DWARFSection &Section,
StringRef StrData,
void (DWARFObject::*)(function_ref<void(const DWARFSection &)>) const);

/// Emits any aggregate information collected, depending on the dump options
Expand Down
25 changes: 14 additions & 11 deletions llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1882,29 +1882,31 @@ bool DWARFVerifier::handleDebugStrOffsets() {
const DWARFObject &DObj = DCtx.getDWARFObj();
bool Success = true;
Success &= verifyDebugStrOffsets(
".debug_str_offsets.dwo", DObj.getStrOffsetsDWOSection(),
DObj.getStrDWOSection(), &DWARFObject::forEachInfoDWOSections);
DCtx.getMaxDWOVersion(), ".debug_str_offsets.dwo",
DObj.getStrOffsetsDWOSection(), DObj.getStrDWOSection(),
&DWARFObject::forEachInfoDWOSections);
Success &= verifyDebugStrOffsets(
".debug_str_offsets", DObj.getStrOffsetsSection(), DObj.getStrSection(),
&DWARFObject::forEachInfoSections);
DCtx.getMaxVersion(), ".debug_str_offsets", DObj.getStrOffsetsSection(),
DObj.getStrSection(), &DWARFObject::forEachInfoSections);
return Success;
}

bool DWARFVerifier::verifyDebugStrOffsets(
StringRef SectionName, const DWARFSection &Section, StringRef StrData,
uint8_t MaxVersion, StringRef SectionName, const DWARFSection &Section,
StringRef StrData,
void (DWARFObject::*VisitInfoSections)(
function_ref<void(const DWARFSection &)>) const) {
const DWARFObject &DObj = DCtx.getDWARFObj();
uint16_t InfoVersion = 0;
DwarfFormat InfoFormat = DwarfFormat::DWARF32;

std::optional<DwarfFormat> MaybeInfoFormat;
(DObj.*VisitInfoSections)([&](const DWARFSection &S) {
if (InfoVersion)
if (MaybeInfoFormat)
return;
DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0);
uint64_t Offset = 0;
InfoFormat = DebugInfoData.getInitialLength(&Offset).second;
InfoVersion = DebugInfoData.getU16(&Offset);
MaybeInfoFormat = DebugInfoData.getInitialLength(&Offset).second;
});
DwarfFormat InfoFormat = MaybeInfoFormat.value_or(DwarfFormat::DWARF32);

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

Expand All @@ -1915,7 +1917,8 @@ bool DWARFVerifier::verifyDebugStrOffsets(
DwarfFormat Format;
uint64_t Length;
uint64_t StartOffset = C.tell();
if (InfoVersion == 4) {
if (MaxVersion == 4) {
// Pre-standardization debug_str_offsets had no header.
Format = InfoFormat;
Length = DA.getData().size();
NextUnit = C.tell() + Length;
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