Skip to content

Commit fe899ce

Browse files
[DWARFLinker] Fix matching logic to remove type 1 missing offset (#151427)
Reverts the [revert](#151424) and fixed some typos. Original PR description: Second attempt to fix https://discourse.llvm.org/t/rfc-new-dwarf-attribute-for-symbolication-of-merged-functions/79434/29?u=alx32 (First attempt: #143656) Context: the sequence offset to row index we parsed may not be complete. And we need to add manual matching to it. #143656 attempts to do trivial 1:1 matching, however, sometimes they don't line up perfectly, as shown below: // While SeqOffToOrigRow parsed from CU could be the ground truth, // e.g. // // SeqOff Row // 0x08 9 // 0x14 15 // // The StmtAttrs and SeqStartRows may not match perfectly, e.g. // // StmtAttrs SeqStartRows // 0x04 3 // 0x08 5 // 0x10 9 // 0x12 11 // 0x14 15 // // In this case, we don't want to assign 5 to 0x08, since we know 0x08 // maps to 9. If we do a dummy 1:1 mapping 0x10 will be mapped to 9 // which is incorrect. The expected behavior is ignore 5, realign the // table based on the result from the line table: // // StmtAttrs SeqStartRows // 0x04 3 // -- 5 // 0x08 9 <- LineTableMapping ground truth // 0x10 11 // 0x12 -- // 0x14 15 <- LineTableMapping ground truth In this case, we need to use the mapping we read from the line table as a ground truth and organize them properly to prevent duplicated offset/missing offset. Test: Updated the test case --------- Signed-off-by: Peter Rong <[email protected]> Co-authored-by: Ellis Hoag <[email protected]>
1 parent d6c85fc commit fe899ce

File tree

2 files changed

+586
-311
lines changed

2 files changed

+586
-311
lines changed

llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,117 @@ static bool isTlsAddressCode(uint8_t DW_OP_Code) {
413413
DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
414414
}
415415

416+
static void constructSeqOffsettoOrigRowMapping(
417+
CompileUnit &Unit, const DWARFDebugLine::LineTable &LT,
418+
DenseMap<uint64_t, unsigned> &SeqOffToOrigRow) {
419+
420+
// Use std::map for ordered iteration.
421+
std::map<uint64_t, unsigned> LineTableMapping;
422+
423+
// First, trust the sequences that the DWARF parser did identify.
424+
for (const DWARFDebugLine::Sequence &Seq : LT.Sequences)
425+
LineTableMapping[Seq.StmtSeqOffset] = Seq.FirstRowIndex;
426+
427+
// Second, manually find sequence boundaries and match them to the
428+
// sorted attributes to handle sequences the parser might have missed.
429+
auto StmtAttrs = Unit.getStmtSeqListAttributes();
430+
llvm::sort(StmtAttrs, [](const PatchLocation &A, const PatchLocation &B) {
431+
return A.get() < B.get();
432+
});
433+
434+
std::vector<unsigned> SeqStartRows;
435+
SeqStartRows.push_back(0);
436+
for (auto [I, Row] : llvm::enumerate(ArrayRef(LT.Rows).drop_back()))
437+
if (Row.EndSequence)
438+
SeqStartRows.push_back(I + 1);
439+
440+
// While SeqOffToOrigRow parsed from CU could be the ground truth,
441+
// e.g.
442+
//
443+
// SeqOff Row
444+
// 0x08 9
445+
// 0x14 15
446+
//
447+
// The StmtAttrs and SeqStartRows may not match perfectly, e.g.
448+
//
449+
// StmtAttrs SeqStartRows
450+
// 0x04 3
451+
// 0x08 5
452+
// 0x10 9
453+
// 0x12 11
454+
// 0x14 15
455+
//
456+
// In this case, we don't want to assign 5 to 0x08, since we know 0x08
457+
// maps to 9. If we do a dummy 1:1 mapping 0x10 will be mapped to 9
458+
// which is incorrect. The expected behavior is ignore 5, realign the
459+
// table based on the result from the line table:
460+
//
461+
// StmtAttrs SeqStartRows
462+
// 0x04 3
463+
// -- 5
464+
// 0x08 9 <- LineTableMapping ground truth
465+
// 0x10 11
466+
// 0x12 --
467+
// 0x14 15 <- LineTableMapping ground truth
468+
469+
ArrayRef StmtAttrsRef(StmtAttrs);
470+
ArrayRef SeqStartRowsRef(SeqStartRows);
471+
472+
// Dummy last element to make sure StmtAttrsRef and SeqStartRowsRef always
473+
// run out first.
474+
constexpr uint64_t DummyKey = UINT64_MAX;
475+
constexpr unsigned DummyVal = UINT32_MAX;
476+
LineTableMapping[DummyKey] = DummyVal;
477+
478+
for (auto [NextSeqOff, NextRow] : LineTableMapping) {
479+
// Explict capture to avoid capturing structured bindings and make C++17
480+
// happy.
481+
auto StmtAttrSmallerThanNext = [N = NextSeqOff](const PatchLocation &SA) {
482+
return SA.get() < N;
483+
};
484+
auto SeqStartSmallerThanNext = [N = NextRow](const unsigned &Row) {
485+
return Row < N;
486+
};
487+
// If both StmtAttrs and SeqStartRows points to value not in
488+
// the LineTableMapping yet, we do a dummy one to one mapping and
489+
// move the pointer.
490+
while (!StmtAttrsRef.empty() && !SeqStartRowsRef.empty() &&
491+
StmtAttrSmallerThanNext(StmtAttrsRef.front()) &&
492+
SeqStartSmallerThanNext(SeqStartRowsRef.front())) {
493+
SeqOffToOrigRow[StmtAttrsRef.consume_front().get()] =
494+
SeqStartRowsRef.consume_front();
495+
}
496+
// One of the pointer points to the value at or past Next in the
497+
// LineTableMapping, We move the pointer to re-align with the
498+
// LineTableMapping
499+
StmtAttrsRef = StmtAttrsRef.drop_while(StmtAttrSmallerThanNext);
500+
SeqStartRowsRef = SeqStartRowsRef.drop_while(SeqStartSmallerThanNext);
501+
// Use the LineTableMapping's result as the ground truth and move
502+
// on.
503+
if (NextSeqOff != DummyKey) {
504+
SeqOffToOrigRow[NextSeqOff] = NextRow;
505+
}
506+
// Move the pointers if they are pointed at Next.
507+
// It is possible that they point to later entries in LineTableMapping.
508+
// Therefore we only increment the pointers after we validate they are
509+
// pointing to the `Next` entry. e.g.
510+
//
511+
// LineTableMapping
512+
// SeqOff Row
513+
// 0x08 9 <- NextSeqOff/NextRow
514+
// 0x14 15
515+
//
516+
// StmtAttrs SeqStartRows
517+
// 0x14 13 <- StmtAttrsRef.front() / SeqStartRowsRef.front()
518+
// 0x16 15
519+
// -- 17
520+
if (!StmtAttrsRef.empty() && StmtAttrsRef.front().get() == NextSeqOff)
521+
StmtAttrsRef.consume_front();
522+
if (!SeqStartRowsRef.empty() && SeqStartRowsRef.front() == NextRow)
523+
SeqStartRowsRef.consume_front();
524+
}
525+
}
526+
416527
std::pair<bool, std::optional<int64_t>>
417528
DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
418529
const DWARFDie &DIE) {
@@ -2297,8 +2408,12 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
22972408

22982409
// Create a map of stmt sequence offsets to original row indices.
22992410
DenseMap<uint64_t, unsigned> SeqOffToOrigRow;
2300-
for (const DWARFDebugLine::Sequence &Seq : LT->Sequences)
2301-
SeqOffToOrigRow[Seq.StmtSeqOffset] = Seq.FirstRowIndex;
2411+
// The DWARF parser's discovery of sequences can be incomplete. To
2412+
// ensure all DW_AT_LLVM_stmt_sequence attributes can be patched, we
2413+
// build a map from both the parser's results and a manual
2414+
// reconstruction.
2415+
if (!LT->Rows.empty())
2416+
constructSeqOffsettoOrigRowMapping(Unit, *LT, SeqOffToOrigRow);
23022417

23032418
// Create a map of original row indices to new row indices.
23042419
DenseMap<size_t, size_t> OrigRowToNewRow;

0 commit comments

Comments
 (0)