Skip to content

Commit

Permalink
Modify llvm-gsymutil to ignore invalid file indexes (llvm#71431)
Browse files Browse the repository at this point in the history
DWARF produced by LTO and BOLT can sometimes be broken where file
indexes are beyond the end of the line table's file list in the
prologue. This patch allows llvm-gsymutil to convert this DWARF without
crashing, and emits errors when:

line table contains entries with an invalid file index (line entry will
be removed) inline functions that have invalid DW_AT_call_file file
indexes when there are no line table entries for a function and we fall
back to making a single line table entry from the functions
DW_AT_decl_file/DW_AT_decl_line attributes, we make sure the
DW_AT_decl_file attribute is valid before emitting it.
  • Loading branch information
clayborg authored Nov 6, 2023
1 parent e15fcd7 commit 0156b6e
Show file tree
Hide file tree
Showing 2 changed files with 405 additions and 14 deletions.
63 changes: 49 additions & 14 deletions llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ struct llvm::gsym::CUInfo {
/// the first client that asks for a compile unit file index will end up
/// doing the conversion, and subsequent clients will get the cached GSYM
/// index.
uint32_t DWARFToGSYMFileIndex(GsymCreator &Gsym, uint32_t DwarfFileIdx) {
if (!LineTable)
return 0;
assert(DwarfFileIdx < FileCache.size());
std::optional<uint32_t> DWARFToGSYMFileIndex(GsymCreator &Gsym,
uint32_t DwarfFileIdx) {
if (!LineTable || DwarfFileIdx >= FileCache.size())
return std::nullopt;
uint32_t &GsymFileIdx = FileCache[DwarfFileIdx];
if (GsymFileIdx != UINT32_MAX)
return GsymFileIdx;
Expand Down Expand Up @@ -272,14 +272,24 @@ static void parseInlineInfo(GsymCreator &Gsym, raw_ostream *Log, CUInfo &CUI,

if (auto NameIndex = getQualifiedNameIndex(Die, CUI.Language, Gsym))
II.Name = *NameIndex;
II.CallFile = CUI.DWARFToGSYMFileIndex(
Gsym, dwarf::toUnsigned(Die.find(dwarf::DW_AT_call_file), 0));
II.CallLine = dwarf::toUnsigned(Die.find(dwarf::DW_AT_call_line), 0);
// parse all children and append to parent
for (DWARFDie ChildDie : Die.children())
parseInlineInfo(Gsym, Log, CUI, ChildDie, Depth + 1, FI, II,
AllInlineRanges, WarnIfEmpty);
Parent.Children.emplace_back(std::move(II));
const uint64_t DwarfFileIdx = dwarf::toUnsigned(
Die.findRecursively(dwarf::DW_AT_call_file), UINT32_MAX);
std::optional<uint32_t> OptGSymFileIdx =
CUI.DWARFToGSYMFileIndex(Gsym, DwarfFileIdx);
if (OptGSymFileIdx) {
II.CallFile = OptGSymFileIdx.value();
II.CallLine = dwarf::toUnsigned(Die.find(dwarf::DW_AT_call_line), 0);
// parse all children and append to parent
for (DWARFDie ChildDie : Die.children())
parseInlineInfo(Gsym, Log, CUI, ChildDie, Depth + 1, FI, II,
AllInlineRanges, WarnIfEmpty);
Parent.Children.emplace_back(std::move(II));
} else if (Log) {
*Log << "error: inlined function DIE at " << HEX32(Die.getOffset())
<< " has an invalid file index " << DwarfFileIdx
<< " in its DW_AT_call_file attribute, this inline entry and all "
<< "children will be removed.\n";
}
return;
}
if (Tag == dwarf::DW_TAG_subprogram || Tag == dwarf::DW_TAG_lexical_block) {
Expand All @@ -306,8 +316,20 @@ static void convertFunctionLineTable(raw_ostream *Log, CUInfo &CUI,
// the DW_AT_decl_file an d DW_AT_decl_line if we have both attributes.
std::string FilePath = Die.getDeclFile(
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
if (FilePath.empty())
if (FilePath.empty()) {
// If we had a DW_AT_decl_file, but got no file then we need to emit a
// warning.
if (Log) {
const uint64_t DwarfFileIdx = dwarf::toUnsigned(
Die.findRecursively(dwarf::DW_AT_decl_file), UINT32_MAX);
*Log << "error: function DIE at " << HEX32(Die.getOffset())
<< " has an invalid file index " << DwarfFileIdx
<< " in its DW_AT_decl_file attribute, unable to create a single "
<< "line entry from the DW_AT_decl_file/DW_AT_decl_line "
<< "attributes.\n";
}
return;
}
if (auto Line =
dwarf::toUnsigned(Die.findRecursively({dwarf::DW_AT_decl_line}))) {
LineEntry LE(StartAddress, Gsym.insertFile(FilePath), *Line);
Expand All @@ -322,7 +344,20 @@ static void convertFunctionLineTable(raw_ostream *Log, CUInfo &CUI,
for (uint32_t RowIndex : RowVector) {
// Take file number and line/column from the row.
const DWARFDebugLine::Row &Row = CUI.LineTable->Rows[RowIndex];
const uint32_t FileIdx = CUI.DWARFToGSYMFileIndex(Gsym, Row.File);
std::optional<uint32_t> OptFileIdx =
CUI.DWARFToGSYMFileIndex(Gsym, Row.File);
if (!OptFileIdx) {
if (Log) {
*Log << "error: function DIE at " << HEX32(Die.getOffset()) << " has "
<< "a line entry with invalid DWARF file index, this entry will "
<< "be removed:\n";
Row.dumpTableHeader(*Log, /*Indent=*/0);
Row.dump(*Log);
*Log << "\n";
}
continue;
}
const uint32_t FileIdx = OptFileIdx.value();
uint64_t RowAddress = Row.Address.Address;
// Watch out for a RowAddress that is in the middle of a line table entry
// in the DWARF. If we pass an address in between two line table entries
Expand Down
Loading

0 comments on commit 0156b6e

Please sign in to comment.