[llvm] [BOLT] Detect Linux kernel version if the binary is a Linux kernel (PR #119088)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 7 11:16:50 PST 2024
https://github.com/FLZ101 updated https://github.com/llvm/llvm-project/pull/119088
>From 782c464e89db62884bde3230aa4ffcc0c9574a8f Mon Sep 17 00:00:00 2001
From: fengleizZZ <zhangfenglei at huawei.com>
Date: Sun, 8 Dec 2024 02:37:49 +0800
Subject: [PATCH] [BOLT] Detect Linux kernel version if the binary is a Linux
kernel
This makes it easier to handle differences (e.g. of exception table
entry size) among versions of Linux kernel
---
bolt/include/bolt/Core/BinaryContext.h | 3 +++
bolt/lib/Rewrite/RewriteInstance.cpp | 22 +++++++++++++++++++
bolt/test/X86/linux-version.s | 30 ++++++++++++++++++++++++++
3 files changed, 55 insertions(+)
create mode 100644 bolt/test/X86/linux-version.s
diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index 115e59ca0697e5..052a145efe4a4b 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -670,6 +670,9 @@ class BinaryContext {
/// Indicates if the binary is Linux kernel.
bool IsLinuxKernel{false};
+ /// Linux kernel version (major, minor, reversion)
+ std::tuple<unsigned, unsigned, unsigned> LinuxKernelVersion;
+
/// Indicates if relocations are available for usage.
bool HasRelocations{false};
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 76e1f0156f828d..b88da11701b354 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -61,6 +61,7 @@
#include <fstream>
#include <memory>
#include <optional>
+#include <regex>
#include <system_error>
#undef DEBUG_TYPE
@@ -1030,6 +1031,27 @@ void RewriteInstance::discoverFileObjects() {
continue;
}
+ if (BC->IsLinuxKernel && SymName == "linux_banner") {
+ const StringRef SectionContents =
+ cantFail(Section->getContents(), "can not get section contents");
+ const std::string S =
+ SectionContents
+ .substr(SymbolAddress - Section->getAddress(), SymbolSize)
+ .str();
+
+ const std::regex Re(R"---(Linux version ((\d+)\.(\d+)(\.(\d+))?))---");
+ std::smatch Match;
+ if (std::regex_search(S, Match, Re)) {
+ unsigned Major = std::stoi(Match[2].str());
+ unsigned Minor = std::stoi(Match[3].str());
+ unsigned Rev = Match.size() > 5 ? std::stoi(Match[5].str()) : 0;
+ BC->LinuxKernelVersion = std::make_tuple(Major, Minor, Rev);
+ BC->outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str();
+ } else {
+ BC->errs() << "BOLT-WARNING: Linux kernel version is unknown\n";
+ }
+ }
+
if (!Section->isText()) {
assert(SymbolType != SymbolRef::ST_Function &&
"unexpected function inside non-code section");
diff --git a/bolt/test/X86/linux-version.s b/bolt/test/X86/linux-version.s
new file mode 100644
index 00000000000000..079910be931cdb
--- /dev/null
+++ b/bolt/test/X86/linux-version.s
@@ -0,0 +1,30 @@
+# REQUIRES: system-linux
+
+## Check that BOLT correctly detects the Linux kernel version
+
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
+# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
+# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr
+
+# RUN: llvm-bolt %t.exe -o %t.out | FileCheck %s
+
+# CHECK: BOLT-INFO: Linux kernel version is 6.6.61
+
+ .text
+ .globl f
+ .type f, @function
+f:
+ ret
+ .size f, .-f
+
+ .globl linux_banner
+ .section .rodata
+ .align 16
+ .type linux_banner, @object
+ .size linux_banner, 22
+linux_banner:
+ .string "Linux version 6.6.61\n"
+
+## Fake Linux Kernel sections.
+ .section __ksymtab,"a", at progbits
+ .section __ksymtab_gpl,"a", at progbits
More information about the llvm-commits
mailing list