@@ -1447,6 +1447,18 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
14471447 ->sizeOf (Unit.getOrigUnit ().getFormParams ());
14481448 }
14491449
1450+ if (AttrSpec.Attr == dwarf::DW_AT_LLVM_stmt_sequence) {
1451+ // If needed, we'll patch this sec_offset later with the correct offset.
1452+ auto Patch = Die.addValue (DIEAlloc, dwarf::Attribute (AttrSpec.Attr ),
1453+ dwarf::DW_FORM_sec_offset,
1454+ DIEInteger (*Val.getAsSectionOffset ()));
1455+
1456+ // Record this patch location so that it can be fixed up later.
1457+ Unit.noteStmtSeqListAttribute (Patch);
1458+
1459+ return Unit.getOrigUnit ().getFormParams ().getDwarfOffsetByteSize ();
1460+ }
1461+
14501462 if (LLVM_UNLIKELY (Linker.Options .Update )) {
14511463 if (auto OptionalValue = Val.getAsUnsignedConstant ())
14521464 Value = *OptionalValue;
@@ -2081,29 +2093,43 @@ void DWARFLinker::DIECloner::emitDebugAddrSection(
20812093 Emitter->emitDwarfDebugAddrsFooter (Unit, EndLabel);
20822094}
20832095
2096+ // / A helper struct to help keep track of the association between the input and
2097+ // / output rows during line table rewriting. This is used to patch
2098+ // / DW_AT_LLVM_stmt_sequence attributes, which reference a particular line table
2099+ // / row.
2100+ struct TrackedRow {
2101+ DWARFDebugLine::Row Row;
2102+ size_t OriginalRowIndex;
2103+ bool isStartSeqInOutput;
2104+ };
2105+
20842106// / Insert the new line info sequence \p Seq into the current
20852107// / set of already linked line info \p Rows.
2086- static void insertLineSequence (std::vector<DWARFDebugLine::Row > &Seq,
2087- std::vector<DWARFDebugLine::Row > &Rows) {
2108+ static void insertLineSequence (std::vector<TrackedRow > &Seq,
2109+ std::vector<TrackedRow > &Rows) {
20882110 if (Seq.empty ())
20892111 return ;
20902112
2091- if (!Rows.empty () && Rows.back ().Address < Seq.front ().Address ) {
2113+ // Mark the first row in Seq to indicate it is the start of a sequence
2114+ // in the output line table.
2115+ Seq.front ().isStartSeqInOutput = true ;
2116+
2117+ if (!Rows.empty () && Rows.back ().Row .Address < Seq.front ().Row .Address ) {
20922118 llvm::append_range (Rows, Seq);
20932119 Seq.clear ();
20942120 return ;
20952121 }
20962122
2097- object::SectionedAddress Front = Seq.front ().Address ;
2123+ object::SectionedAddress Front = Seq.front ().Row . Address ;
20982124 auto InsertPoint = partition_point (
2099- Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });
2125+ Rows, [=](const TrackedRow &O) { return O. Row .Address < Front; });
21002126
21012127 // FIXME: this only removes the unneeded end_sequence if the
21022128 // sequences have been inserted in order. Using a global sort like
2103- // described in generateLineTableForUnit() and delaying the end_sequene
2129+ // described in generateLineTableForUnit() and delaying the end_sequence
21042130 // elimination to emitLineTableForUnit() we can get rid of all of them.
2105- if (InsertPoint != Rows.end () && InsertPoint->Address == Front &&
2106- InsertPoint->EndSequence ) {
2131+ if (InsertPoint != Rows.end () && InsertPoint->Row . Address == Front &&
2132+ InsertPoint->Row . EndSequence ) {
21072133 *InsertPoint = Seq.front ();
21082134 Rows.insert (InsertPoint + 1 , Seq.begin () + 1 , Seq.end ());
21092135 } else {
@@ -2171,14 +2197,24 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
21712197 LineTable.Rows .clear ();
21722198
21732199 LineTable.Sequences = LT->Sequences ;
2200+
2201+ Emitter->emitLineTableForUnit (LineTable, Unit, DebugStrPool,
2202+ DebugLineStrPool);
21742203 } else {
2175- // This vector is the output line table.
2176- std::vector<DWARFDebugLine::Row> NewRows;
2177- NewRows.reserve (LT->Rows .size ());
2204+ // Create TrackedRow objects for all input rows.
2205+ std::vector<TrackedRow> AllTrackedRows;
2206+ AllTrackedRows.reserve (LT->Rows .size ());
2207+ for (size_t i = 0 ; i < LT->Rows .size (); i++)
2208+ AllTrackedRows.emplace_back (TrackedRow{LT->Rows [i], i, false });
2209+
2210+ // This vector is the output line table (still in TrackedRow form).
2211+ std::vector<TrackedRow> NewRows;
2212+ NewRows.reserve (AllTrackedRows.size ());
21782213
21792214 // Current sequence of rows being extracted, before being inserted
21802215 // in NewRows.
2181- std::vector<DWARFDebugLine::Row> Seq;
2216+ std::vector<TrackedRow> Seq;
2217+ Seq.reserve (AllTrackedRows.size ());
21822218
21832219 const auto &FunctionRanges = Unit.getFunctionRanges ();
21842220 std::optional<AddressRangeValuePair> CurrRange;
@@ -2194,27 +2230,30 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
21942230
21952231 // Iterate over the object file line info and extract the sequences
21962232 // that correspond to linked functions.
2197- for (DWARFDebugLine::Row Row : LT->Rows ) {
2233+ for (size_t i = 0 ; i < AllTrackedRows.size (); i++) {
2234+ TrackedRow TR = AllTrackedRows[i];
2235+
21982236 // Check whether we stepped out of the range. The range is
2199- // half-open, but consider accept the end address of the range if
2237+ // half-open, but consider accepting the end address of the range if
22002238 // it is marked as end_sequence in the input (because in that
22012239 // case, the relocation offset is accurate and that entry won't
22022240 // serve as the start of another function).
2203- if (!CurrRange || !CurrRange->Range .contains (Row.Address .Address )) {
2204- // We just stepped out of a known range. Insert a end_sequence
2241+ if (!CurrRange || !CurrRange->Range .contains (TR. Row .Address .Address )) {
2242+ // We just stepped out of a known range. Insert an end_sequence
22052243 // corresponding to the end of the range.
22062244 uint64_t StopAddress =
22072245 CurrRange ? CurrRange->Range .end () + CurrRange->Value : -1ULL ;
2208- CurrRange = FunctionRanges.getRangeThatContains (Row.Address .Address );
2246+ CurrRange =
2247+ FunctionRanges.getRangeThatContains (TR.Row .Address .Address );
22092248 if (StopAddress != -1ULL && !Seq.empty ()) {
22102249 // Insert end sequence row with the computed end address, but
22112250 // the same line as the previous one.
22122251 auto NextLine = Seq.back ();
2213- NextLine.Address .Address = StopAddress;
2214- NextLine.EndSequence = 1 ;
2215- NextLine.PrologueEnd = 0 ;
2216- NextLine.BasicBlock = 0 ;
2217- NextLine.EpilogueBegin = 0 ;
2252+ NextLine.Row . Address .Address = StopAddress;
2253+ NextLine.Row . EndSequence = 1 ;
2254+ NextLine.Row . PrologueEnd = 0 ;
2255+ NextLine.Row . BasicBlock = 0 ;
2256+ NextLine.Row . EpilogueBegin = 0 ;
22182257 Seq.push_back (NextLine);
22192258 insertLineSequence (Seq, NewRows);
22202259 }
@@ -2224,22 +2263,78 @@ void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) {
22242263 }
22252264
22262265 // Ignore empty sequences.
2227- if (Row.EndSequence && Seq.empty ())
2266+ if (TR. Row .EndSequence && Seq.empty ())
22282267 continue ;
22292268
22302269 // Relocate row address and add it to the current sequence.
2231- Row.Address .Address += CurrRange->Value ;
2232- Seq.emplace_back (Row );
2270+ TR. Row .Address .Address += CurrRange->Value ;
2271+ Seq.push_back (TR );
22332272
2234- if (Row.EndSequence )
2273+ if (TR. Row .EndSequence )
22352274 insertLineSequence (Seq, NewRows);
22362275 }
22372276
2238- LineTable.Rows = std::move (NewRows);
2277+ // Materialize the tracked rows into final DWARFDebugLine::Row objects.
2278+ LineTable.Rows .clear ();
2279+ LineTable.Rows .reserve (NewRows.size ());
2280+ for (auto &TR : NewRows)
2281+ LineTable.Rows .push_back (TR.Row );
2282+
2283+ // Use OutputRowOffsets to store the offsets of each line table row in the
2284+ // output .debug_line section.
2285+ std::vector<uint64_t > OutputRowOffsets;
2286+
2287+ // The unit might not have any DW_AT_LLVM_stmt_sequence attributes, so use
2288+ // hasStmtSeq to skip the patching logic.
2289+ bool hasStmtSeq = Unit.getStmtSeqListAttributes ().size () > 0 ;
2290+ Emitter->emitLineTableForUnit (LineTable, Unit, DebugStrPool,
2291+ DebugLineStrPool,
2292+ hasStmtSeq ? &OutputRowOffsets : nullptr );
2293+
2294+ if (hasStmtSeq) {
2295+ assert (OutputRowOffsets.size () == NewRows.size () &&
2296+ " OutputRowOffsets size mismatch" );
2297+
2298+ // Create a map of stmt sequence offsets to original row indices.
2299+ DenseMap<uint64_t , unsigned > SeqOffToOrigRow;
2300+ for (const DWARFDebugLine::Sequence &Seq : LT->Sequences )
2301+ SeqOffToOrigRow[Seq.StmtSeqOffset ] = Seq.FirstRowIndex ;
2302+
2303+ // Create a map of original row indices to new row indices.
2304+ DenseMap<size_t , size_t > OrigRowToNewRow;
2305+ for (size_t i = 0 ; i < NewRows.size (); ++i)
2306+ OrigRowToNewRow[NewRows[i].OriginalRowIndex ] = i;
2307+
2308+ // Patch DW_AT_LLVM_stmt_sequence attributes in the compile unit DIE
2309+ // with the correct offset into the .debug_line section.
2310+ for (const auto &StmtSeq : Unit.getStmtSeqListAttributes ()) {
2311+ uint64_t OrigStmtSeq = StmtSeq.get ();
2312+ // 1. Get the original row index from the stmt list offset.
2313+ auto OrigRowIter = SeqOffToOrigRow.find (OrigStmtSeq);
2314+ assert (OrigRowIter != SeqOffToOrigRow.end () &&
2315+ " Stmt list offset not found in sequence offsets map" );
2316+ size_t OrigRowIndex = OrigRowIter->second ;
2317+
2318+ // 2. Get the new row index from the original row index.
2319+ auto NewRowIter = OrigRowToNewRow.find (OrigRowIndex);
2320+ if (NewRowIter == OrigRowToNewRow.end ()) {
2321+ // If the original row index is not found in the map, update the
2322+ // stmt_sequence attribute to the 'invalid offset' magic value.
2323+ StmtSeq.set (UINT64_MAX);
2324+ continue ;
2325+ }
2326+
2327+ // 3. Get the offset of the new row in the output .debug_line section.
2328+ assert (NewRowIter->second < OutputRowOffsets.size () &&
2329+ " New row index out of bounds" );
2330+ uint64_t NewStmtSeqOffset = OutputRowOffsets[NewRowIter->second ];
2331+
2332+ // 4. Patch the stmt_list attribute with the new offset.
2333+ StmtSeq.set (NewStmtSeqOffset);
2334+ }
2335+ }
22392336 }
22402337
2241- Emitter->emitLineTableForUnit (LineTable, Unit, DebugStrPool,
2242- DebugLineStrPool);
22432338 } else
22442339 Linker.reportWarning (" Cann't load line table." , ObjFile);
22452340}
0 commit comments