[llvm] [BOLT] Detect Linux kernel version if the binary is a Linux kernel (PR #119088)

via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 13 08:15:27 PST 2024


https://github.com/FLZ101 updated https://github.com/llvm/llvm-project/pull/119088

>From 69554a819ef782199d1b25039e484b174a48cdaf Mon Sep 17 00:00:00 2001
From: fengleizZZ <zhangfenglei at huawei.com>
Date: Sun, 8 Dec 2024 02:37:49 +0800
Subject: [PATCH 1/4] [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) between versions of Linux kernel
---
 bolt/include/bolt/Core/BinaryContext.h |  3 +++
 bolt/lib/Rewrite/RewriteInstance.cpp   | 23 ++++++++++++++++++++
 bolt/test/X86/linux-version.s          | 30 ++++++++++++++++++++++++++
 3 files changed, 56 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..48617dc8ea5946 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,25 @@ 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();
+      }
+    }
+
     if (!Section->isText()) {
       assert(SymbolType != SymbolRef::ST_Function &&
              "unexpected function inside non-code section");
@@ -1205,6 +1225,9 @@ void RewriteInstance::discoverFileObjects() {
     PreviousFunction = BF;
   }
 
+  if (BC->IsLinuxKernel && !std::get<0>(BC->LinuxKernelVersion))
+    BC->errs() << "BOLT-WARNING: Linux kernel version is unknown\n";
+
   // Read dynamic relocation first as their presence affects the way we process
   // static relocations. E.g. we will ignore a static relocation at an address
   // that is a subject to dynamic relocation processing.
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

>From 6b931b37b0a0b40828c018f2e095b25d778c4b9d Mon Sep 17 00:00:00 2001
From: fengleizZZ <zhangfenglei at huawei.com>
Date: Mon, 9 Dec 2024 00:27:31 +0800
Subject: [PATCH 2/4] [BOLT] Detect Linux kernel version if the binary is a
 Linux kernel

Use struct instead of tuple to represent Linux kernel version
---
 bolt/include/bolt/Core/BinaryContext.h | 31 ++++++++++++++++++++++++--
 bolt/lib/Rewrite/RewriteInstance.cpp   |  4 ++--
 bolt/unittests/Core/BinaryContext.cpp  | 14 ++++++++++++
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h
index 052a145efe4a4b..7d49dd003ca02a 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -180,6 +180,34 @@ struct JournalingStreams {
 Error createNonFatalBOLTError(const Twine &S);
 Error createFatalBOLTError(const Twine &S);
 
+/// 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};
+};
+
 class BinaryContext {
   BinaryContext() = delete;
 
@@ -670,8 +698,7 @@ class BinaryContext {
   /// Indicates if the binary is Linux kernel.
   bool IsLinuxKernel{false};
 
-  /// Linux kernel version (major, minor, reversion)
-  std::tuple<unsigned, unsigned, unsigned> LinuxKernelVersion;
+  LKVersion 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 48617dc8ea5946..85a753b3cb0554 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -1045,7 +1045,7 @@ void RewriteInstance::discoverFileObjects() {
         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->LinuxKernelVersion = LKVersion(Major, Minor, Rev);
         BC->outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str();
       }
     }
@@ -1225,7 +1225,7 @@ void RewriteInstance::discoverFileObjects() {
     PreviousFunction = BF;
   }
 
-  if (BC->IsLinuxKernel && !std::get<0>(BC->LinuxKernelVersion))
+  if (BC->IsLinuxKernel && !BC->LinuxKernelVersion.Major)
     BC->errs() << "BOLT-WARNING: Linux kernel version is unknown\n";
 
   // Read dynamic relocation first as their presence affects the way we process
diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp
index 9819a8c2b777b7..d8400d9b18174f 100644
--- a/bolt/unittests/Core/BinaryContext.cpp
+++ b/bolt/unittests/Core/BinaryContext.cpp
@@ -218,3 +218,17 @@ TEST_P(BinaryContextTester, BaseAddressSegmentsSmallerThanAlignment) {
   ASSERT_TRUE(BaseAddress.has_value());
   ASSERT_EQ(*BaseAddress, 0xaaaaaaaa0000ULL);
 }
+
+TEST(BinaryContextTester, LKVersion) {
+  LKVersion V1;
+  LKVersion V2(5, 9, 15);
+  LKVersion V3(6, 12, 1);
+
+  V1 = V3;
+  ASSERT_TRUE(V1 == V3);
+  ASSERT_TRUE(V2 != V3);
+  ASSERT_TRUE(V2 < V3);
+  ASSERT_TRUE(V2 <= V3);
+  ASSERT_TRUE(V3 > V2);
+  ASSERT_TRUE(V3 >= V2);
+}

>From bb683eb25d229aa31a55abe804c784843be1affc Mon Sep 17 00:00:00 2001
From: fengleizZZ <zhangfenglei at huawei.com>
Date: Mon, 9 Dec 2024 23:23:50 +0800
Subject: [PATCH 3/4] [BOLT] Detect Linux kernel version if the binary is a
 Linux kernel

Move LinuxKernelVersion to LinuxKernelRewriter
---
 bolt/include/bolt/Core/BinaryContext.h   | 30 ------------
 bolt/include/bolt/Core/BinaryData.h      |  5 ++
 bolt/lib/Core/BinaryContext.cpp          |  1 +
 bolt/lib/Rewrite/LinuxKernelRewriter.cpp | 59 ++++++++++++++++++++++++
 bolt/lib/Rewrite/RewriteInstance.cpp     | 23 ---------
 bolt/test/X86/linux-alt-instruction.s    |  9 ++++
 bolt/test/X86/linux-bug-table.s          |  9 ++++
 bolt/test/X86/linux-exceptions.s         |  9 ++++
 bolt/test/X86/linux-orc.s                |  9 ++++
 bolt/test/X86/linux-parainstructions.s   |  9 ++++
 bolt/test/X86/linux-pci-fixup.s          |  9 ++++
 bolt/test/X86/linux-smp-locks.s          |  9 ++++
 bolt/test/X86/linux-static-calls.s       |  9 ++++
 bolt/test/X86/linux-static-keys.s        |  9 ++++
 bolt/test/X86/linux-version.s            | 30 ------------
 bolt/unittests/Core/BinaryContext.cpp    | 14 ------
 16 files changed, 146 insertions(+), 97 deletions(-)
 delete 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 7d49dd003ca02a..115e59ca0697e5 100644
--- a/bolt/include/bolt/Core/BinaryContext.h
+++ b/bolt/include/bolt/Core/BinaryContext.h
@@ -180,34 +180,6 @@ struct JournalingStreams {
 Error createNonFatalBOLTError(const Twine &S);
 Error createFatalBOLTError(const Twine &S);
 
-/// 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};
-};
-
 class BinaryContext {
   BinaryContext() = delete;
 
@@ -698,8 +670,6 @@ class BinaryContext {
   /// Indicates if the binary is Linux kernel.
   bool IsLinuxKernel{false};
 
-  LKVersion LinuxKernelVersion;
-
   /// Indicates if relocations are available for usage.
   bool HasRelocations{false};
 
diff --git a/bolt/include/bolt/Core/BinaryData.h b/bolt/include/bolt/Core/BinaryData.h
index 6a773c4cb70678..4ab628030ff0d2 100644
--- a/bolt/include/bolt/Core/BinaryData.h
+++ b/bolt/include/bolt/Core/BinaryData.h
@@ -169,6 +169,11 @@ class BinaryData {
     return Parent && (Parent == BD || Parent->isAncestorOf(BD));
   }
 
+  void updateSize(uint64_t N) {
+    if (N > Size)
+      Size = N;
+  }
+
   void setIsMoveable(bool Flag) { IsMoveable = Flag; }
   void setSection(BinarySection &NewSection);
   void setOutputSection(BinarySection &NewSection) {
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index ac96b836ed5796..8ff8254f1eb140 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -1076,6 +1076,7 @@ MCSymbol *BinaryContext::registerNameAtAddress(StringRef Name, uint64_t Address,
     BD = GAI->second;
     if (!BD->hasName(Name)) {
       GlobalSymbols[Name] = BD;
+      BD->updateSize(Size);
       BD->Symbols.push_back(Symbol);
     }
   }
diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
index 03b414b71caca7..e233217b9e66fa 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 {
@@ -124,6 +154,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const ORCState &E) {
 namespace {
 
 class LinuxKernelRewriter final : public MetadataRewriter {
+  LKVersion LinuxKernelVersion;
+
   /// Information required for updating metadata referencing an instruction.
   struct InstructionFixup {
     BinarySection &Section; // Section referencing the instruction.
@@ -225,6 +257,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();
 
@@ -290,6 +324,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
       : MetadataRewriter("linux-kernel-rewriter", BC) {}
 
   Error preCFGInitializer() override {
+    if (Error E = detectLinuxKernelVersion())
+      return E;
+
     processLKSections();
 
     if (Error E = processSMPLocks())
@@ -370,6 +407,28 @@ class LinuxKernelRewriter final : public MetadataRewriter {
   }
 };
 
+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.size() > 5 ? 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);
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index 85a753b3cb0554..76e1f0156f828d 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -61,7 +61,6 @@
 #include <fstream>
 #include <memory>
 #include <optional>
-#include <regex>
 #include <system_error>
 
 #undef  DEBUG_TYPE
@@ -1031,25 +1030,6 @@ 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 = LKVersion(Major, Minor, Rev);
-        BC->outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str();
-      }
-    }
-
     if (!Section->isText()) {
       assert(SymbolType != SymbolRef::ST_Function &&
              "unexpected function inside non-code section");
@@ -1225,9 +1205,6 @@ void RewriteInstance::discoverFileObjects() {
     PreviousFunction = BF;
   }
 
-  if (BC->IsLinuxKernel && !BC->LinuxKernelVersion.Major)
-    BC->errs() << "BOLT-WARNING: Linux kernel version is unknown\n";
-
   // Read dynamic relocation first as their presence affects the way we process
   // static relocations. E.g. we will ignore a static relocation at an address
   // that is a subject to dynamic relocation processing.
diff --git a/bolt/test/X86/linux-alt-instruction.s b/bolt/test/X86/linux-alt-instruction.s
index fe3abbfc2b4c93..83d2cd0634d085 100644
--- a/bolt/test/X86/linux-alt-instruction.s
+++ b/bolt/test/X86/linux-alt-instruction.s
@@ -142,6 +142,15 @@ _start:
   .section .orc_unwind_ip
   .long .L0 + 2 - .
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-bug-table.s b/bolt/test/X86/linux-bug-table.s
index 07a4729ade7374..2965daab2b2656 100644
--- a/bolt/test/X86/linux-bug-table.s
+++ b/bolt/test/X86/linux-bug-table.s
@@ -56,6 +56,15 @@ _start:
   .long .L1 - .  # instruction
   .org 2b + 12
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-exceptions.s b/bolt/test/X86/linux-exceptions.s
index 20b8c965f853a9..b0e7641af1cd9c 100644
--- a/bolt/test/X86/linux-exceptions.s
+++ b/bolt/test/X86/linux-exceptions.s
@@ -59,6 +59,15 @@ foo:
   .long .LF0 - . # fixup
   .long 0        # data
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-orc.s b/bolt/test/X86/linux-orc.s
index 1b0e681b1dbf96..133b0df690e623 100644
--- a/bolt/test/X86/linux-orc.s
+++ b/bolt/test/X86/linux-orc.s
@@ -157,6 +157,15 @@ bar:
   .section .orc_unwind_ip
   .long .L4 - .
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-parainstructions.s b/bolt/test/X86/linux-parainstructions.s
index 07fca6bbedafab..facfcb168b1662 100644
--- a/bolt/test/X86/linux-parainstructions.s
+++ b/bolt/test/X86/linux-parainstructions.s
@@ -49,6 +49,15 @@ _start:
   .byte 1        # type
   .byte 7        # length
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-pci-fixup.s b/bolt/test/X86/linux-pci-fixup.s
index 42504c108d339c..d8df91a4e9bcd1 100644
--- a/bolt/test/X86/linux-pci-fixup.s
+++ b/bolt/test/X86/linux-pci-fixup.s
@@ -36,6 +36,15 @@ _start:
   .long 0x0         # class shift
   .long .L0 - .     # fixup
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-smp-locks.s b/bolt/test/X86/linux-smp-locks.s
index 50d9e632b11720..2fc136fd78cda5 100644
--- a/bolt/test/X86/linux-smp-locks.s
+++ b/bolt/test/X86/linux-smp-locks.s
@@ -35,6 +35,15 @@ _start:
   .long .L0 - .
   .long .L1 - .
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-static-calls.s b/bolt/test/X86/linux-static-calls.s
index ce90f4bb79c094..758e1395d88462 100644
--- a/bolt/test/X86/linux-static-calls.s
+++ b/bolt/test/X86/linux-static-calls.s
@@ -54,6 +54,15 @@ __start_static_call_sites:
   .type __stop_static_call_sites, %object
 __stop_static_call_sites:
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type linux_banner, @object
+linux_banner:
+  .string "Linux version 6.6.61\n"
+  .size linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-static-keys.s b/bolt/test/X86/linux-static-keys.s
index 0bd17a375d8824..d3ca74c1ec2518 100644
--- a/bolt/test/X86/linux-static-keys.s
+++ b/bolt/test/X86/linux-static-keys.s
@@ -79,6 +79,15 @@ __start___jump_table:
   .type __stop___jump_table, %object
 __stop___jump_table:
 
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+  .string  "Linux version 6.6.61\n"
+  .size  linux_banner, . - linux_banner
+
 ## Fake Linux Kernel sections.
   .section __ksymtab,"a", at progbits
   .section __ksymtab_gpl,"a", at progbits
diff --git a/bolt/test/X86/linux-version.s b/bolt/test/X86/linux-version.s
deleted file mode 100644
index 079910be931cdb..00000000000000
--- a/bolt/test/X86/linux-version.s
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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
diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp
index d8400d9b18174f..9819a8c2b777b7 100644
--- a/bolt/unittests/Core/BinaryContext.cpp
+++ b/bolt/unittests/Core/BinaryContext.cpp
@@ -218,17 +218,3 @@ TEST_P(BinaryContextTester, BaseAddressSegmentsSmallerThanAlignment) {
   ASSERT_TRUE(BaseAddress.has_value());
   ASSERT_EQ(*BaseAddress, 0xaaaaaaaa0000ULL);
 }
-
-TEST(BinaryContextTester, LKVersion) {
-  LKVersion V1;
-  LKVersion V2(5, 9, 15);
-  LKVersion V3(6, 12, 1);
-
-  V1 = V3;
-  ASSERT_TRUE(V1 == V3);
-  ASSERT_TRUE(V2 != V3);
-  ASSERT_TRUE(V2 < V3);
-  ASSERT_TRUE(V2 <= V3);
-  ASSERT_TRUE(V3 > V2);
-  ASSERT_TRUE(V3 >= V2);
-}

>From 2268ec6dcf7bbaba9075a4b07fa06393d664502f Mon Sep 17 00:00:00 2001
From: fengleizZZ <zhangfenglei at huawei.com>
Date: Sat, 14 Dec 2024 00:10:20 +0800
Subject: [PATCH 4/4] [BOLT] Detect Linux kernel version if the binary is a
 Linux kernel

Add tests
---
 bolt/lib/Rewrite/LinuxKernelRewriter.cpp |  2 +-
 bolt/test/X86/linux-version.S            | 54 ++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 bolt/test/X86/linux-version.S

diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
index e233217b9e66fa..aeb82ef3558d68 100644
--- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
+++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp
@@ -418,7 +418,7 @@ Error LinuxKernelRewriter::detectLinuxKernelVersion() {
     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.size() > 5 ? std::stoi(Match[5].str()) : 0;
+      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";
diff --git a/bolt/test/X86/linux-version.S b/bolt/test/X86/linux-version.S
new file mode 100644
index 00000000000000..d1d8c3f2b73f13
--- /dev/null
+++ b/bolt/test/X86/linux-version.S
@@ -0,0 +1,54 @@
+# REQUIRES: system-linux
+
+## Check that BOLT correctly detects the Linux kernel version
+
+# RUN: %clang -DA -target x86_64-unknown-unknown \
+# RUN:   %cflags -nostdlib %s -o %t.exe \
+# RUN:   -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr ;\
+# RUN: llvm-bolt %t.exe -o %t.out 2>&1 | FileCheck --check-prefix=CHECK-A %s
+
+# CHECK-A: BOLT-INFO: Linux kernel version is 6.6.61
+
+# RUN: %clang -DB -target x86_64-unknown-unknown \
+# RUN:   %cflags -nostdlib %s -o %t.exe \
+# RUN:   -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr ;\
+# RUN: llvm-bolt %t.exe -o %t.out 2>&1 | FileCheck --check-prefix=CHECK-B %s
+
+# CHECK-B: BOLT-INFO: Linux kernel version is 6.6.50
+
+# RUN: %clang -DC -target x86_64-unknown-unknown \
+# RUN:   %cflags -nostdlib %s -o %t.exe \
+# RUN:   -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr ;\
+# RUN: llvm-bolt %t.exe -o %t.out 2>&1 | FileCheck --check-prefix=CHECK-C %s
+
+# CHECK-C: BOLT-INFO: Linux kernel version is 6.6
+
+  .text
+  .globl foo
+  .type foo, %function
+foo:
+  ret
+  .size foo, .-foo
+
+## Linux kernel version
+  .rodata
+  .align 16
+  .globl linux_banner
+  .type  linux_banner, @object
+linux_banner:
+
+#ifdef A
+  .string  "Linux version 6.6.61\n"
+#endif
+#ifdef B
+  .string  "Linux version 6.6.50-rc4\n"
+#endif
+#ifdef C
+  .string  "Linux version 6.6\n"
+#endif
+
+  .size  linux_banner, . - linux_banner
+
+## Fake Linux Kernel sections.
+  .section __ksymtab,"a", at progbits
+  .section __ksymtab_gpl,"a", at progbits



More information about the llvm-commits mailing list