[BOLT] Add ORC validation for the Linux kernel (#90660)

The Linux kernel expects ORC tables to be sorted by IP address (for
binary search to work). Add a post-emit pass in LinuxKernelRewriter that
validates the written .orc_unwind_ip against that expectation.
This commit is contained in:
Maksim Panchenko
2024-04-30 14:17:33 -07:00
committed by GitHub
parent 1fb5083aed
commit c665e49911

View File

@@ -248,6 +248,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
/// Update ORC data in the binary.
Error rewriteORCTables();
/// Validate written ORC tables after binary emission.
Error validateORCTables();
/// Static call table handling.
Error readStaticCalls();
Error rewriteStaticCalls();
@@ -358,6 +361,9 @@ public:
if (Error E = updateStaticKeysJumpTablePostEmit())
return E;
if (Error E = validateORCTables())
return E;
return Error::success();
}
};
@@ -837,6 +843,31 @@ Error LinuxKernelRewriter::rewriteORCTables() {
return Error::success();
}
Error LinuxKernelRewriter::validateORCTables() {
if (!ORCUnwindIPSection)
return Error::success();
const uint64_t IPSectionAddress = ORCUnwindIPSection->getAddress();
DataExtractor IPDE = DataExtractor(ORCUnwindIPSection->getOutputContents(),
BC.AsmInfo->isLittleEndian(),
BC.AsmInfo->getCodePointerSize());
DataExtractor::Cursor IPCursor(0);
uint64_t PrevIP = 0;
for (uint32_t Index = 0; Index < NumORCEntries; ++Index) {
const uint64_t IP =
IPSectionAddress + IPCursor.tell() + (int32_t)IPDE.getU32(IPCursor);
if (!IPCursor)
return createStringError(errc::executable_format_error,
"out of bounds while reading ORC IP table: %s",
toString(IPCursor.takeError()).c_str());
assert(IP >= PrevIP && "Unsorted ORC table detected");
PrevIP = IP;
}
return Error::success();
}
/// The static call site table is created by objtool and contains entries in the
/// following format:
///