Skip to content

Commit fa0225b

Browse files
author
git apple-llvm automerger
committed
Merge commit 'd16b21b17d13' from llvm.org/main into next
2 parents d716b84 + d16b21b commit fa0225b

File tree

4 files changed

+88
-8
lines changed

4 files changed

+88
-8
lines changed

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,10 @@ class BinaryFunction {
930930
return const_cast<BinaryFunction *>(this)->getInstructionAtOffset(Offset);
931931
}
932932

933+
/// When the function is in disassembled state, return an instruction that
934+
/// contains the \p Offset.
935+
MCInst *getInstructionContainingOffset(uint64_t Offset);
936+
933937
std::optional<MCInst> disassembleInstructionAtOffset(uint64_t Offset) const;
934938

935939
/// Return offset for the first instruction. If there is data at the

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4472,6 +4472,18 @@ MCInst *BinaryFunction::getInstructionAtOffset(uint64_t Offset) {
44724472
}
44734473
}
44744474

4475+
MCInst *BinaryFunction::getInstructionContainingOffset(uint64_t Offset) {
4476+
assert(CurrentState == State::Disassembled && "Wrong function state");
4477+
4478+
if (Offset > Size)
4479+
return nullptr;
4480+
4481+
auto II = Instructions.upper_bound(Offset);
4482+
assert(II != Instructions.begin() && "First instruction not at offset 0");
4483+
--II;
4484+
return &II->second;
4485+
}
4486+
44754487
void BinaryFunction::printLoopInfo(raw_ostream &OS) const {
44764488
if (!opts::shouldPrint(*this))
44774489
return;

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,6 @@ class LinuxKernelRewriter final : public MetadataRewriter {
295295
if (Error E = processSMPLocks())
296296
return E;
297297

298-
if (Error E = readORCTables())
299-
return E;
300-
301298
if (Error E = readStaticCalls())
302299
return E;
303300

@@ -313,6 +310,11 @@ class LinuxKernelRewriter final : public MetadataRewriter {
313310
if (Error E = readAltInstructions())
314311
return E;
315312

313+
// Some ORC entries could be linked to alternative instruction
314+
// sequences. Hence, we read ORC after .altinstructions.
315+
if (Error E = readORCTables())
316+
return E;
317+
316318
if (Error E = readPCIFixupTable())
317319
return E;
318320

@@ -563,11 +565,28 @@ Error LinuxKernelRewriter::readORCTables() {
563565
if (!BF->hasInstructions())
564566
continue;
565567

566-
MCInst *Inst = BF->getInstructionAtOffset(IP - BF->getAddress());
567-
if (!Inst)
568+
const uint64_t Offset = IP - BF->getAddress();
569+
MCInst *Inst = BF->getInstructionAtOffset(Offset);
570+
if (!Inst) {
571+
// Check if there is an alternative instruction(s) at this IP. Multiple
572+
// alternative instructions can take a place of a single original
573+
// instruction and each alternative can have a separate ORC entry.
574+
// Since ORC table is shared between all alternative sequences, there's
575+
// a requirement that only one (out of many) sequences can have an
576+
// instruction from the ORC table to avoid ambiguities/conflicts.
577+
//
578+
// For now, we have limited support for alternatives. I.e. we still print
579+
// functions with them, but will not change the code in the output binary.
580+
// As such, we can ignore alternative ORC entries. They will be preserved
581+
// in the binary, but will not get printed in the instruction stream.
582+
Inst = BF->getInstructionContainingOffset(Offset);
583+
if (Inst || BC.MIB->hasAnnotation(*Inst, "AltInst"))
584+
continue;
585+
568586
return createStringError(
569587
errc::executable_format_error,
570588
"no instruction at address 0x%" PRIx64 " in .orc_unwind_ip", IP);
589+
}
571590

572591
// Some addresses will have two entries associated with them. The first
573592
// one being a "weak" section terminator. Since we ignore the terminator,
@@ -1440,7 +1459,7 @@ Error LinuxKernelRewriter::tryReadAltInstructions(uint32_t AltInstFeatureSize,
14401459
AltBF->setIgnored();
14411460
}
14421461

1443-
if (!BF || !BC.shouldEmit(*BF))
1462+
if (!BF || !BF->hasInstructions())
14441463
continue;
14451464

14461465
if (OrgInstAddress + OrgSize > BF->getAddress() + BF->getSize())

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

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
# RUN: llvm-bolt %t.exe --print-cfg -o %t.fs4.out | FileCheck %s
3939

4040
# CHECK: BOLT-INFO: Linux kernel binary detected
41-
# CHECK: BOLT-INFO: parsed 2 alternative instruction entries
41+
# CHECK: BOLT-INFO: parsed 3 alternative instruction entries
4242

4343
.text
4444
.globl _start
@@ -50,10 +50,12 @@ _start:
5050
# CHECK: rdtsc
5151
# CHECK-SAME: AltInst: 1
5252
# CHECK-SAME: AltInst2: 2
53+
# CHECK-SAME: AltInst3: 3
5354
nop
5455
# CHECK-NEXT: nop
5556
# CHECK-SAME: AltInst: 1
5657
# CHECK-SAME: AltInst2: 2
58+
# CHECK-SAME: AltInst3: 3
5759
nop
5860
nop
5961
.L1:
@@ -66,6 +68,9 @@ _start:
6668
rdtsc
6769
.A1:
6870
rdtscp
71+
.A2:
72+
pushf
73+
pop %rax
6974
.Ae:
7075

7176
## Alternative instruction info.
@@ -92,11 +97,51 @@ _start:
9297
.word 0x3b # feature flags
9398
.endif
9499
.byte .L1 - .L0 # org size
95-
.byte .Ae - .A1 # alt size
100+
.byte .A2 - .A1 # alt size
96101
.ifdef PADLEN
97102
.byte 0
98103
.endif
99104

105+
.long .L0 - . # org instruction
106+
.long .A2 - . # alt instruction
107+
.ifdef FEATURE_SIZE_4
108+
.long 0x110 # feature flags
109+
.else
110+
.word 0x110 # feature flags
111+
.endif
112+
.byte .L1 - .L0 # org size
113+
.byte .Ae - .A2 # alt size
114+
.ifdef PADLEN
115+
.byte 0
116+
.endif
117+
118+
## ORC unwind for "pushf; pop %rax" alternative sequence.
119+
.section .orc_unwind,"a",@progbits
120+
.align 4
121+
.section .orc_unwind_ip,"a",@progbits
122+
.align 4
123+
124+
.section .orc_unwind
125+
.2byte 8
126+
.2byte 0
127+
.2byte 0x205
128+
.section .orc_unwind_ip
129+
.long _start - .
130+
131+
.section .orc_unwind
132+
.2byte 16
133+
.2byte 0
134+
.2byte 0x205
135+
.section .orc_unwind_ip
136+
.long .L0 + 1 - .
137+
138+
.section .orc_unwind
139+
.2byte 8
140+
.2byte 0
141+
.2byte 0x205
142+
.section .orc_unwind_ip
143+
.long .L0 + 2 - .
144+
100145
## Fake Linux Kernel sections.
101146
.section __ksymtab,"a",@progbits
102147
.section __ksymtab_gpl,"a",@progbits

0 commit comments

Comments
 (0)