aboutsummaryrefslogtreecommitdiff
path: root/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 17:16:04 +0900
committerNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 17:16:04 +0900
commit0aa930a41f2d1ebf1fa90ec42da8f96d15a4dcbb (patch)
tree6a77b463f700e090df586672c26b9fe765fd115b /bolt/lib/Rewrite/LinuxKernelRewriter.cpp
parentec6892d1c979ce0b84c86918d5cdbb03037b409a (diff)
parent6d16b1c5c468a79ecf867293023c89ac518ecdda (diff)
downloadllvm-users/chapuni/cov/single/nextcount-base.zip
llvm-users/chapuni/cov/single/nextcount-base.tar.gz
llvm-users/chapuni/cov/single/nextcount-base.tar.bz2
Merge branch 'users/chapuni/cov/single/pair' into users/chapuni/cov/single/nextcount-baseusers/chapuni/cov/single/nextcount-base
Diffstat (limited to 'bolt/lib/Rewrite/LinuxKernelRewriter.cpp')
-rw-r--r--bolt/lib/Rewrite/LinuxKernelRewriter.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
index 0532468..5a5e044 100644
--- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
+++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
@@ -21,6 +21,8 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorOr.h"
+#include <regex>
#define DEBUG_TYPE "bolt-linux"
@@ -89,6 +91,34 @@ static cl::opt<bool>
} // namespace opts
+/// Linux kernel version
+struct LKVersion {
+ LKVersion() {}
+ LKVersion(unsigned Major, unsigned Minor, unsigned Rev)
+ : Major(Major), Minor(Minor), Rev(Rev) {}
+
+ bool operator<(const LKVersion &Other) const {
+ return std::make_tuple(Major, Minor, Rev) <
+ std::make_tuple(Other.Major, Other.Minor, Other.Rev);
+ }
+
+ bool operator>(const LKVersion &Other) const { return Other < *this; }
+
+ bool operator<=(const LKVersion &Other) const { return !(*this > Other); }
+
+ bool operator>=(const LKVersion &Other) const { return !(*this < Other); }
+
+ bool operator==(const LKVersion &Other) const {
+ return Major == Other.Major && Minor == Other.Minor && Rev == Other.Rev;
+ }
+
+ bool operator!=(const LKVersion &Other) const { return !(*this == Other); }
+
+ unsigned Major{0};
+ unsigned Minor{0};
+ unsigned Rev{0};
+};
+
/// Linux Kernel supports stack unwinding using ORC (oops rewind capability).
/// ORC state at every IP can be described by the following data structure.
struct ORCState {
@@ -148,6 +178,8 @@ public:
};
class LinuxKernelRewriter final : public MetadataRewriter {
+ LKVersion LinuxKernelVersion;
+
/// Information required for updating metadata referencing an instruction.
struct InstructionFixup {
BinarySection &Section; // Section referencing the instruction.
@@ -249,6 +281,8 @@ class LinuxKernelRewriter final : public MetadataRewriter {
ErrorOr<BinarySection &> PCIFixupSection = std::errc::bad_address;
static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16;
+ Error detectLinuxKernelVersion();
+
/// Process linux kernel special sections and their relocations.
void processLKSections();
@@ -314,6 +348,9 @@ public:
: MetadataRewriter("linux-kernel-rewriter", BC) {}
Error preCFGInitializer() override {
+ if (Error E = detectLinuxKernelVersion())
+ return E;
+
processLKSections();
if (Error E = processSMPLocks())
@@ -394,6 +431,28 @@ public:
}
};
+Error LinuxKernelRewriter::detectLinuxKernelVersion() {
+ if (BinaryData *BD = BC.getBinaryDataByName("linux_banner")) {
+ const BinarySection &Section = BD->getSection();
+ const std::string S =
+ Section.getContents().substr(BD->getOffset(), BD->getSize()).str();
+
+ const std::regex Re(R"---(Linux version ((\d+)\.(\d+)(\.(\d+))?))---");
+ std::smatch Match;
+ if (std::regex_search(S, Match, Re)) {
+ const unsigned Major = std::stoi(Match[2].str());
+ const unsigned Minor = std::stoi(Match[3].str());
+ const unsigned Rev = Match[5].matched ? std::stoi(Match[5].str()) : 0;
+ LinuxKernelVersion = LKVersion(Major, Minor, Rev);
+ BC.outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str()
+ << "\n";
+ return Error::success();
+ }
+ }
+ return createStringError(errc::executable_format_error,
+ "Linux kernel version is unknown");
+}
+
void LinuxKernelRewriter::processLKSections() {
processLKKSymtab();
processLKKSymtab(true);