Skip to content

Commit e471d65

Browse files
author
Jenkins
committed
merge main into amd-staging
Change-Id: If4828221f8fec260305cef07b5a181a32c61278a
2 parents 096ed0c + 7cff05a commit e471d65

File tree

174 files changed

+2860
-1255
lines changed

Some content is hidden

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

174 files changed

+2860
-1255
lines changed

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,13 +1412,14 @@ class MCPlusBuilder {
14121412
return false;
14131413
}
14141414

1415-
/// Modify a direct call instruction \p Inst with an indirect call taking
1416-
/// a destination from a memory location pointed by \p TargetLocation symbol.
1417-
virtual bool convertCallToIndirectCall(MCInst &Inst,
1418-
const MCSymbol *TargetLocation,
1419-
MCContext *Ctx) {
1415+
/// Creates an indirect call to the function within the \p DirectCall PLT
1416+
/// stub. The function's memory location is pointed by the \p TargetLocation
1417+
/// symbol.
1418+
virtual InstructionListType
1419+
createIndirectPltCall(const MCInst &DirectCall,
1420+
const MCSymbol *TargetLocation, MCContext *Ctx) {
14201421
llvm_unreachable("not implemented");
1421-
return false;
1422+
return {};
14221423
}
14231424

14241425
/// Morph an indirect call into a load where \p Reg holds the call target.

bolt/include/bolt/Rewrite/DWARFRewriter.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,6 @@ class DWARFRewriter {
150150
/// blocks) to be updated.
151151
void updateDebugAddressRanges();
152152

153-
/// Rewrite .gdb_index section if present.
154-
void updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs);
155-
156153
/// DWARFDie contains a pointer to a DIE and hence gets invalidated once the
157154
/// embedded DIE is destroyed. This wrapper class stores a DIE internally and
158155
/// could be cast to a DWARFDie that is valid even after the initial DIE is
@@ -194,14 +191,6 @@ class DWARFRewriter {
194191
DwoRangesBase[DWOId] = RangesBase;
195192
}
196193

197-
/// Adds an GDBIndexTUEntry if .gdb_index seciton exists.
198-
void addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry);
199-
200-
/// Returns all entries needed for Types CU list
201-
const GDBIndexTUEntryType &getGDBIndexTUEntryVector() const {
202-
return GDBIndexTUEntryVector;
203-
}
204-
205194
using OverriddenSectionsMap = std::unordered_map<DWARFSectionKind, StringRef>;
206195
/// Output .dwo files.
207196
void writeDWOFiles(DWARFUnit &, const OverriddenSectionsMap &,

bolt/lib/Passes/PLTCall.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ Error PLTCall::runOnFunctions(BinaryContext &BC) {
4848
return Error::success();
4949

5050
uint64_t NumCallsOptimized = 0;
51-
for (auto &It : BC.getBinaryFunctions()) {
52-
BinaryFunction &Function = It.second;
51+
for (auto &BFI : BC.getBinaryFunctions()) {
52+
BinaryFunction &Function = BFI.second;
5353
if (!shouldOptimize(Function))
5454
continue;
5555

@@ -61,18 +61,21 @@ Error PLTCall::runOnFunctions(BinaryContext &BC) {
6161
if (opts::PLT == OT_HOT && !BB.getKnownExecutionCount())
6262
continue;
6363

64-
for (MCInst &Instr : BB) {
65-
if (!BC.MIB->isCall(Instr))
64+
for (auto II = BB.begin(); II != BB.end(); II++) {
65+
if (!BC.MIB->isCall(*II))
6666
continue;
67-
const MCSymbol *CallSymbol = BC.MIB->getTargetSymbol(Instr);
67+
const MCSymbol *CallSymbol = BC.MIB->getTargetSymbol(*II);
6868
if (!CallSymbol)
6969
continue;
7070
const BinaryFunction *CalleeBF = BC.getFunctionForSymbol(CallSymbol);
7171
if (!CalleeBF || !CalleeBF->isPLTFunction())
7272
continue;
73-
BC.MIB->convertCallToIndirectCall(Instr, CalleeBF->getPLTSymbol(),
74-
BC.Ctx.get());
75-
BC.MIB->addAnnotation(Instr, "PLTCall", true);
73+
const InstructionListType NewCode = BC.MIB->createIndirectPltCall(
74+
*II, CalleeBF->getPLTSymbol(), BC.Ctx.get());
75+
II = BB.replaceInstruction(II, NewCode);
76+
assert(!NewCode.empty() && "PLT Call replacement must be non-empty");
77+
std::advance(II, NewCode.size() - 1);
78+
BC.MIB->addAnnotation(*II, "PLTCall", true);
7679
++NumCallsOptimized;
7780
}
7881
}

bolt/lib/Rewrite/DWARFRewriter.cpp

Lines changed: 0 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,177 +2060,6 @@ void DWARFRewriter::writeDWOFiles(
20602060
TempOut->keep();
20612061
}
20622062

2063-
void DWARFRewriter::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
2064-
std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
2065-
if (!BC.getGdbIndexSection())
2066-
return;
2067-
GDBIndexTUEntryVector.emplace_back(Entry);
2068-
}
2069-
2070-
void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs) {
2071-
if (!BC.getGdbIndexSection())
2072-
return;
2073-
2074-
// See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
2075-
// for .gdb_index section format.
2076-
2077-
StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
2078-
2079-
const char *Data = GdbIndexContents.data();
2080-
2081-
// Parse the header.
2082-
const uint32_t Version = read32le(Data);
2083-
if (Version != 7 && Version != 8) {
2084-
errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
2085-
exit(1);
2086-
}
2087-
2088-
// Some .gdb_index generators use file offsets while others use section
2089-
// offsets. Hence we can only rely on offsets relative to each other,
2090-
// and ignore their absolute values.
2091-
const uint32_t CUListOffset = read32le(Data + 4);
2092-
const uint32_t CUTypesOffset = read32le(Data + 8);
2093-
const uint32_t AddressTableOffset = read32le(Data + 12);
2094-
const uint32_t SymbolTableOffset = read32le(Data + 16);
2095-
const uint32_t ConstantPoolOffset = read32le(Data + 20);
2096-
Data += 24;
2097-
2098-
// Map CUs offsets to indices and verify existing index table.
2099-
std::map<uint32_t, uint32_t> OffsetToIndexMap;
2100-
const uint32_t CUListSize = CUTypesOffset - CUListOffset;
2101-
const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
2102-
const unsigned NUmCUsEncoded = CUListSize / 16;
2103-
unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
2104-
unsigned NumDWARF5TUs =
2105-
getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
2106-
bool SkipTypeUnits = false;
2107-
// For DWARF5 Types are in .debug_info.
2108-
// LLD doesn't generate Types CU List, and in CU list offset
2109-
// only includes CUs.
2110-
// GDB 11+ includes only CUs in CU list and generates Types
2111-
// list.
2112-
// GDB 9 includes CUs and TUs in CU list and generates TYpes
2113-
// list. The NumCUs is CUs + TUs, so need to modify the check.
2114-
// For split-dwarf
2115-
// GDB-11, DWARF5: TU units from dwo are not included.
2116-
// GDB-11, DWARF4: TU units from dwo are included.
2117-
if (MaxDWARFVersion >= 5)
2118-
SkipTypeUnits = !TUListSize ? true
2119-
: ((NUmCUsEncoded + NumDWARF5TUs) ==
2120-
BC.DwCtx->getNumCompileUnits());
2121-
2122-
if (!((CUListSize == NumCUs * 16) ||
2123-
(CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
2124-
errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
2125-
exit(1);
2126-
}
2127-
DenseSet<uint64_t> OriginalOffsets;
2128-
for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
2129-
Index < Units; ++Index) {
2130-
const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index);
2131-
if (SkipTypeUnits && CU->isTypeUnit())
2132-
continue;
2133-
const uint64_t Offset = read64le(Data);
2134-
Data += 16;
2135-
if (CU->getOffset() != Offset) {
2136-
errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
2137-
exit(1);
2138-
}
2139-
2140-
OriginalOffsets.insert(Offset);
2141-
OffsetToIndexMap[Offset] = Index;
2142-
}
2143-
2144-
// Ignore old address table.
2145-
const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
2146-
// Move Data to the beginning of symbol table.
2147-
Data += SymbolTableOffset - CUTypesOffset;
2148-
2149-
// Calculate the size of the new address table.
2150-
uint32_t NewAddressTableSize = 0;
2151-
for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
2152-
const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
2153-
NewAddressTableSize += Ranges.size() * 20;
2154-
}
2155-
2156-
// Difference between old and new table (and section) sizes.
2157-
// Could be negative.
2158-
int32_t Delta = NewAddressTableSize - OldAddressTableSize;
2159-
2160-
size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
2161-
2162-
// Free'd by ExecutableFileMemoryManager.
2163-
auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
2164-
uint8_t *Buffer = NewGdbIndexContents;
2165-
2166-
write32le(Buffer, Version);
2167-
write32le(Buffer + 4, CUListOffset);
2168-
write32le(Buffer + 8, CUTypesOffset);
2169-
write32le(Buffer + 12, AddressTableOffset);
2170-
write32le(Buffer + 16, SymbolTableOffset + Delta);
2171-
write32le(Buffer + 20, ConstantPoolOffset + Delta);
2172-
Buffer += 24;
2173-
2174-
using MapEntry = std::pair<uint32_t, CUInfo>;
2175-
std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
2176-
// Need to sort since we write out all of TUs in .debug_info before CUs.
2177-
std::sort(CUVector.begin(), CUVector.end(),
2178-
[](const MapEntry &E1, const MapEntry &E2) -> bool {
2179-
return E1.second.Offset < E2.second.Offset;
2180-
});
2181-
// Writing out CU List <Offset, Size>
2182-
for (auto &CUInfo : CUVector) {
2183-
// Skipping TU for DWARF5 when they are not included in CU list.
2184-
if (!OriginalOffsets.count(CUInfo.first))
2185-
continue;
2186-
write64le(Buffer, CUInfo.second.Offset);
2187-
// Length encoded in CU doesn't contain first 4 bytes that encode length.
2188-
write64le(Buffer + 8, CUInfo.second.Length + 4);
2189-
Buffer += 16;
2190-
}
2191-
2192-
// Rewrite TU CU List, since abbrevs can be different.
2193-
// Entry example:
2194-
// 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
2195-
// 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
2196-
// the second value is the type offset in the CU, and the third value is the
2197-
// type signature" Looking at what is being generated by gdb-add-index. The
2198-
// first entry is TU offset, second entry is offset from it, and third entry
2199-
// is the type signature.
2200-
if (TUListSize)
2201-
for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
2202-
write64le(Buffer, Entry.UnitOffset);
2203-
write64le(Buffer + 8, Entry.TypeDIERelativeOffset);
2204-
write64le(Buffer + 16, Entry.TypeHash);
2205-
Buffer += sizeof(GDBIndexTUEntry);
2206-
}
2207-
2208-
// Generate new address table.
2209-
for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
2210-
ARangesSectionWriter->getCUAddressRanges()) {
2211-
const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
2212-
const DebugAddressRangesVector &Ranges = CURangesPair.second;
2213-
for (const DebugAddressRange &Range : Ranges) {
2214-
write64le(Buffer, Range.LowPC);
2215-
write64le(Buffer + 8, Range.HighPC);
2216-
write32le(Buffer + 16, CUIndex);
2217-
Buffer += 20;
2218-
}
2219-
}
2220-
2221-
const size_t TrailingSize =
2222-
GdbIndexContents.data() + GdbIndexContents.size() - Data;
2223-
assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
2224-
"size calculation error");
2225-
2226-
// Copy over the rest of the original data.
2227-
memcpy(Buffer, Data, TrailingSize);
2228-
2229-
// Register the new section.
2230-
BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
2231-
NewGdbIndexSize);
2232-
}
2233-
22342063
std::unique_ptr<DebugBufferVector>
22352064
DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
22362065
auto LocBuffer = std::make_unique<DebugBufferVector>();

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ class LinuxKernelRewriter final : public MetadataRewriter {
273273

274274
/// Handle alternative instruction info from .altinstructions.
275275
Error readAltInstructions();
276+
Error tryReadAltInstructions(uint32_t AltInstFeatureSize,
277+
bool AltInstHasPadLen, bool ParseOnly);
276278
Error rewriteAltInstructions();
277279

278280
/// Read .pci_fixup
@@ -1319,12 +1321,69 @@ Error LinuxKernelRewriter::rewriteBugTable() {
13191321
/// u8 padlen; // present in older kernels
13201322
/// } __packed;
13211323
///
1322-
/// Note the structures is packed.
1324+
/// Note that the structure is packed.
1325+
///
1326+
/// Since the size of the "feature" field could be either u16 or u32, and
1327+
/// "padlen" presence is unknown, we attempt to parse .altinstructions section
1328+
/// using all possible combinations (four at this time). Since we validate the
1329+
/// contents of the section and its size, the detection works quite well.
1330+
/// Still, we leave the user the opportunity to specify these features on the
1331+
/// command line and skip the guesswork.
13231332
Error LinuxKernelRewriter::readAltInstructions() {
13241333
AltInstrSection = BC.getUniqueSectionByName(".altinstructions");
13251334
if (!AltInstrSection)
13261335
return Error::success();
13271336

1337+
// Presence of "padlen" field.
1338+
std::vector<bool> PadLenVariants;
1339+
if (opts::AltInstHasPadLen.getNumOccurrences())
1340+
PadLenVariants.push_back(opts::AltInstHasPadLen);
1341+
else
1342+
PadLenVariants = {false, true};
1343+
1344+
// Size (in bytes) variants of "feature" field.
1345+
std::vector<uint32_t> FeatureSizeVariants;
1346+
if (opts::AltInstFeatureSize.getNumOccurrences())
1347+
FeatureSizeVariants.push_back(opts::AltInstFeatureSize);
1348+
else
1349+
FeatureSizeVariants = {2, 4};
1350+
1351+
for (bool AltInstHasPadLen : PadLenVariants) {
1352+
for (uint32_t AltInstFeatureSize : FeatureSizeVariants) {
1353+
LLVM_DEBUG({
1354+
dbgs() << "BOLT-DEBUG: trying AltInstHasPadLen = " << AltInstHasPadLen
1355+
<< "; AltInstFeatureSize = " << AltInstFeatureSize << ";\n";
1356+
});
1357+
if (Error E = tryReadAltInstructions(AltInstFeatureSize, AltInstHasPadLen,
1358+
/*ParseOnly*/ true)) {
1359+
consumeError(std::move(E));
1360+
continue;
1361+
}
1362+
1363+
LLVM_DEBUG(dbgs() << "Matched .altinstructions format\n");
1364+
1365+
if (!opts::AltInstHasPadLen.getNumOccurrences())
1366+
BC.outs() << "BOLT-INFO: setting --" << opts::AltInstHasPadLen.ArgStr
1367+
<< '=' << AltInstHasPadLen << '\n';
1368+
1369+
if (!opts::AltInstFeatureSize.getNumOccurrences())
1370+
BC.outs() << "BOLT-INFO: setting --" << opts::AltInstFeatureSize.ArgStr
1371+
<< '=' << AltInstFeatureSize << '\n';
1372+
1373+
return tryReadAltInstructions(AltInstFeatureSize, AltInstHasPadLen,
1374+
/*ParseOnly*/ false);
1375+
}
1376+
}
1377+
1378+
// We couldn't match the format. Read again to properly propagate the error
1379+
// to the user.
1380+
return tryReadAltInstructions(opts::AltInstFeatureSize,
1381+
opts::AltInstHasPadLen, /*ParseOnly*/ false);
1382+
}
1383+
1384+
Error LinuxKernelRewriter::tryReadAltInstructions(uint32_t AltInstFeatureSize,
1385+
bool AltInstHasPadLen,
1386+
bool ParseOnly) {
13281387
const uint64_t Address = AltInstrSection->getAddress();
13291388
DataExtractor DE = DataExtractor(AltInstrSection->getContents(),
13301389
BC.AsmInfo->isLittleEndian(),
@@ -1336,12 +1395,12 @@ Error LinuxKernelRewriter::readAltInstructions() {
13361395
Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
13371396
const uint64_t AltInstAddress =
13381397
Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
1339-
const uint64_t Feature = DE.getUnsigned(Cursor, opts::AltInstFeatureSize);
1398+
const uint64_t Feature = DE.getUnsigned(Cursor, AltInstFeatureSize);
13401399
const uint8_t OrgSize = DE.getU8(Cursor);
13411400
const uint8_t AltSize = DE.getU8(Cursor);
13421401

13431402
// Older kernels may have the padlen field.
1344-
const uint8_t PadLen = opts::AltInstHasPadLen ? DE.getU8(Cursor) : 0;
1403+
const uint8_t PadLen = AltInstHasPadLen ? DE.getU8(Cursor) : 0;
13451404

13461405
if (!Cursor)
13471406
return createStringError(
@@ -1358,7 +1417,7 @@ Error LinuxKernelRewriter::readAltInstructions() {
13581417
<< "\n\tFeature: 0x" << Twine::utohexstr(Feature)
13591418
<< "\n\tOrgSize: " << (int)OrgSize
13601419
<< "\n\tAltSize: " << (int)AltSize << '\n';
1361-
if (opts::AltInstHasPadLen)
1420+
if (AltInstHasPadLen)
13621421
BC.outs() << "\tPadLen: " << (int)PadLen << '\n';
13631422
}
13641423

@@ -1375,7 +1434,7 @@ Error LinuxKernelRewriter::readAltInstructions() {
13751434

13761435
BinaryFunction *AltBF =
13771436
BC.getBinaryFunctionContainingAddress(AltInstAddress);
1378-
if (AltBF && BC.shouldEmit(*AltBF)) {
1437+
if (!ParseOnly && AltBF && BC.shouldEmit(*AltBF)) {
13791438
BC.errs()
13801439
<< "BOLT-WARNING: alternative instruction sequence found in function "
13811440
<< *AltBF << '\n';
@@ -1397,6 +1456,9 @@ Error LinuxKernelRewriter::readAltInstructions() {
13971456
" referenced by .altinstructions entry %d",
13981457
OrgInstAddress, EntryID);
13991458

1459+
if (ParseOnly)
1460+
continue;
1461+
14001462
// There could be more than one alternative instruction sequences for the
14011463
// same original instruction. Annotate each alternative separately.
14021464
std::string AnnotationName = "AltInst";

0 commit comments

Comments
 (0)