From 69554a819ef782199d1b25039e484b174a48cdaf Mon Sep 17 00:00:00 2001 From: fengleizZZ Date: Sun, 8 Dec 2024 02:37:49 +0800 Subject: [PATCH 1/6] [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 115e59ca0697e..052a145efe4a4 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 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 76e1f0156f828..48617dc8ea594 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #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 0000000000000..079910be931cd --- /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",@progbits + .section __ksymtab_gpl,"a",@progbits From 6b931b37b0a0b40828c018f2e095b25d778c4b9d Mon Sep 17 00:00:00 2001 From: fengleizZZ Date: Mon, 9 Dec 2024 00:27:31 +0800 Subject: [PATCH 2/6] [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 052a145efe4a4..7d49dd003ca02 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 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 48617dc8ea594..85a753b3cb055 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 9819a8c2b777b..d8400d9b18174 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 Date: Mon, 9 Dec 2024 23:23:50 +0800 Subject: [PATCH 3/6] [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 7d49dd003ca02..115e59ca0697e 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 6a773c4cb7067..4ab628030ff0d 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 ac96b836ed579..8ff8254f1eb14 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 03b414b71caca..e233217b9e66f 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 #define DEBUG_TYPE "bolt-linux" @@ -89,6 +91,34 @@ static cl::opt } // 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 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 85a753b3cb055..76e1f0156f828 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -61,7 +61,6 @@ #include #include #include -#include #include #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 fe3abbfc2b4c9..83d2cd0634d08 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-bug-table.s b/bolt/test/X86/linux-bug-table.s index 07a4729ade737..2965daab2b265 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-exceptions.s b/bolt/test/X86/linux-exceptions.s index 20b8c965f853a..b0e7641af1cd9 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-orc.s b/bolt/test/X86/linux-orc.s index 1b0e681b1dbf9..133b0df690e62 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-parainstructions.s b/bolt/test/X86/linux-parainstructions.s index 07fca6bbedafa..facfcb168b166 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-pci-fixup.s b/bolt/test/X86/linux-pci-fixup.s index 42504c108d339..d8df91a4e9bcd 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-smp-locks.s b/bolt/test/X86/linux-smp-locks.s index 50d9e632b1172..2fc136fd78cda 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-static-calls.s b/bolt/test/X86/linux-static-calls.s index ce90f4bb79c09..758e1395d8846 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-static-keys.s b/bolt/test/X86/linux-static-keys.s index 0bd17a375d882..d3ca74c1ec251 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",@progbits .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-version.s b/bolt/test/X86/linux-version.s deleted file mode 100644 index 079910be931cd..0000000000000 --- 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",@progbits - .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp index d8400d9b18174..9819a8c2b777b 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 Date: Sat, 14 Dec 2024 00:10:20 +0800 Subject: [PATCH 4/6] [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 e233217b9e66f..aeb82ef3558d6 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 0000000000000..d1d8c3f2b73f1 --- /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",@progbits + .section __ksymtab_gpl,"a",@progbits From e932882c98bd73e37f8409cd2878bf379f39904d Mon Sep 17 00:00:00 2001 From: Franklin Date: Sat, 14 Dec 2024 12:14:31 +0800 Subject: [PATCH 5/6] [BOLT] Detect Linux kernel version if the binary is a Linux kernel Fix linux-version.S --- bolt/test/X86/linux-version.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bolt/test/X86/linux-version.S b/bolt/test/X86/linux-version.S index d1d8c3f2b73f1..9a0b5c7f11c0c 100644 --- a/bolt/test/X86/linux-version.S +++ b/bolt/test/X86/linux-version.S @@ -4,21 +4,21 @@ # 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: -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: -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: -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 From 035668eafad278ea50700efa16e6daca6700300a Mon Sep 17 00:00:00 2001 From: Franklin Date: Tue, 17 Dec 2024 14:28:33 +0800 Subject: [PATCH 6/6] [BOLT] Detect Linux kernel version if the binary is a Linux kernel --- bolt/test/X86/linux-version.S | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bolt/test/X86/linux-version.S b/bolt/test/X86/linux-version.S index 9a0b5c7f11c0c..e680d0d64a21f 100644 --- a/bolt/test/X86/linux-version.S +++ b/bolt/test/X86/linux-version.S @@ -7,22 +7,16 @@ # 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 @@ -40,12 +34,17 @@ linux_banner: #ifdef A .string "Linux version 6.6.61\n" #endif +# CHECK-A: BOLT-INFO: Linux kernel version is 6.6.61 + #ifdef B .string "Linux version 6.6.50-rc4\n" #endif +# CHECK-B: BOLT-INFO: Linux kernel version is 6.6.50 + #ifdef C .string "Linux version 6.6\n" #endif +# CHECK-C: BOLT-INFO: Linux kernel version is 6.6 .size linux_banner, . - linux_banner