//===- llvm/unittest/DWARFLinkerParallel/DWARFLinkerTest.cpp --------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/ADT/DenseMap.h" #include "llvm/DWARFLinker/Utils.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "gtest/gtest.h" using namespace llvm; using namespace dwarf_linker; #define DEVELOPER_DIR "/Applications/Xcode.app/Contents/Developer" namespace { TEST(DWARFLinker, PathTest) { EXPECT_EQ(guessDeveloperDir("/Foo"), ""); EXPECT_EQ(guessDeveloperDir("Foo.sdk"), ""); EXPECT_EQ(guessDeveloperDir( DEVELOPER_DIR "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk"), DEVELOPER_DIR); EXPECT_EQ(guessDeveloperDir(DEVELOPER_DIR "/SDKs/MacOSX.sdk"), DEVELOPER_DIR); } // Helpers for building DWARFDebugLine::LineTable fixtures. Only the fields // that buildStmtSeqOffsetToFirstRowIndex inspects are populated; everything // else defaults to Row's/Sequence's own defaults. namespace { void addRows(DWARFDebugLine::LineTable <, unsigned Count, ArrayRef EndSequenceIndices) { for (unsigned I = 0; I < Count; ++I) LT.Rows.emplace_back(); for (unsigned I : EndSequenceIndices) LT.Rows[I].EndSequence = 1; } void addParsedSequence(DWARFDebugLine::LineTable <, uint64_t StmtSeqOffset, unsigned FirstRowIndex) { DWARFDebugLine::Sequence S; S.StmtSeqOffset = StmtSeqOffset; S.FirstRowIndex = FirstRowIndex; LT.Sequences.push_back(S); } } // namespace TEST(DWARFLinker, BuildStmtSeqOffsetToFirstRowIndex_ParserOnly) { // Single parser-registered sequence covering rows [0..3). The attribute // at offset 0x10 resolves straight from LT.Sequences. DWARFDebugLine::LineTable LT; addRows(LT, /*Count=*/3, /*EndSequenceIndices=*/{2}); addParsedSequence(LT, /*StmtSeqOffset=*/0x10, /*FirstRowIndex=*/0); DenseMap Result; buildStmtSeqOffsetToFirstRowIndex(LT, /*SortedStmtSeqOffsets=*/{0x10}, Result); EXPECT_EQ(Result.lookup(0x10), 0u); EXPECT_EQ(Result.size(), 1u); } TEST(DWARFLinker, BuildStmtSeqOffsetToFirstRowIndex_ParserMissFallback) { // Two real sequences in the table (rows [0..3) and [3..5)), but the // parser only registered the second one. The fallback must recover // the first from the end_sequence boundary at row 2. DWARFDebugLine::LineTable LT; addRows(LT, /*Count=*/5, /*EndSequenceIndices=*/{2, 4}); addParsedSequence(LT, /*StmtSeqOffset=*/0x20, /*FirstRowIndex=*/3); DenseMap Result; buildStmtSeqOffsetToFirstRowIndex(LT, /*SortedStmtSeqOffsets=*/{0x10, 0x20}, Result); EXPECT_EQ(Result.lookup(0x10), 0u); // recovered from row boundaries EXPECT_EQ(Result.lookup(0x20), 3u); // parser-registered ground truth } TEST(DWARFLinker, BuildStmtSeqOffsetToFirstRowIndex_RealignIgnoresStale) { // SeqStartRows is seeded with row 0 and then every row immediately // following an end_sequence marker. For 16 rows with end_sequence at // {2, 4, 8, 10, 14} that's {0, 3, 5, 9, 11, 15}. // // StmtAttrs {0x04, 0x08, 0x10, 0x12, 0x14} // SeqStartRows {0, 3, 5, 9, 11, 15} // Parser {0x08 -> 9, 0x14 -> 15} // // Walk: // anchor (0x08, 9): (0x04, 0) < anchor -> pair 0x04 -> 0 // 0x08 not < 0x08 -> exit while // drop seq-starts < 9 -> {9, 11, 15} // ground truth -> 0x08 -> 9 // anchor (0x14, 15): (0x10, 11) < anchor -> pair 0x10 -> 11 // (0x12, 15) not < 15 -> exit while // drop stmt-attrs<0x14-> {0x14} // ground truth -> 0x14 -> 15 // // 0x12 is dropped because no safe row to pair it with remains. DWARFDebugLine::LineTable LT; addRows(LT, /*Count=*/16, /*EndSequenceIndices=*/{2, 4, 8, 10, 14}); addParsedSequence(LT, 0x08, 9); addParsedSequence(LT, 0x14, 15); DenseMap Result; buildStmtSeqOffsetToFirstRowIndex(LT, {0x04, 0x08, 0x10, 0x12, 0x14}, Result); EXPECT_EQ(Result.lookup(0x04), 0u); EXPECT_EQ(Result.lookup(0x08), 9u); EXPECT_EQ(Result.lookup(0x10), 11u); EXPECT_FALSE(Result.contains(0x12)); EXPECT_EQ(Result.lookup(0x14), 15u); } TEST(DWARFLinker, BuildStmtSeqOffsetToFirstRowIndex_EmptyRows) { // When LT.Rows is empty the builder just copies the parser-registered // sequences over and returns — no fallback work possible. DWARFDebugLine::LineTable LT; addParsedSequence(LT, 0x10, 0); addParsedSequence(LT, 0x20, 42); DenseMap Result; buildStmtSeqOffsetToFirstRowIndex(LT, {0x10, 0x20, 0x30}, Result); EXPECT_EQ(Result.lookup(0x10), 0u); EXPECT_EQ(Result.lookup(0x20), 42u); EXPECT_FALSE(Result.contains(0x30)); // no way to recover without rows } TEST(DWARFLinker, BuildStmtSeqOffsetToFirstRowIndex_NoAttributes) { // No stmt-seq attributes to resolve: the builder still seeds the map // from parser-registered sequences (harmless, helps shared callers). DWARFDebugLine::LineTable LT; addRows(LT, /*Count=*/3, /*EndSequenceIndices=*/{2}); addParsedSequence(LT, 0x10, 0); DenseMap Result; buildStmtSeqOffsetToFirstRowIndex(LT, /*SortedStmtSeqOffsets=*/{}, Result); EXPECT_EQ(Result.lookup(0x10), 0u); EXPECT_EQ(Result.size(), 1u); } } // anonymous namespace