Skip to content

Commit b8d3efa

Browse files
authored
[BOLT][Linux] Fix linux_banner lookup (#144962)
While detecting the Linux kernel version, look for `linux_banner` symbol with local visibility if the global one was not found. Fixes #144847
1 parent 6997465 commit b8d3efa

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -432,25 +432,33 @@ class LinuxKernelRewriter final : public MetadataRewriter {
432432
};
433433

434434
Error LinuxKernelRewriter::detectLinuxKernelVersion() {
435-
if (BinaryData *BD = BC.getBinaryDataByName("linux_banner")) {
436-
const BinarySection &Section = BD->getSection();
437-
const std::string S =
438-
Section.getContents().substr(BD->getOffset(), BD->getSize()).str();
439-
440-
const std::regex Re(R"---(Linux version ((\d+)\.(\d+)(\.(\d+))?))---");
441-
std::smatch Match;
442-
if (std::regex_search(S, Match, Re)) {
443-
const unsigned Major = std::stoi(Match[2].str());
444-
const unsigned Minor = std::stoi(Match[3].str());
445-
const unsigned Rev = Match[5].matched ? std::stoi(Match[5].str()) : 0;
446-
LinuxKernelVersion = LKVersion(Major, Minor, Rev);
447-
BC.outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str()
448-
<< "\n";
449-
return Error::success();
450-
}
435+
// Check for global and local linux_banner symbol.
436+
BinaryData *BD = BC.getBinaryDataByName("linux_banner");
437+
if (!BD)
438+
BD = BC.getBinaryDataByName("linux_banner/1");
439+
440+
if (!BD)
441+
return createStringError(errc::executable_format_error,
442+
"unable to locate linux_banner");
443+
444+
const BinarySection &Section = BD->getSection();
445+
const std::string S =
446+
Section.getContents().substr(BD->getOffset(), BD->getSize()).str();
447+
448+
const std::regex Re(R"---(Linux version ((\d+)\.(\d+)(\.(\d+))?))---");
449+
std::smatch Match;
450+
if (std::regex_search(S, Match, Re)) {
451+
const unsigned Major = std::stoi(Match[2].str());
452+
const unsigned Minor = std::stoi(Match[3].str());
453+
const unsigned Rev = Match[5].matched ? std::stoi(Match[5].str()) : 0;
454+
LinuxKernelVersion = LKVersion(Major, Minor, Rev);
455+
BC.outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str()
456+
<< "\n";
457+
return Error::success();
451458
}
459+
452460
return createStringError(errc::executable_format_error,
453-
"Linux kernel version is unknown");
461+
"Linux kernel version is unknown: " + S);
454462
}
455463

456464
void LinuxKernelRewriter::processLKSections() {

bolt/test/X86/linux-version.S

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr
1818
# RUN: llvm-bolt %t.exe -o %t.out 2>&1 | FileCheck --check-prefix=CHECK-C %s
1919

20+
# RUN: %clang -DD -target x86_64-unknown-unknown \
21+
# RUN: %cflags -nostdlib %s -o %t.exe \
22+
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr
23+
# RUN: llvm-bolt %t.exe -o %t.out 2>&1 | FileCheck --check-prefix=CHECK-D %s
24+
2025
.text
2126
.globl foo
2227
.type foo, %function
@@ -46,6 +51,12 @@ linux_banner:
4651
#endif
4752
# CHECK-C: BOLT-INFO: Linux kernel version is 6.6
4853

54+
#ifdef D
55+
.hidden linux_banner
56+
.string "Linux version 6.6.15.2-2-xxx\n"
57+
#endif
58+
# CHECK-D: BOLT-INFO: Linux kernel version is 6.6
59+
4960
.size linux_banner, . - linux_banner
5061

5162
## Fake Linux Kernel sections.

0 commit comments

Comments
 (0)