@@ -77,7 +77,8 @@ void GDBIndex::updateGdbIndexSection(
7777 exit (1 );
7878 }
7979 DenseSet<uint64_t > OriginalOffsets;
80- for (unsigned Index = 0 , Units = BC.DwCtx ->getNumCompileUnits ();
80+ for (unsigned Index = 0 , PresentUnitsIndex = 0 ,
81+ Units = BC.DwCtx ->getNumCompileUnits ();
8182 Index < Units; ++Index) {
8283 const DWARFUnit *CU = BC.DwCtx ->getUnitAtIndex (Index);
8384 if (SkipTypeUnits && CU->isTypeUnit ())
@@ -90,7 +91,7 @@ void GDBIndex::updateGdbIndexSection(
9091 }
9192
9293 OriginalOffsets.insert (Offset);
93- OffsetToIndexMap[Offset] = Index ;
94+ OffsetToIndexMap[Offset] = PresentUnitsIndex++ ;
9495 }
9596
9697 // Ignore old address table.
@@ -99,10 +100,19 @@ void GDBIndex::updateGdbIndexSection(
99100 Data += SymbolTableOffset - CUTypesOffset;
100101
101102 // Calculate the size of the new address table.
103+ const auto IsValidAddressRange = [](const DebugAddressRange &Range) {
104+ return Range.HighPC > Range.LowPC ;
105+ };
106+
102107 uint32_t NewAddressTableSize = 0 ;
103108 for (const auto &CURangesPair : ARangesSectionWriter.getCUAddressRanges ()) {
104109 const SmallVector<DebugAddressRange, 2 > &Ranges = CURangesPair.second ;
105- NewAddressTableSize += Ranges.size () * 20 ;
110+ NewAddressTableSize +=
111+ llvm::count_if (Ranges,
112+ [&IsValidAddressRange](const DebugAddressRange &Range) {
113+ return IsValidAddressRange (Range);
114+ }) *
115+ 20 ;
106116 }
107117
108118 // Difference between old and new table (and section) sizes.
@@ -125,16 +135,52 @@ void GDBIndex::updateGdbIndexSection(
125135
126136 using MapEntry = std::pair<uint32_t , CUInfo>;
127137 std::vector<MapEntry> CUVector (CUMap.begin (), CUMap.end ());
138+ // Remove the CUs we won't emit anyway.
139+ CUVector.erase (std::remove_if (CUVector.begin (), CUVector.end (),
140+ [&OriginalOffsets](const MapEntry &It) {
141+ // Skipping TU for DWARF5 when they are not
142+ // included in CU list.
143+ return OriginalOffsets.count (It.first ) == 0 ;
144+ }),
145+ CUVector.end ());
128146 // Need to sort since we write out all of TUs in .debug_info before CUs.
129147 std::sort (CUVector.begin (), CUVector.end (),
130148 [](const MapEntry &E1 , const MapEntry &E2 ) -> bool {
131149 return E1 .second .Offset < E2 .second .Offset ;
132150 });
151+ // Create the original CU index -> updated CU index mapping,
152+ // as the sort above could've changed the order and we have to update
153+ // indices correspondingly in address map and constant pool.
154+ std::unordered_map<uint32_t , uint32_t > OriginalCUIndexToUpdatedCUIndexMap;
155+ OriginalCUIndexToUpdatedCUIndexMap.reserve (CUVector.size ());
156+ for (uint32_t I = 0 ; I < CUVector.size (); ++I) {
157+ OriginalCUIndexToUpdatedCUIndexMap[OffsetToIndexMap.at (CUVector[I].first )] =
158+ I;
159+ }
160+ const auto RemapCUIndex = [&OriginalCUIndexToUpdatedCUIndexMap,
161+ CUVectorSize = CUVector.size (),
162+ TUVectorSize = getGDBIndexTUEntryVector ().size ()](
163+ uint32_t OriginalIndex) {
164+ if (OriginalIndex >= CUVectorSize) {
165+ if (OriginalIndex >= CUVectorSize + TUVectorSize) {
166+ errs () << " BOLT-ERROR: .gdb_index unknown CU index\n " ;
167+ exit (1 );
168+ }
169+ // The index is into TU CU List, which we don't reorder, so return as is.
170+ return OriginalIndex;
171+ }
172+
173+ const auto It = OriginalCUIndexToUpdatedCUIndexMap.find (OriginalIndex);
174+ if (It == OriginalCUIndexToUpdatedCUIndexMap.end ()) {
175+ errs () << " BOLT-ERROR: .gdb_index unknown CU index\n " ;
176+ exit (1 );
177+ }
178+
179+ return It->second ;
180+ };
181+
133182 // Writing out CU List <Offset, Size>
134183 for (auto &CUInfo : CUVector) {
135- // Skipping TU for DWARF5 when they are not included in CU list.
136- if (!OriginalOffsets.count (CUInfo.first ))
137- continue ;
138184 write64le (Buffer, CUInfo.second .Offset );
139185 // Length encoded in CU doesn't contain first 4 bytes that encode length.
140186 write64le (Buffer + 8 , CUInfo.second .Length + 4 );
@@ -160,13 +206,19 @@ void GDBIndex::updateGdbIndexSection(
160206 // Generate new address table.
161207 for (const std::pair<const uint64_t , DebugAddressRangesVector> &CURangesPair :
162208 ARangesSectionWriter.getCUAddressRanges ()) {
163- const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first ];
209+ const uint32_t OriginalCUIndex = OffsetToIndexMap[CURangesPair.first ];
210+ const uint32_t UpdatedCUIndex = RemapCUIndex (OriginalCUIndex);
164211 const DebugAddressRangesVector &Ranges = CURangesPair.second ;
165212 for (const DebugAddressRange &Range : Ranges) {
166- write64le (Buffer, Range.LowPC );
167- write64le (Buffer + 8 , Range.HighPC );
168- write32le (Buffer + 16 , CUIndex);
169- Buffer += 20 ;
213+ // Don't emit ranges that break gdb,
214+ // https://sourceware.org/bugzilla/show_bug.cgi?id=33247.
215+ // We've seen [0, 0) ranges here, for instance.
216+ if (IsValidAddressRange (Range)) {
217+ write64le (Buffer, Range.LowPC );
218+ write64le (Buffer + 8 , Range.HighPC );
219+ write32le (Buffer + 16 , UpdatedCUIndex);
220+ Buffer += 20 ;
221+ }
170222 }
171223 }
172224
@@ -178,6 +230,56 @@ void GDBIndex::updateGdbIndexSection(
178230 // Copy over the rest of the original data.
179231 memcpy (Buffer, Data, TrailingSize);
180232
233+ // Fixup CU-indices in constant pool.
234+ const char *const OriginalConstantPoolData =
235+ GdbIndexContents.data () + ConstantPoolOffset;
236+ uint8_t *const UpdatedConstantPoolData =
237+ NewGdbIndexContents + ConstantPoolOffset + Delta;
238+
239+ const char *OriginalSymbolTableData =
240+ GdbIndexContents.data () + SymbolTableOffset;
241+ std::set<uint32_t > CUVectorOffsets;
242+ // Parse the symbol map and extract constant pool CU offsets from it.
243+ while (OriginalSymbolTableData < OriginalConstantPoolData) {
244+ const uint32_t NameOffset = read32le (OriginalSymbolTableData);
245+ const uint32_t CUVectorOffset = read32le (OriginalSymbolTableData + 4 );
246+ OriginalSymbolTableData += 8 ;
247+
248+ // Iff both are zero, then the slot is considered empty in the hash-map.
249+ if (NameOffset || CUVectorOffset) {
250+ CUVectorOffsets.insert (CUVectorOffset);
251+ }
252+ }
253+
254+ // Update the CU-indicies in the constant pool
255+ for (const auto CUVectorOffset : CUVectorOffsets) {
256+ const char *CurrentOriginalConstantPoolData =
257+ OriginalConstantPoolData + CUVectorOffset;
258+ uint8_t *CurrentUpdatedConstantPoolData =
259+ UpdatedConstantPoolData + CUVectorOffset;
260+
261+ const uint32_t Num = read32le (CurrentOriginalConstantPoolData);
262+ CurrentOriginalConstantPoolData += 4 ;
263+ CurrentUpdatedConstantPoolData += 4 ;
264+
265+ for (uint32_t J = 0 ; J < Num; ++J) {
266+ const uint32_t OriginalCUIndexAndAttributes =
267+ read32le (CurrentOriginalConstantPoolData);
268+ CurrentOriginalConstantPoolData += 4 ;
269+
270+ // We only care for the index, which is the lowest 24 bits, other bits are
271+ // left as is.
272+ const uint32_t OriginalCUIndex =
273+ OriginalCUIndexAndAttributes & ((1 << 24 ) - 1 );
274+ const uint32_t Attributes = OriginalCUIndexAndAttributes >> 24 ;
275+ const uint32_t UpdatedCUIndexAndAttributes =
276+ RemapCUIndex (OriginalCUIndex) | (Attributes << 24 );
277+
278+ write32le (CurrentUpdatedConstantPoolData, UpdatedCUIndexAndAttributes);
279+ CurrentUpdatedConstantPoolData += 4 ;
280+ }
281+ }
282+
181283 // Register the new section.
182284 BC.registerOrUpdateNoteSection (" .gdb_index" , NewGdbIndexContents,
183285 NewGdbIndexSize);
0 commit comments