Skip to content

Commit f9c446a

Browse files
committed
[DWARFLinker] Fix matching logic to remove type 1 missing offsets and duplicated offsets
1 parent 9ad7ede commit f9c446a

File tree

2 files changed

+599
-311
lines changed

2 files changed

+599
-311
lines changed

llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "llvm/Support/LEB128.h"
3737
#include "llvm/Support/Path.h"
3838
#include "llvm/Support/ThreadPool.h"
39+
#include <iostream>
3940
#include <vector>
4041

4142
namespace llvm {
@@ -2297,8 +2298,135 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
22972298

22982299
// Create a map of stmt sequence offsets to original row indices.
22992300
DenseMap<uint64_t, unsigned> SeqOffToOrigRow;
2300-
for (const DWARFDebugLine::Sequence &Seq : LT->Sequences)
2301-
SeqOffToOrigRow[Seq.StmtSeqOffset] = Seq.FirstRowIndex;
2301+
DenseMap<uint64_t, unsigned> LineTableMapping;
2302+
// The DWARF parser's discovery of sequences can be incomplete. To
2303+
// ensure all DW_AT_LLVM_stmt_sequence attributes can be patched, we
2304+
// build a map from both the parser's results and a manual
2305+
// reconstruction.
2306+
if (!LT->Rows.empty()) {
2307+
// First, trust the sequences that the DWARF parser did identify.
2308+
for (const DWARFDebugLine::Sequence &Seq : LT->Sequences) {
2309+
LineTableMapping[Seq.StmtSeqOffset] = Seq.FirstRowIndex;
2310+
}
2311+
2312+
// Second, manually find sequence boundaries and match them to the
2313+
// sorted attributes to handle sequences the parser might have missed.
2314+
auto StmtAttrs = Unit.getStmtSeqListAttributes();
2315+
llvm::sort(StmtAttrs,
2316+
[](const PatchLocation &A, const PatchLocation &B) {
2317+
return A.get() < B.get();
2318+
});
2319+
2320+
std::vector<size_t> SeqStartRows;
2321+
SeqStartRows.push_back(0);
2322+
for (size_t i = 0; i < LT->Rows.size() - 1; ++i)
2323+
if (LT->Rows[i].EndSequence)
2324+
SeqStartRows.push_back(i + 1);
2325+
2326+
// While SeqOffToOrigRow parsed from CU could be the ground truth,
2327+
// e.g.
2328+
//
2329+
// SeqOff Row
2330+
// 0x08 9
2331+
// 0x14 15
2332+
//
2333+
// The StmtAttrs and SeqStartRows may not match perfectly, e.g.
2334+
//
2335+
// StmtAttrs SeqStartRows
2336+
// 0x04 3
2337+
// 0x08 5
2338+
// 0x10 9
2339+
// 0x12 11
2340+
// 0x14 15
2341+
//
2342+
// In this case, we don't want to assign 5 to 0x08, since we know 0x08
2343+
// maps to 9. If we do a dummy 1:1 mapping 0x10 will be mapped to 9
2344+
// which is incorrect. The expected behavior is ignore 5, realign the
2345+
// table based on the result from the line table:
2346+
//
2347+
// StmtAttrs SeqStartRows
2348+
// 0x04 3
2349+
// -- 5
2350+
// 0x08 9 <- LineTableMapping ground truth
2351+
// 0x10 11
2352+
// 0x12 --
2353+
// 0x14 15 <- LineTableMapping ground truth
2354+
2355+
// Dummy last element to make sure StmtAttrIdx and SeqStartIdx always
2356+
// run out first. Can't directly use TombstoneKey/TombstoneVal, that's
2357+
// preserved.
2358+
constexpr size_t DummyKey = UINT64_MAX - 2;
2359+
constexpr unsigned DummyVal = UINT32_MAX - 2;
2360+
LineTableMapping[DummyKey] = DummyVal;
2361+
SmallVector<uint64_t> SortedLineTableKeys(LineTableMapping.keys());
2362+
llvm::sort(SortedLineTableKeys);
2363+
for (auto Key : SortedLineTableKeys) {
2364+
std::cout << std::hex << Key << " " << LineTableMapping[Key]
2365+
<< "\n";
2366+
}
2367+
for (auto StmtAttr : StmtAttrs) {
2368+
std::cout << std::hex << StmtAttr.get() << "\n";
2369+
}
2370+
for (auto Row : SeqStartRows) {
2371+
std::cout << std::hex << Row << "\n";
2372+
}
2373+
2374+
size_t StmtAttrIdx = 0, SeqStartIdx = 0;
2375+
size_t NextSeqOff = 0;
2376+
unsigned NextRow = 0;
2377+
2378+
auto StmtIdxValidAndSmallerThanNext = [&]() {
2379+
return StmtAttrIdx < StmtAttrs.size() &&
2380+
StmtAttrs[StmtAttrIdx].get() < NextSeqOff;
2381+
};
2382+
2383+
auto SeqStartIdxValidAndSmallerThanNext = [&]() {
2384+
return SeqStartIdx < SeqStartRows.size() &&
2385+
SeqStartRows[SeqStartIdx] < NextRow;
2386+
};
2387+
for (size_t i = 0; i < SortedLineTableKeys.size(); ++i) {
2388+
NextSeqOff = SortedLineTableKeys[i];
2389+
NextRow = LineTableMapping[NextSeqOff];
2390+
// If both StmtAttrs and SeqStartRows points to value not in
2391+
// the LineTableMapping yet, we do a dummy one to one mapping and
2392+
// move the pointer.
2393+
while (StmtIdxValidAndSmallerThanNext() &&
2394+
SeqStartIdxValidAndSmallerThanNext()) {
2395+
SeqOffToOrigRow[StmtAttrs[StmtAttrIdx].get()] =
2396+
SeqStartRows[SeqStartIdx];
2397+
++StmtAttrIdx;
2398+
++SeqStartIdx;
2399+
}
2400+
// One of the pointer points to the value at or past Next in the
2401+
// LineTableMapping, We move the pointer to re-align with the
2402+
// LineTableMapping
2403+
while (StmtIdxValidAndSmallerThanNext()) {
2404+
++StmtAttrIdx;
2405+
}
2406+
while (SeqStartIdxValidAndSmallerThanNext()) {
2407+
++SeqStartIdx;
2408+
}
2409+
// Use the LineTableMapping's result as the ground truth and move
2410+
// on.
2411+
SeqOffToOrigRow[NextSeqOff] = NextRow;
2412+
}
2413+
// size_t i = 0, j = 0;
2414+
// while (i < StmtAttrs.size() && j < SeqStartRows.size()) {
2415+
// auto It = SeqOffToOrigRow.find(StmtAttrs[i].get());
2416+
// // The match is not set, use current result.
2417+
// if (It == SeqOffToOrigRow.end()) {
2418+
// SeqOffToOrigRow.try_emplace(StmtAttrs[i].get(),
2419+
// SeqStartRows[j]);
2420+
// } else {
2421+
// while (It->second != SeqStartRows[j] && j <
2422+
// SeqStartRows.size()) {
2423+
// ++j;
2424+
// }
2425+
// }
2426+
// ++i;
2427+
// ++j;
2428+
// }
2429+
}
23022430

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

0 commit comments

Comments
 (0)