Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions bolt/include/bolt/Core/BinaryFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2356,10 +2356,9 @@ class BinaryFunction {
bool postProcessIndirectBranches(MCPlusBuilder::AllocatorIdTy AllocId);

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

/// Return all call site profile info for this function.
IndirectCallSiteProfile &getAllCallSites() { return AllCallSites; }
Expand Down
92 changes: 48 additions & 44 deletions bolt/lib/Core/BinaryFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2049,41 +2049,47 @@ void BinaryFunction::postProcessJumpTables() {
}
}

bool BinaryFunction::validateExternallyReferencedOffsets() {
SmallPtrSet<MCSymbol *, 4> JTTargets;
for (const JumpTable *JT : llvm::make_second_range(JumpTables))
JTTargets.insert_range(JT->Entries);

bool HasUnclaimedReference = false;
for (uint64_t Destination : ExternallyReferencedOffsets) {
// Ignore __builtin_unreachable().
if (Destination == getSize())
continue;
// Ignore constant islands
if (isInConstantIsland(Destination + getAddress()))
continue;
bool BinaryFunction::validateInternalRefDataRelocations() {
if (InternalRefDataRelocations.empty())
return true;

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

if (opts::Verbosity >= 1) {
BC.errs() << "BOLT-WARNING: unclaimed data to code reference (possibly "
<< "an unrecognized jump table entry) to " << BB->getName()
<< " in " << *this << "\n";
}
auto L = BC.scopeLock();
addEntryPoint(*BB);
} else {
BC.errs() << "BOLT-WARNING: unknown data to code reference to offset "
<< Twine::utohexstr(Destination) << " in " << *this << "\n";
setIgnored();
DenseSet<uint64_t> UnclaimedRelocations(InternalRefDataRelocations);
for (const JumpTable *JT : llvm::make_second_range(JumpTables)) {
uint64_t EntryAddress = JT->getAddress();
while (EntryAddress < JT->getAddress() + JT->getSize()) {
UnclaimedRelocations.erase(EntryAddress);
EntryAddress += JT->EntrySize;
}
HasUnclaimedReference = true;
}
return !HasUnclaimedReference;

if (UnclaimedRelocations.empty())
return true;

BC.errs() << "BOLT-WARNING: " << UnclaimedRelocations.size()
<< " unclaimed data relocation"
<< (UnclaimedRelocations.size() > 1 ? "s" : "")
<< " remain against function " << *this;
if (opts::Verbosity) {
BC.errs() << ":\n";
for (uint64_t RelocationAddress : UnclaimedRelocations) {
const Relocation *Relocation = BC.getRelocationAt(RelocationAddress);
BC.errs() << " ";
if (Relocation)
BC.errs() << *Relocation;
else
BC.errs() << "<missing relocation>";
BC.errs() << '\n';
}
} else {
BC.errs() << ". Re-run with -v=1 to see the list\n";
}

return false;
}

bool BinaryFunction::postProcessIndirectBranches(
Expand Down Expand Up @@ -2208,14 +2214,6 @@ bool BinaryFunction::postProcessIndirectBranches(
LastIndirectJumpBB->updateJumpTableSuccessors();
}

// Validate that all data references to function offsets are claimed by
// recognized jump tables. Register externally referenced blocks as entry
// points.
if (!opts::StrictMode && hasInternalReference()) {
if (!validateExternallyReferencedOffsets())
return false;
}

if (HasUnknownControlFlow && !BC.HasRelocations)
return false;

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

// Make any necessary adjustments for indirect branches.
if (!postProcessIndirectBranches(AllocatorId)) {
if (opts::Verbosity) {
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
<< *this << '\n';
}
bool ValidCFG = postProcessIndirectBranches(AllocatorId);
if (!ValidCFG && opts::Verbosity) {
BC.errs() << "BOLT-WARNING: failed to post-process indirect branches for "
<< *this << '\n';
}

// Validate that all data references to function offsets are claimed by
// recognized jump tables.
if (ValidCFG)
ValidCFG = validateInternalRefDataRelocations();

if (!ValidCFG) {
if (BC.isAArch64())
PreserveNops = BC.HasRelocations;

Expand Down
7 changes: 1 addition & 6 deletions bolt/test/X86/unclaimed-jt-entries.s
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,7 @@

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

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

.text
.globl main
Expand Down
9 changes: 2 additions & 7 deletions bolt/test/runtime/X86/unclaimed-jt-entries.s
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,9 @@

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

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

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