@@ -77,7 +77,8 @@ void GDBIndex::updateGdbIndexSection(
77
77
exit (1 );
78
78
}
79
79
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 ();
81
82
Index < Units; ++Index) {
82
83
const DWARFUnit *CU = BC.DwCtx ->getUnitAtIndex (Index);
83
84
if (SkipTypeUnits && CU->isTypeUnit ())
@@ -90,7 +91,7 @@ void GDBIndex::updateGdbIndexSection(
90
91
}
91
92
92
93
OriginalOffsets.insert (Offset);
93
- OffsetToIndexMap[Offset] = Index ;
94
+ OffsetToIndexMap[Offset] = PresentUnitsIndex++ ;
94
95
}
95
96
96
97
// Ignore old address table.
@@ -99,10 +100,19 @@ void GDBIndex::updateGdbIndexSection(
99
100
Data += SymbolTableOffset - CUTypesOffset;
100
101
101
102
// Calculate the size of the new address table.
103
+ const auto IsValidAddressRange = [](const DebugAddressRange &Range) {
104
+ return Range.HighPC > Range.LowPC ;
105
+ };
106
+
102
107
uint32_t NewAddressTableSize = 0 ;
103
108
for (const auto &CURangesPair : ARangesSectionWriter.getCUAddressRanges ()) {
104
109
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 ;
106
116
}
107
117
108
118
// Difference between old and new table (and section) sizes.
@@ -125,16 +135,52 @@ void GDBIndex::updateGdbIndexSection(
125
135
126
136
using MapEntry = std::pair<uint32_t , CUInfo>;
127
137
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 ());
128
146
// Need to sort since we write out all of TUs in .debug_info before CUs.
129
147
std::sort (CUVector.begin (), CUVector.end (),
130
148
[](const MapEntry &E1 , const MapEntry &E2 ) -> bool {
131
149
return E1 .second .Offset < E2 .second .Offset ;
132
150
});
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
+
133
182
// Writing out CU List <Offset, Size>
134
183
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 ;
138
184
write64le (Buffer, CUInfo.second .Offset );
139
185
// Length encoded in CU doesn't contain first 4 bytes that encode length.
140
186
write64le (Buffer + 8 , CUInfo.second .Length + 4 );
@@ -160,13 +206,19 @@ void GDBIndex::updateGdbIndexSection(
160
206
// Generate new address table.
161
207
for (const std::pair<const uint64_t , DebugAddressRangesVector> &CURangesPair :
162
208
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);
164
211
const DebugAddressRangesVector &Ranges = CURangesPair.second ;
165
212
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
+ }
170
222
}
171
223
}
172
224
@@ -178,6 +230,56 @@ void GDBIndex::updateGdbIndexSection(
178
230
// Copy over the rest of the original data.
179
231
memcpy (Buffer, Data, TrailingSize);
180
232
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
+
181
283
// Register the new section.
182
284
BC.registerOrUpdateNoteSection (" .gdb_index" , NewGdbIndexContents,
183
285
NewGdbIndexSize);
0 commit comments