Skip to content

Commit bb683eb

Browse files
committed
[BOLT] Detect Linux kernel version if the binary is a Linux kernel
Move LinuxKernelVersion to LinuxKernelRewriter
1 parent 6b931b3 commit bb683eb

16 files changed

+146
-97
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -180,34 +180,6 @@ struct JournalingStreams {
180180
Error createNonFatalBOLTError(const Twine &S);
181181
Error createFatalBOLTError(const Twine &S);
182182

183-
/// Linux kernel version
184-
struct LKVersion {
185-
LKVersion() {}
186-
LKVersion(unsigned Major, unsigned Minor, unsigned Rev)
187-
: Major(Major), Minor(Minor), Rev(Rev) {}
188-
189-
bool operator<(const LKVersion &Other) const {
190-
return std::make_tuple(Major, Minor, Rev) <
191-
std::make_tuple(Other.Major, Other.Minor, Other.Rev);
192-
}
193-
194-
bool operator>(const LKVersion &Other) const { return Other < *this; }
195-
196-
bool operator<=(const LKVersion &Other) const { return !(*this > Other); }
197-
198-
bool operator>=(const LKVersion &Other) const { return !(*this < Other); }
199-
200-
bool operator==(const LKVersion &Other) const {
201-
return Major == Other.Major && Minor == Other.Minor && Rev == Other.Rev;
202-
}
203-
204-
bool operator!=(const LKVersion &Other) const { return !(*this == Other); }
205-
206-
unsigned Major{0};
207-
unsigned Minor{0};
208-
unsigned Rev{0};
209-
};
210-
211183
class BinaryContext {
212184
BinaryContext() = delete;
213185

@@ -698,8 +670,6 @@ class BinaryContext {
698670
/// Indicates if the binary is Linux kernel.
699671
bool IsLinuxKernel{false};
700672

701-
LKVersion LinuxKernelVersion;
702-
703673
/// Indicates if relocations are available for usage.
704674
bool HasRelocations{false};
705675

bolt/include/bolt/Core/BinaryData.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ class BinaryData {
169169
return Parent && (Parent == BD || Parent->isAncestorOf(BD));
170170
}
171171

172+
void updateSize(uint64_t N) {
173+
if (N > Size)
174+
Size = N;
175+
}
176+
172177
void setIsMoveable(bool Flag) { IsMoveable = Flag; }
173178
void setSection(BinarySection &NewSection);
174179
void setOutputSection(BinarySection &NewSection) {

bolt/lib/Core/BinaryContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,7 @@ MCSymbol *BinaryContext::registerNameAtAddress(StringRef Name, uint64_t Address,
10761076
BD = GAI->second;
10771077
if (!BD->hasName(Name)) {
10781078
GlobalSymbols[Name] = BD;
1079+
BD->updateSize(Size);
10791080
BD->Symbols.push_back(Symbol);
10801081
}
10811082
}

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "llvm/Support/CommandLine.h"
2222
#include "llvm/Support/Debug.h"
2323
#include "llvm/Support/Errc.h"
24+
#include "llvm/Support/ErrorOr.h"
25+
#include <regex>
2426

2527
#define DEBUG_TYPE "bolt-linux"
2628

@@ -89,6 +91,34 @@ static cl::opt<bool>
8991

9092
} // namespace opts
9193

94+
/// Linux kernel version
95+
struct LKVersion {
96+
LKVersion() {}
97+
LKVersion(unsigned Major, unsigned Minor, unsigned Rev)
98+
: Major(Major), Minor(Minor), Rev(Rev) {}
99+
100+
bool operator<(const LKVersion &Other) const {
101+
return std::make_tuple(Major, Minor, Rev) <
102+
std::make_tuple(Other.Major, Other.Minor, Other.Rev);
103+
}
104+
105+
bool operator>(const LKVersion &Other) const { return Other < *this; }
106+
107+
bool operator<=(const LKVersion &Other) const { return !(*this > Other); }
108+
109+
bool operator>=(const LKVersion &Other) const { return !(*this < Other); }
110+
111+
bool operator==(const LKVersion &Other) const {
112+
return Major == Other.Major && Minor == Other.Minor && Rev == Other.Rev;
113+
}
114+
115+
bool operator!=(const LKVersion &Other) const { return !(*this == Other); }
116+
117+
unsigned Major{0};
118+
unsigned Minor{0};
119+
unsigned Rev{0};
120+
};
121+
92122
/// Linux Kernel supports stack unwinding using ORC (oops rewind capability).
93123
/// ORC state at every IP can be described by the following data structure.
94124
struct ORCState {
@@ -124,6 +154,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const ORCState &E) {
124154
namespace {
125155

126156
class LinuxKernelRewriter final : public MetadataRewriter {
157+
LKVersion LinuxKernelVersion;
158+
127159
/// Information required for updating metadata referencing an instruction.
128160
struct InstructionFixup {
129161
BinarySection &Section; // Section referencing the instruction.
@@ -225,6 +257,8 @@ class LinuxKernelRewriter final : public MetadataRewriter {
225257
ErrorOr<BinarySection &> PCIFixupSection = std::errc::bad_address;
226258
static constexpr size_t PCI_FIXUP_ENTRY_SIZE = 16;
227259

260+
Error detectLinuxKernelVersion();
261+
228262
/// Process linux kernel special sections and their relocations.
229263
void processLKSections();
230264

@@ -290,6 +324,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
290324
: MetadataRewriter("linux-kernel-rewriter", BC) {}
291325

292326
Error preCFGInitializer() override {
327+
if (Error E = detectLinuxKernelVersion())
328+
return E;
329+
293330
processLKSections();
294331

295332
if (Error E = processSMPLocks())
@@ -370,6 +407,28 @@ class LinuxKernelRewriter final : public MetadataRewriter {
370407
}
371408
};
372409

410+
Error LinuxKernelRewriter::detectLinuxKernelVersion() {
411+
if (BinaryData *BD = BC.getBinaryDataByName("linux_banner")) {
412+
const BinarySection &Section = BD->getSection();
413+
const std::string S =
414+
Section.getContents().substr(BD->getOffset(), BD->getSize()).str();
415+
416+
const std::regex Re(R"---(Linux version ((\d+)\.(\d+)(\.(\d+))?))---");
417+
std::smatch Match;
418+
if (std::regex_search(S, Match, Re)) {
419+
const unsigned Major = std::stoi(Match[2].str());
420+
const unsigned Minor = std::stoi(Match[3].str());
421+
const unsigned Rev = Match.size() > 5 ? std::stoi(Match[5].str()) : 0;
422+
LinuxKernelVersion = LKVersion(Major, Minor, Rev);
423+
BC.outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str()
424+
<< "\n";
425+
return Error::success();
426+
}
427+
}
428+
return createStringError(errc::executable_format_error,
429+
"Linux kernel version is unknown");
430+
}
431+
373432
void LinuxKernelRewriter::processLKSections() {
374433
processLKKSymtab();
375434
processLKKSymtab(true);

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
#include <fstream>
6262
#include <memory>
6363
#include <optional>
64-
#include <regex>
6564
#include <system_error>
6665

6766
#undef DEBUG_TYPE
@@ -1031,25 +1030,6 @@ void RewriteInstance::discoverFileObjects() {
10311030
continue;
10321031
}
10331032

1034-
if (BC->IsLinuxKernel && SymName == "linux_banner") {
1035-
const StringRef SectionContents =
1036-
cantFail(Section->getContents(), "can not get section contents");
1037-
const std::string S =
1038-
SectionContents
1039-
.substr(SymbolAddress - Section->getAddress(), SymbolSize)
1040-
.str();
1041-
1042-
const std::regex Re(R"---(Linux version ((\d+)\.(\d+)(\.(\d+))?))---");
1043-
std::smatch Match;
1044-
if (std::regex_search(S, Match, Re)) {
1045-
unsigned Major = std::stoi(Match[2].str());
1046-
unsigned Minor = std::stoi(Match[3].str());
1047-
unsigned Rev = Match.size() > 5 ? std::stoi(Match[5].str()) : 0;
1048-
BC->LinuxKernelVersion = LKVersion(Major, Minor, Rev);
1049-
BC->outs() << "BOLT-INFO: Linux kernel version is " << Match[1].str();
1050-
}
1051-
}
1052-
10531033
if (!Section->isText()) {
10541034
assert(SymbolType != SymbolRef::ST_Function &&
10551035
"unexpected function inside non-code section");
@@ -1225,9 +1205,6 @@ void RewriteInstance::discoverFileObjects() {
12251205
PreviousFunction = BF;
12261206
}
12271207

1228-
if (BC->IsLinuxKernel && !BC->LinuxKernelVersion.Major)
1229-
BC->errs() << "BOLT-WARNING: Linux kernel version is unknown\n";
1230-
12311208
// Read dynamic relocation first as their presence affects the way we process
12321209
// static relocations. E.g. we will ignore a static relocation at an address
12331210
// that is a subject to dynamic relocation processing.

bolt/test/X86/linux-alt-instruction.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@ _start:
142142
.section .orc_unwind_ip
143143
.long .L0 + 2 - .
144144

145+
## Linux kernel version
146+
.rodata
147+
.align 16
148+
.globl linux_banner
149+
.type linux_banner, @object
150+
linux_banner:
151+
.string "Linux version 6.6.61\n"
152+
.size linux_banner, . - linux_banner
153+
145154
## Fake Linux Kernel sections.
146155
.section __ksymtab,"a",@progbits
147156
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-bug-table.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ _start:
5656
.long .L1 - . # instruction
5757
.org 2b + 12
5858

59+
## Linux kernel version
60+
.rodata
61+
.align 16
62+
.globl linux_banner
63+
.type linux_banner, @object
64+
linux_banner:
65+
.string "Linux version 6.6.61\n"
66+
.size linux_banner, . - linux_banner
67+
5968
## Fake Linux Kernel sections.
6069
.section __ksymtab,"a",@progbits
6170
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-exceptions.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ foo:
5959
.long .LF0 - . # fixup
6060
.long 0 # data
6161

62+
## Linux kernel version
63+
.rodata
64+
.align 16
65+
.globl linux_banner
66+
.type linux_banner, @object
67+
linux_banner:
68+
.string "Linux version 6.6.61\n"
69+
.size linux_banner, . - linux_banner
70+
6271
## Fake Linux Kernel sections.
6372
.section __ksymtab,"a",@progbits
6473
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-orc.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,15 @@ bar:
157157
.section .orc_unwind_ip
158158
.long .L4 - .
159159

160+
## Linux kernel version
161+
.rodata
162+
.align 16
163+
.globl linux_banner
164+
.type linux_banner, @object
165+
linux_banner:
166+
.string "Linux version 6.6.61\n"
167+
.size linux_banner, . - linux_banner
168+
160169
## Fake Linux Kernel sections.
161170
.section __ksymtab,"a",@progbits
162171
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-parainstructions.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ _start:
4949
.byte 1 # type
5050
.byte 7 # length
5151

52+
## Linux kernel version
53+
.rodata
54+
.align 16
55+
.globl linux_banner
56+
.type linux_banner, @object
57+
linux_banner:
58+
.string "Linux version 6.6.61\n"
59+
.size linux_banner, . - linux_banner
60+
5261
## Fake Linux Kernel sections.
5362
.section __ksymtab,"a",@progbits
5463
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-pci-fixup.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ _start:
3636
.long 0x0 # class shift
3737
.long .L0 - . # fixup
3838

39+
## Linux kernel version
40+
.rodata
41+
.align 16
42+
.globl linux_banner
43+
.type linux_banner, @object
44+
linux_banner:
45+
.string "Linux version 6.6.61\n"
46+
.size linux_banner, . - linux_banner
47+
3948
## Fake Linux Kernel sections.
4049
.section __ksymtab,"a",@progbits
4150
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-smp-locks.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ _start:
3535
.long .L0 - .
3636
.long .L1 - .
3737

38+
## Linux kernel version
39+
.rodata
40+
.align 16
41+
.globl linux_banner
42+
.type linux_banner, @object
43+
linux_banner:
44+
.string "Linux version 6.6.61\n"
45+
.size linux_banner, . - linux_banner
46+
3847
## Fake Linux Kernel sections.
3948
.section __ksymtab,"a",@progbits
4049
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-static-calls.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ __start_static_call_sites:
5454
.type __stop_static_call_sites, %object
5555
__stop_static_call_sites:
5656

57+
## Linux kernel version
58+
.rodata
59+
.align 16
60+
.globl linux_banner
61+
.type linux_banner, @object
62+
linux_banner:
63+
.string "Linux version 6.6.61\n"
64+
.size linux_banner, . - linux_banner
65+
5766
## Fake Linux Kernel sections.
5867
.section __ksymtab,"a",@progbits
5968
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-static-keys.s

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,15 @@ __start___jump_table:
7979
.type __stop___jump_table, %object
8080
__stop___jump_table:
8181

82+
## Linux kernel version
83+
.rodata
84+
.align 16
85+
.globl linux_banner
86+
.type linux_banner, @object
87+
linux_banner:
88+
.string "Linux version 6.6.61\n"
89+
.size linux_banner, . - linux_banner
90+
8291
## Fake Linux Kernel sections.
8392
.section __ksymtab,"a",@progbits
8493
.section __ksymtab_gpl,"a",@progbits

bolt/test/X86/linux-version.s

Lines changed: 0 additions & 30 deletions
This file was deleted.

0 commit comments

Comments
 (0)