Skip to content

Commit ab31dbc

Browse files
Merge remote-tracking branch 'upstream/main' into aa/getline_precond
2 parents 19a4c0f + d3ec8c2 commit ab31dbc

File tree

1,466 files changed

+44095
-21681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,466 files changed

+44095
-21681
lines changed

.github/workflows/issue-release-workflow.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,5 @@ jobs:
6565
release-workflow \
6666
--branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \
6767
--issue-number ${{ github.event.issue.number }} \
68-
--requested-by ${{ github.event.issue.user.login }} \
68+
--requested-by ${{ (github.event.action == 'opened' && github.event.issue.user.login) || github.event.comment.user.login }} \
6969
auto

.github/workflows/release-binaries.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jobs:
3535
prepare:
3636
name: Prepare to build binaries
3737
runs-on: ubuntu-22.04
38+
if: github.repository == 'llvm/llvm-project'
3839
outputs:
3940
release-version: ${{ steps.vars.outputs.release-version }}
4041
flags: ${{ steps.vars.outputs.flags }}
@@ -47,11 +48,16 @@ jobs:
4748
- name: Checkout LLVM
4849
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
4950

51+
- name: Install Dependencies
52+
run: |
53+
pip install -r ./llvm/utils/git/requirements.txt
54+
5055
- name: Check Permissions
5156
env:
5257
GITHUB_TOKEN: ${{ github.token }}
58+
USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }}
5359
run: |
54-
./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} check-permissions
60+
./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} --user-token "$USER_TOKEN" check-permissions
5561
5662
- name: Collect Variables
5763
id: vars
@@ -85,6 +91,7 @@ jobs:
8591
name: "Fill Cache ${{ matrix.os }}"
8692
needs: prepare
8793
runs-on: ${{ matrix.os }}
94+
if: github.repository == 'llvm/llvm-project'
8895
strategy:
8996
matrix:
9097
os:
@@ -119,6 +126,7 @@ jobs:
119126
- prepare
120127
- fill-cache
121128
runs-on: ${{ matrix.target.runs-on }}
129+
if: github.repository == 'llvm/llvm-project'
122130
strategy:
123131
fail-fast: false
124132
matrix:

bolt/lib/Rewrite/LinuxKernelRewriter.cpp

Lines changed: 159 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ using namespace bolt;
2727

