@@ -413,6 +413,116 @@ static bool isTlsAddressCode(uint8_t DW_OP_Code) {
413
413
DW_OP_Code == dwarf::DW_OP_GNU_push_tls_address;
414
414
}
415
415
416
+ static void constructSeqOffsettoOrigRowMapping (
417
+ CompileUnit &Unit, const DWARFDebugLine::LineTable <,
418
+ DenseMap<size_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<size_t > 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 size_t DummyKey = UINT64_MAX;
475
+ constexpr unsigned DummyVal = UINT32_MAX;
476
+ LineTableMapping[DummyKey] = DummyVal;
477
+
478
+ for (auto [NextSeqOff, NextRow] : LineTableMapping) {
479
+ auto StmtAttrSmallerThanNext = [NextSeqOff](const PatchLocation &SA) {
480
+ return SA.get () < NextSeqOff;
481
+ };
482
+ auto SeqStartSmallerThanNext = [NextRow](const size_t &Row) {
483
+ return Row < NextRow;
484
+ };
485
+
486
+ // If both StmtAttrs and SeqStartRows points to value not in
487
+ // the LineTableMapping yet, we do a dummy one to one mapping and
488
+ // move the pointer.
489
+ while (!StmtAttrsRef.empty () && !SeqStartRowsRef.empty () &&
490
+ StmtAttrSmallerThanNext (StmtAttrsRef.front ()) &&
491
+ SeqStartSmallerThanNext (SeqStartRowsRef.front ())) {
492
+ SeqOffToOrigRow[StmtAttrsRef.consume_front ().get ()] =
493
+ SeqStartRowsRef.consume_front ();
494
+ }
495
+ // One of the pointer points to the value at or past Next in the
496
+ // LineTableMapping, We move the pointer to re-align with the
497
+ // LineTableMapping
498
+ StmtAttrsRef = StmtAttrsRef.drop_while (StmtAttrSmallerThanNext);
499
+ SeqStartRowsRef = SeqStartRowsRef.drop_while (SeqStartSmallerThanNext);
500
+ // Use the LineTableMapping's result as the ground truth and move
501
+ // on.
502
+ if (NextSeqOff != DummyKey) {
503
+ SeqOffToOrigRow[NextSeqOff] = NextRow;
504
+ }
505
+ // Move the pointers if they are pointed at Next.
506
+ // It is possible that they point to later entries in LineTableMapping.
507
+ // Therefore we only increment the pointers after we validate they are
508
+ // pointing to the `Next` entry. e.g.
509
+ //
510
+ // LineTableMapping
511
+ // SeqOff Row
512
+ // 0x08 9 <- NextSeqOff/NextRow
513
+ // 0x14 15
514
+ //
515
+ // StmtAttrs SeqStartRows
516
+ // 0x14 13 <- StmtAttrsRef.front() / SeqStartRowsRef.front()
517
+ // 0x16 15
518
+ // -- 17
519
+ if (!StmtAttrsRef.empty () && StmtAttrsRef.front ().get () == NextSeqOff)
520
+ StmtAttrsRef.consume_front ();
521
+ if (!SeqStartRowsRef.empty () && SeqStartRowsRef.front () == NextRow)
522
+ SeqStartRowsRef.consume_front ();
523
+ }
524
+ }
525
+
416
526
std::pair<bool , std::optional<int64_t >>
417
527
DWARFLinker::getVariableRelocAdjustment (AddressesMap &RelocMgr,
418
528
const DWARFDie &DIE) {
@@ -2297,8 +2407,12 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
2297
2407
2298
2408
// Create a map of stmt sequence offsets to original row indices.
2299
2409
DenseMap<uint64_t , unsigned > SeqOffToOrigRow;
2300
- for (const DWARFDebugLine::Sequence &Seq : LT->Sequences )
2301
- SeqOffToOrigRow[Seq.StmtSeqOffset ] = Seq.FirstRowIndex ;
2410
+ // The DWARF parser's discovery of sequences can be incomplete. To
2411
+ // ensure all DW_AT_LLVM_stmt_sequence attributes can be patched, we
2412
+ // build a map from both the parser's results and a manual
2413
+ // reconstruction.
2414
+ if (!LT->Rows .empty ())
2415
+ constructSeqOffsettoOrigRowMapping (Unit, *LT, SeqOffToOrigRow);
2302
2416
2303
2417
// Create a map of original row indices to new row indices.
2304
2418
DenseMap<size_t , size_t > OrigRowToNewRow;
0 commit comments