Skip to content

Commit 49308c2

Browse files
Merge branch 'main' into fpclass
2 parents 7a83b07 + 80beefa commit 49308c2

File tree

685 files changed

+107456
-90036
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

685 files changed

+107456
-90036
lines changed

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,6 @@ class BinaryFunction {
192192

193193
mutable MCSymbol *FunctionConstantIslandLabel{nullptr};
194194
mutable MCSymbol *FunctionColdConstantIslandLabel{nullptr};
195-
196-
// Returns constant island alignment
197-
uint16_t getAlignment() const { return sizeof(uint64_t); }
198195
};
199196

200197
static constexpr uint64_t COUNT_NO_PROFILE =
@@ -2114,9 +2111,7 @@ class BinaryFunction {
21142111
return *std::prev(CodeIter) <= *DataIter;
21152112
}
21162113

2117-
uint16_t getConstantIslandAlignment() const {
2118-
return Islands ? Islands->getAlignment() : 1;
2119-
}
2114+
uint16_t getConstantIslandAlignment() const;
21202115

21212116
/// If there is a constant island in the range [StartOffset, EndOffset),
21222117
/// return its address.
@@ -2168,6 +2163,11 @@ class BinaryFunction {
21682163
return Islands && !Islands->DataOffsets.empty();
21692164
}
21702165

2166+
/// Return true if the whole function is a constant island.
2167+
bool isDataObject() const {
2168+
return Islands && Islands->CodeOffsets.size() == 0;
2169+
}
2170+
21712171
bool isStartOfConstantIsland(uint64_t Offset) const {
21722172
return hasConstantIsland() && Islands->DataOffsets.count(Offset);
21732173
}

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class raw_ostream;
5151

5252
namespace bolt {
5353
class BinaryBasicBlock;
54+
class BinaryContext;
5455
class BinaryFunction;
5556

5657
/// Different types of indirect branches encountered during disassembly.
@@ -530,10 +531,15 @@ class MCPlusBuilder {
530531
return 0;
531532
}
532533

534+
/// Create a helper function to increment counter for Instrumentation
535+
virtual void createInstrCounterIncrFunc(BinaryContext &BC) {
536+
llvm_unreachable("not implemented");
537+
}
538+
533539
/// Create increment contents of target by 1 for Instrumentation
534-
virtual InstructionListType
535-
createInstrIncMemory(const MCSymbol *Target, MCContext *Ctx, bool IsLeaf,
536-
unsigned CodePointerSize) const {
540+
virtual InstructionListType createInstrIncMemory(const MCSymbol *Target,
541+
MCContext *Ctx, bool IsLeaf,
542+
unsigned CodePointerSize) {
537543
llvm_unreachable("not implemented");
538544
return InstructionListType();
539545
}

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,33 @@ BinaryFunction::getBasicBlockContainingOffset(uint64_t Offset) {
284284
return (Offset < BB->getOffset() + BB->getOriginalSize()) ? BB : nullptr;
285285
}
286286

287+
uint16_t BinaryFunction::getConstantIslandAlignment() const {
288+
if (Islands == nullptr)
289+
return 1;
290+
291+
// For constant island inside a function, the default 8-byte alignment is
292+
// probably good enough.
293+
const uint16_t DefaultAlignment = sizeof(uint64_t);
294+
if (!isDataObject())
295+
return DefaultAlignment;
296+
297+
// If the constant island itself is a binary function, get its alignment
298+
// based on its size, original address, and its owning section's alignment.
299+
const uint64_t MaxAlignment =
300+
std::min(uint64_t(1) << llvm::countr_zero(getAddress()),
301+
OriginSection->getAlignment());
302+
const uint64_t MinAlignment =
303+
std::max((uint64_t)DefaultAlignment,
304+
uint64_t(1) << (63 - llvm::countl_zero(getSize())));
305+
uint64_t Alignment = std::min(MinAlignment, MaxAlignment);
306+
if (Alignment >> 16) {
307+
BC.errs() << "BOLT-ERROR: the constant island's alignment is too big: 0x"
308+
<< Twine::utohexstr(Alignment) << "\n";
309+
exit(1);
310+
}
311+
return (uint16_t)Alignment;
312+
}
313+
287314
void BinaryFunction::markUnreachableBlocks() {
288315
std::stack<BinaryBasicBlock *> Stack;
289316

bolt/lib/Core/GDBIndex.cpp

Lines changed: 113 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

bolt/lib/Passes/Instrumentation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,8 @@ void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) {
753753
createSimpleFunction("__bolt_fini_trampoline",
754754
BC.MIB->createReturnInstructionList(BC.Ctx.get()));
755755
}
756+
if (BC.isAArch64())
757+
BC.MIB->createInstrCounterIncrFunc(BC);
756758
}
757759
}
758760

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1312,7 +1312,9 @@ void RewriteInstance::discoverFileObjects() {
13121312

13131313
// Annotate functions with code/data markers in AArch64
13141314
for (auto &[Address, Type] : MarkerSymbols) {
1315-
auto *BF = BC->getBinaryFunctionContainingAddress(Address, true, true);
1315+
auto *BF = BC->getBinaryFunctionContainingAddress(Address,
1316+
/*CheckPastEnd*/ false,
1317+
/*UseMaxSize*/ true);
13161318

13171319
if (!BF) {
13181320
// Stray marker

0 commit comments

Comments
 (0)