2828
namespace opts {
2929

30+
static cl::opt<bool>
31+
AltInstHasPadLen("alt-inst-has-padlen",
32+
cl::desc("specify that .altinstructions has padlen field"),
33+
cl::init(false), cl::Hidden, cl::cat(BoltCategory));
34+
35+
static cl::opt<uint32_t>
36+
AltInstFeatureSize("alt-inst-feature-size",
37+
cl::desc("size of feature field in .altinstructions"),
38+
cl::init(2), cl::Hidden, cl::cat(BoltCategory));
39+
40+
static cl::opt<bool>
41+
DumpAltInstructions("dump-alt-instructions",
42+
cl::desc("dump Linux alternative instructions info"),
43+
cl::init(false), cl::Hidden, cl::cat(BoltCategory));
44+
3045
static cl::opt<bool>
3146
DumpExceptions("dump-linux-exceptions",
3247
cl::desc("dump Linux kernel exception table"),
@@ -157,6 +172,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
157172
/// Alignment of paravirtual patch structures.
158173
static constexpr size_t PARA_PATCH_ALIGN = 8;
159174

175+
/// .altinstructions section.
176+
ErrorOr<BinarySection &> AltInstrSection = std::errc::bad_address;
177+
160178
/// Section containing Linux bug table.
161179
ErrorOr<BinarySection &> BugTableSection = std::errc::bad_address;
162180

@@ -205,6 +223,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
205223

206224
Error readBugTable();
207225

226+
/// Read alternative instruction info from .altinstructions.
227+
Error readAltInstructions();
228+
208229
/// Mark instructions referenced by kernel metadata.
209230
Error markInstructions();
210231

@@ -232,6 +253,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
232253
if (Error E = readBugTable())
233254
return E;
234255

256+
if (Error E = readAltInstructions())
257+
return E;
258+
235259
return Error::success();
236260
}
237261

@@ -476,7 +500,8 @@ Error LinuxKernelRewriter::readORCTables() {
476500
// Consume the status of the cursor.
477501
if (!IPCursor)
478502
return createStringError(errc::executable_format_error,
479-
"out of bounds while reading ORC IP table");
503+
"out of bounds while reading ORC IP table: %s",
504+
toString(IPCursor.takeError()).c_str());
480505

481506
if (IP < PrevIP && opts::Verbosity)
482507
BC.errs() << "BOLT-WARNING: out of order IP 0x" << Twine::utohexstr(IP)
@@ -498,7 +523,8 @@ Error LinuxKernelRewriter::readORCTables() {
498523
// Consume the status of the cursor.
499524
if (!ORCCursor)
500525
return createStringError(errc::executable_format_error,
501-
"out of bounds while reading ORC");
526+
"out of bounds while reading ORC: %s",
527+
toString(ORCCursor.takeError()).c_str());
502528

503529
if (Entry.ORC == NullORC)
504530
continue;
@@ -819,7 +845,8 @@ Error LinuxKernelRewriter::readStaticCalls() {
819845
// Consume the status of the cursor.
820846
if (!Cursor)
821847
return createStringError(errc::executable_format_error,
822-
"out of bounds while reading static calls");
848+
"out of bounds while reading static calls: %s",
849+
toString(Cursor.takeError()).c_str());
823850

824851
++EntryID;
825852

@@ -930,8 +957,10 @@ Error LinuxKernelRewriter::readExceptionTable() {
930957

931958
// Consume the status of the cursor.
932959
if (!Cursor)
933-
return createStringError(errc::executable_format_error,
934-
"out of bounds while reading exception table");
960+
return createStringError(
961+
errc::executable_format_error,
962+
"out of bounds while reading exception table: %s",
963+
toString(Cursor.takeError()).c_str());
935964

936965
++EntryID;
937966

@@ -1037,8 +1066,10 @@ Error LinuxKernelRewriter::readParaInstructions() {
10371066
const uint8_t Len = DE.getU8(Cursor);
10381067

10391068
if (!Cursor)
1040-
return createStringError(errc::executable_format_error,
1041-
"out of bounds while reading .parainstructions");
1069+
return createStringError(
1070+
errc::executable_format_error,
1071+
"out of bounds while reading .parainstructions: %s",
1072+
toString(Cursor.takeError()).c_str());
10421073

10431074
++EntryID;
10441075

@@ -1105,7 +1136,8 @@ Error LinuxKernelRewriter::readBugTable() {
11051136

11061137
if (!Cursor)
11071138
return createStringError(errc::executable_format_error,
1108-
"out of bounds while reading __bug_table");
1139+
"out of bounds while reading __bug_table: %s",
1140+
toString(Cursor.takeError()).c_str());
11091141

11101142
++EntryID;
11111143

@@ -1132,6 +1164,125 @@ Error LinuxKernelRewriter::readBugTable() {
11321164
return Error::success();
11331165
}
11341166

1167+
/// The kernel can replace certain instruction sequences depending on hardware
1168+
/// it is running on and features specified during boot time. The information
1169+
/// about alternative instruction sequences is stored in .altinstructions
1170+
/// section. The format of entries in this section is defined in
1171+
/// arch/x86/include/asm/alternative.h:
1172+
///
1173+
/// struct alt_instr {
1174+
/// s32 instr_offset;
1175+
/// s32 repl_offset;
1176+
/// uXX feature;
1177+
/// u8 instrlen;
1178+
/// u8 replacementlen;
1179+
/// u8 padlen; // present in older kernels
1180+
/// } __packed;
1181+
///
1182+
/// Note the structures is packed.
1183+
Error LinuxKernelRewriter::readAltInstructions() {
1184+
AltInstrSection = BC.getUniqueSectionByName(".altinstructions");
1185+
if (!AltInstrSection)
1186+
return Error::success();
1187+
1188+
const uint64_t Address = AltInstrSection->getAddress();
1189+
DataExtractor DE = DataExtractor(AltInstrSection->getContents(),
1190+
BC.AsmInfo->isLittleEndian(),
1191+
BC.AsmInfo->getCodePointerSize());
1192+
uint64_t EntryID = 0;
1193+
DataExtractor::Cursor Cursor(0);
1194+
while (Cursor && !DE.eof(Cursor)) {
1195+
const uint64_t OrgInstAddress =
1196+
Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
1197+
const uint64_t AltInstAddress =
1198+
Address + Cursor.tell() + (int32_t)DE.getU32(Cursor);
1199+
const uint64_t Feature = DE.getUnsigned(Cursor, opts::AltInstFeatureSize);
1200+
const uint8_t OrgSize = DE.getU8(Cursor);
1201+
const uint8_t AltSize = DE.getU8(Cursor);
1202+
1203+
// Older kernels may have the padlen field.
1204+
const uint8_t PadLen = opts::AltInstHasPadLen ? DE.getU8(Cursor) : 0;
1205+
1206+
if (!Cursor)
1207+
return createStringError(
1208+
errc::executable_format_error,
1209+
"out of bounds while reading .altinstructions: %s",
1210+
toString(Cursor.takeError()).c_str());
1211+
1212+
++EntryID;
1213+
1214+
if (opts::DumpAltInstructions) {
1215+
BC.outs() << "Alternative instruction entry: " << EntryID
1216+
<< "\n\tOrg: 0x" << Twine::utohexstr(OrgInstAddress)
1217+
<< "\n\tAlt: 0x" << Twine::utohexstr(AltInstAddress)
1218+
<< "\n\tFeature: 0x" << Twine::utohexstr(Feature)
1219+
<< "\n\tOrgSize: " << (int)OrgSize
1220+
<< "\n\tAltSize: " << (int)AltSize << '\n';
1221+
if (opts::AltInstHasPadLen)
1222+
BC.outs() << "\tPadLen: " << (int)PadLen << '\n';
1223+
}
1224+
1225+
if (AltSize > OrgSize)
1226+
return createStringError(errc::executable_format_error,
1227+
"error reading .altinstructions");
1228+
1229+
BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(OrgInstAddress);
1230+
if (!BF && opts::Verbosity) {
1231+
BC.outs() << "BOLT-INFO: no function matches address 0x"
1232+
<< Twine::utohexstr(OrgInstAddress)
1233+
<< " of instruction from .altinstructions\n";
1234+
}
1235+
1236+
BinaryFunction *AltBF =
1237+
BC.getBinaryFunctionContainingAddress(AltInstAddress);
1238+
if (AltBF && BC.shouldEmit(*AltBF)) {
1239+
BC.errs()
1240+
<< "BOLT-WARNING: alternative instruction sequence found in function "
1241+
<< *AltBF << '\n';
1242+
AltBF->setIgnored();
1243+
}
1244+
1245+
if (!BF || !BC.shouldEmit(*BF))
1246+
continue;
1247+
1248+
if (OrgInstAddress + OrgSize > BF->getAddress() + BF->getSize())
1249+
return createStringError(errc::executable_format_error,
1250+
"error reading .altinstructions");
1251+
1252+
MCInst *Inst =
1253+
BF->getInstructionAtOffset(OrgInstAddress - BF->getAddress());
1254+
if (!Inst)
1255+
return createStringError(errc::executable_format_error,
1256+
"no instruction at address 0x%" PRIx64
1257+
" referenced by .altinstructions entry %d",
1258+
OrgInstAddress, EntryID);
1259+
1260+
// There could be more than one alternative instruction sequences for the
1261+
// same original instruction. Annotate each alternative separately.
1262+
std::string AnnotationName = "AltInst";
1263+
unsigned N = 2;
1264+
while (BC.MIB->hasAnnotation(*Inst, AnnotationName))
1265+
AnnotationName = "AltInst" + std::to_string(N++);
1266+
1267+
BC.MIB->addAnnotation(*Inst, AnnotationName, EntryID);
1268+
1269+
// Annotate all instructions from the original sequence. Note that it's not
1270+
// the most efficient way to look for instructions in the address range,
1271+
// but since alternative instructions are uncommon, it will do for now.
1272+
for (uint32_t Offset = 1; Offset < OrgSize; ++Offset) {
1273+
Inst = BF->getInstructionAtOffset(OrgInstAddress + Offset -
1274+
BF->getAddress());
1275+
if (Inst)
1276+
BC.MIB->addAnnotation(*Inst, AnnotationName, EntryID);
1277+
}
1278+
}
1279+
1280+
BC.outs() << "BOLT-INFO: parsed " << EntryID
1281+
<< " alternative instruction entries\n";
1282+
1283+
return Error::success();
1284+
}
1285+
11351286
} // namespace
11361287

11371288
std::unique_ptr<MetadataRewriter>

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

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# REQUIRES: system-linux
2+
3+
## Check that BOLT correctly parses the Linux kernel .altinstructions section
4+
## and annotates alternative instructions.
5+
6+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
7+
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
8+
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie
9+
# RUN: llvm-bolt %t.exe --print-normalized --keep-nops -o %t.out \
10+
# RUN: --alt-inst-feature-size=2 | FileCheck %s
11+
12+
## Older kernels used to have padlen field in alt_instr. Check compatibility.
13+
14+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown --defsym PADLEN=1 \
15+
# RUN: %s -o %t.o
16+
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
17+
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie
18+
# RUN: llvm-bolt %t.exe --print-normalized --keep-nops --alt-inst-has-padlen \
19+
# RUN: -o %t.out | FileCheck %s
20+
21+
## Check with a larger size of "feature" field in alt_instr.
22+
23+
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \
24+
# RUN: --defsym FEATURE_SIZE_4=1 %s -o %t.o
25+
# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \
26+
# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie
27+
# RUN: llvm-bolt %t.exe --print-normalized --keep-nops \
28+
# RUN: --alt-inst-feature-size=4 -o %t.out | FileCheck %s
29+
30+
## Check that out-of-bounds read is handled properly.
31+
32+
# RUN: not llvm-bolt %t.exe --print-normalized --keep-nops \
33+
# RUN: --alt-inst-feature-size=2 -o %t.out
34+
35+
# CHECK: BOLT-INFO: Linux kernel binary detected
36+
# CHECK: BOLT-INFO: parsed 2 alternative instruction entries
37+
38+
.text
39+
.globl _start
40+
.type _start, %function
41+
_start:
42+
# CHECK: Binary Function "_start"
43+
.L0:
44+
rdtsc
45+
# CHECK: rdtsc
46+
# CHECK-SAME: AltInst: 1
47+
# CHECK-SAME: AltInst2: 2
48+
nop
49+
# CHECK-NEXT: nop
50+
# CHECK-SAME: AltInst: 1
51+
# CHECK-SAME: AltInst2: 2
52+
nop
53+
nop
54+
.L1:
55+
ret
56+
.size _start, .-_start
57+
58+
.section .altinstr_replacement,"ax",@progbits
59+
.A0:
60+
lfence
61+
rdtsc
62+
.A1:
63+
rdtscp
64+
.Ae:
65+
66+
## Alternative instruction info.
67+
.section .altinstructions,"a",@progbits
68+
69+
.long .L0 - . # org instruction
70+
.long .A0 - . # alt instruction
71+
.ifdef FEATURE_SIZE_4
72+
.long 0x72 # feature flags
73+
.else
74+
.word 0x72 # feature flags
75+
.endif
76+
.byte .L1 - .L0 # org size
77+
.byte .A1 - .A0 # alt size
78+
.ifdef PADLEN
79+
.byte 0
80+
.endif
81+
82+
.long .L0 - . # org instruction
83+
.long .A1 - . # alt instruction
84+
.ifdef FEATURE_SIZE_4
85+
.long 0x3b # feature flags
86+
.else
87+
.word 0x3b # feature flags
88+
.endif
89+
.byte .L1 - .L0 # org size
90+
.byte .Ae - .A1 # alt size
91+
.ifdef PADLEN
92+
.byte 0
93+
.endif
94+
95+
## Fake Linux Kernel sections.
96+
.section __ksymtab,"a",@progbits
97+
.section __ksymtab_gpl,"a",@progbits

0 commit comments

Comments
 (0)