diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index d96199e020d31..3944bb742938a 100644 --- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp +++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp @@ -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 @@ class LinuxKernelRewriter final : public MetadataRewriter { 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: ///