Skip to content

Commit b8ece51

Browse files
committed
[BOLT] Properly validate relocations against internals of a function
Validation of data relocations targeting internals of a function was happening based on offsets inside a function. As a result, if multiple relocations were targeting the same offset, and one of the relocations was verified, e.g. as belonging to a jump table, then all relocations targeting the offset would be considered verified and valid. Now that we are tracking relocations pointing inside every function, we can do a better validation based on the location of the relocation. E.g., if a relocation belongs to a jump table only that relocation will be accounted for and other relocations pointing to the same address will be evaluated independently.
1 parent e5e74e9 commit b8ece51

File tree

4 files changed

+54
-61
lines changed

4 files changed

+54
-61
lines changed

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2356,10 +2356,9 @@ class BinaryFunction {
23562356
bool postProcessIndirectBranches(MCPlusBuilder::AllocatorIdTy AllocId);
23572357

23582358
/// Validate that all data references to function offsets are claimed by
2359-
/// recognized jump tables. Register externally referenced blocks as entry
2360-
/// points. Returns true if there are no unclaimed externally referenced
2361-
/// offsets.
2362-
bool validateExternallyReferencedOffsets();
2359+
/// recognized jump tables. Returns true if there are no unclaimed externally
2360+
/// referenced offsets.
2361+
bool validateInternalRefDataRelocations();
23632362

23642363
/// Return all call site profile info for this function.
23652364
IndirectCallSiteProfile &getAllCallSites() { return AllCallSites; }

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,41 +2049,47 @@ void BinaryFunction::postProcessJumpTables() {
20492049
}
20502050
}
20512051

