[BOLT] Detect internal references into a middle of instruction

Summary:
Some instructions in assembly-written functions could reference 8-byte
constants from another instructions using 4-byte offsets, presumably to
save a couple of bytes.

Detect such cases, and skip processing such functions until we teach
BOLT how to handle references into a middle of instruction.

(cherry picked from FBD14768212)
This commit is contained in:
Maksim Panchenko 2019-04-03 22:31:12 -07:00
parent 7fd487066f
commit c8a927696c
2 changed files with 27 additions and 1 deletions

View File

@ -1464,9 +1464,32 @@ add_instruction:
updateState(State::Disassembled);
postProcessEntryPoints();
postProcessJumpTables();
}
void BinaryFunction::postProcessEntryPoints() {
for (auto Offset : EntryOffsets) {
if (!getInstructionAtOffset(Offset)) {
// On AArch64 there are legitimate reasons to have references past the
// end of the function, e.g. jump tables.
if (BC.isAArch64() && Offset == getSize()) {
continue;
}
errs() << "BOLT-WARNING: reference in the middle of instruction "
"detected in function " << *this
<< " at offset 0x" << Twine::utohexstr(Offset) << '\n';
if (BC.HasRelocations) {
errs() << "BOLT-ERROR: unable to keep processing in relocation mode\n";
exit(1);
}
setSimple(false);
}
}
}
void BinaryFunction::postProcessJumpTables() {
// Create labels for all entries.
for (auto &JTI : JumpTables) {
@ -1683,7 +1706,7 @@ bool BinaryFunction::buildCFG() {
return false;
}
if (!(CurrentState == State::Disassembled))
if (CurrentState != State::Disassembled)
return false;
assert(BasicBlocks.empty() && "basic block list should be empty");

View File

@ -1960,6 +1960,9 @@ public:
/// Returns false if disassembly failed.
void disassemble(ArrayRef<uint8_t> FunctionData);
/// Validate entry points.
void postProcessEntryPoints();
/// Post-processing for jump tables after disassembly. Since their
/// boundaries are not known until all call sites are seen, we need this
/// extra pass to perform any final adjustments.