Skip to content

Commit 02482f4

Browse files
authored
[BOLT] Properly validate relocations against internals of a function (#167451)
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 49a7772 commit 02482f4

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
@@ -2041,41 +2041,47 @@ void BinaryFunction::postProcessJumpTables() {
20412041
}
20422042
}
20432043

2044-
bool BinaryFunction::validateExternallyReferencedOffsets() {
2045-
SmallPtrSet<MCSymbol *, 4> JTTargets;
2046-
for (const JumpTable *JT : llvm::make_second_range(JumpTables))
2047-
JTTargets.insert_range(JT->Entries);
2048-
2049-
bool HasUnclaimedReference = false;
2050-
for (uint64_t Destination : ExternallyReferencedOffsets) {
2051-
// Ignore __builtin_unreachable().
2052-
if (Destination == getSize())
2053-
continue;
2054-
// Ignore constant islands
2055-
if (isInConstantIsland(Destination + getAddress()))
2056-
continue;
2044+
bool BinaryFunction::validateInternalRefDataRelocations() {
2045+
if (InternalRefDataRelocations.empty())
2046+
return true;
20572047

2058-
if (BinaryBasicBlock *BB = getBasicBlockAtOffset(Destination)) {
2059-
// Check if the externally referenced offset is a recognized jump table
2060-
// target.
2061-
if (JTTargets.contains(BB->getLabel()))
2062-
continue;
2048+
// Rely on the user hint that all data refs are valid and only used as
2049+
// destinations by indirect branch in the same function.
2050+
if (opts::StrictMode)
2051+
return true;
20632052

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

20812087
bool BinaryFunction::postProcessIndirectBranches(
@@ -2200,14 +2206,6 @@ bool BinaryFunction::postProcessIndirectBranches(
22002206
LastIndirectJumpBB->updateJumpTableSuccessors();
22012207
}
22022208

2203-
// Validate that all data references to function offsets are claimed by
2204-
// recognized jump tables. Register externally referenced blocks as entry
2205-
// points.
2206-
if (!opts::StrictMode && hasInternalReference()) {
2207-
if (!validateExternallyReferencedOffsets())
2208-
return false;
2209-
}
2210-
22112209
if (HasUnknownControlFlow && !BC.HasRelocations)
22122210
return false;
22132211

@@ -2496,12 +2494,18 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
24962494
CurrentState = State::CFG;
24972495

24982496
// Make any necessary adjustments for indirect branches.
2499-
if (!postProcessIndirectBranches(AllocatorId)) {
2500-
if (opts::Verbosity) {
2501-
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
2502-
<< *this << '\n';
2503-
}
2497+
bool ValidCFG = postProcessIndirectBranches(AllocatorId);
2498+
if (!ValidCFG && opts::Verbosity) {
2499+
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
2500+
<< *this << '\n';
2501+
}
2502+
2503+
// Validate that all data references to function offsets are claimed by
2504+
// recognized jump tables.
2505+
if (ValidCFG)
2506+
ValidCFG = validateInternalRefDataRelocations();
25042507

2508+
if (!ValidCFG) {
25052509
if (BC.isAArch64())
25062510
PreserveNops = BC.HasRelocations;
25072511

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)