2052-
bool BinaryFunction::validateExternallyReferencedOffsets() {
2053-
SmallPtrSet<MCSymbol *, 4> JTTargets;
2054-
for (const JumpTable *JT : llvm::make_second_range(JumpTables))
2055-
JTTargets.insert_range(JT->Entries);
2056-
2057-
bool HasUnclaimedReference = false;
2058-
for (uint64_t Destination : ExternallyReferencedOffsets) {
2059-
// Ignore __builtin_unreachable().
2060-
if (Destination == getSize())
2061-
continue;
2062-
// Ignore constant islands
2063-
if (isInConstantIsland(Destination + getAddress()))
2064-
continue;
2052+
bool BinaryFunction::validateInternalRefDataRelocations() {
2053+
if (InternalRefDataRelocations.empty())
2054+
return true;
20652055

2066-
if (BinaryBasicBlock *BB = getBasicBlockAtOffset(Destination)) {
2067-
// Check if the externally referenced offset is a recognized jump table
2068-
// target.
2069-
if (JTTargets.contains(BB->getLabel()))
2070-
continue;
2056+
// Rely on the user hint that all data refs are valid and only used as
2057+
// destinations by indirect branch in the same function.
2058+
if (opts::StrictMode)
2059+
return true;
20712060

2072-
if (opts::Verbosity >= 1) {
2073-
BC.errs() << "BOLT-WARNING: unclaimed data to code reference (possibly "
2074-
<< "an unrecognized jump table entry) to " << BB->getName()
2075-
<< " in " << *this << "\n";
2076-
}
2077-
auto L = BC.scopeLock();
2078-
addEntryPoint(*BB);
2079-
} else {
2080-
BC.errs() << "BOLT-WARNING: unknown data to code reference to offset "
2081-
<< Twine::utohexstr(Destination) << " in " << *this << "\n";
2082-
setIgnored();
2061+
DenseSet<uint64_t> UnclaimedRelocations(InternalRefDataRelocations);
2062+
for (const JumpTable *JT : llvm::make_second_range(JumpTables)) {
2063+
uint64_t EntryAddress = JT->getAddress();
2064+
while (EntryAddress < JT->getAddress() + JT->getSize()) {
2065+
UnclaimedRelocations.erase(EntryAddress);
2066+
EntryAddress += JT->EntrySize;
20832067
}
2084-
HasUnclaimedReference = true;
20852068
}
2086-
return !HasUnclaimedReference;
2069+
2070+
if (UnclaimedRelocations.empty())
2071+
return true;
2072+
2073+
BC.errs() << "BOLT-WARNING: " << UnclaimedRelocations.size()
2074+
<< " unclaimed data relocation"
2075+
<< (UnclaimedRelocations.size() > 1 ? "s" : "")
2076+
<< " remain against function " << *this;
2077+
if (opts::Verbosity) {
2078+
BC.errs() << ":\n";
2079+
for (uint64_t RelocationAddress : UnclaimedRelocations) {
2080+
const Relocation *Relocation = BC.getRelocationAt(RelocationAddress);
2081+
BC.errs() << " ";
2082+
if (Relocation)
2083+
BC.errs() << *Relocation;
2084+
else
2085+
BC.errs() << "<missing relocation>";
2086+
BC.errs() << '\n';
2087+
}
2088+
} else {
2089+
BC.errs() << ". Re-run with -v=1 to see the list\n";
2090+
}
2091+
2092+
return false;
20872093
}
20882094

20892095
bool BinaryFunction::postProcessIndirectBranches(
@@ -2208,14 +2214,6 @@ bool BinaryFunction::postProcessIndirectBranches(
22082214
LastIndirectJumpBB->updateJumpTableSuccessors();
22092215
}
22102216

2211-
// Validate that all data references to function offsets are claimed by
2212-
// recognized jump tables. Register externally referenced blocks as entry
2213-
// points.
2214-
if (!opts::StrictMode && hasInternalReference()) {
2215-
if (!validateExternallyReferencedOffsets())
2216-
return false;
2217-
}
2218-
22192217
if (HasUnknownControlFlow && !BC.HasRelocations)
22202218
return false;
22212219

@@ -2504,12 +2502,18 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
25042502
CurrentState = State::CFG;
25052503

25062504
// Make any necessary adjustments for indirect branches.
2507-
if (!postProcessIndirectBranches(AllocatorId)) {
2508-
if (opts::Verbosity) {
2509-
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
2510-
<< *this << '\n';
2511-
}
2505+
bool ValidCFG = postProcessIndirectBranches(AllocatorId);
2506+
if (!ValidCFG && opts::Verbosity) {
2507+
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
2508+
<< *this << '\n';
2509+
}
2510+
2511+
// Validate that all data references to function offsets are claimed by
2512+
// recognized jump tables.
2513+
if (ValidCFG)
2514+
ValidCFG = validateInternalRefDataRelocations();
25122515

2516+
if (!ValidCFG) {
25132517
if (BC.isAArch64())
25142518
PreserveNops = BC.HasRelocations;
25152519

bolt/test/X86/unclaimed-jt-entries.s

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,7 @@
3232

3333
# RUN: llvm-bolt %t.exe -v=1 -o %t.out 2>&1 | FileCheck %s
3434

35-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in main
36-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in main
37-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in main
38-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in main
39-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in main
40-
# CHECK: BOLT-WARNING: failed to post-process indirect branches for main
35+
# CHECK: BOLT-WARNING: 11 unclaimed data relocations remain against function main
4136

4237
.text
4338
.globl main

bolt/test/runtime/X86/unclaimed-jt-entries.s

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,9 @@
1818

1919
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
2020
# RUN: %clang %cflags %S/Inputs/unclaimed-jt-entries.c -no-pie %t.o -o %t.exe -Wl,-q
21-
# RUN: llvm-bolt %t.exe -v=1 -o %t.out --sequential-disassembly 2>&1 | FileCheck %s
21+
# RUN: llvm-bolt %t.exe -o %t.out 2>&1 | FileCheck %s
2222

23-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in func
24-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in func
25-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in func
26-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in func
27-
# CHECK: BOLT-WARNING: unclaimed data to code reference (possibly an unrecognized jump table entry) to .Ltmp[[#]] in func
28-
# CHECK: BOLT-WARNING: failed to post-process indirect branches for func
23+
# CHECK: BOLT-WARNING: 11 unclaimed data relocations remain against function func
2924

3025
# Run the optimized binary
3126
# RUN: %t.out 3 | FileCheck %s --check-prefix=CHECK3

0 commit comments

Comments
 (0)