Skip to content

Commit 9854453

Browse files
committed
Merge remote-tracking branch 'origin/main' into vplan-all-regions-as-transform
2 parents d5ba9a3 + d6c076e commit 9854453

File tree

2,485 files changed

+149318
-77333
lines changed

Some content is hidden

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

2,485 files changed

+149318
-77333
lines changed

.ci/compute_projects.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ def _get_modified_projects(modified_files: list[str]) -> Set[str]:
200200
# documentation builds.
201201
if len(path_parts) > 2 and path_parts[1] == "docs":
202202
continue
203+
# Exclude files for the gn build. We do not test it within premerge
204+
# and changes occur often enough that they otherwise take up
205+
# capacity.
206+
if len(path_parts) > 3 and path_parts[:3] == ("llvm", "utils", "gn"):
207+
continue
203208
modified_projects.add(pathlib.Path(modified_file).parts[0])
204209
return modified_projects
205210

.ci/compute_projects_test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,15 @@ def test_exclude_docs(self):
179179
self.assertEqual(env_variables["runtimes_to_build"], "")
180180
self.assertEqual(env_variables["runtimes_check_targets"], "")
181181

182+
def test_exclude_gn(self):
183+
env_variables = compute_projects.get_env_variables(
184+
["llvm/utils/gn/build/BUILD.gn"], "Linux"
185+
)
186+
self.assertEqual(env_variables["projects_to_build"], "")
187+
self.assertEqual(env_variables["project_check_targets"], "")
188+
self.assertEqual(env_variables["runtimes_to_build"], "")
189+
self.assertEqual(env_variables["runtimes_check_targets"], "")
190+
182191

183192
if __name__ == "__main__":
184193
unittest.main()

.github/workflows/libclang-abi-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ jobs:
104104
- name: Install abi-compliance-checker
105105
run: |
106106
sudo apt-get update
107-
sudo apt-get install abi-dumper autoconf pkg-config
107+
sudo apt-get install -y abi-dumper autoconf pkg-config
108108
- name: Install universal-ctags
109109
run: |
110110
git clone https://github.com/universal-ctags/ctags.git
@@ -157,7 +157,7 @@ jobs:
157157
- name: Install abi-compliance-checker
158158
run: |
159159
sudo apt-get update
160-
sudo apt-get install abi-compliance-checker
160+
sudo apt-get install -y abi-compliance-checker
161161
- name: Compare ABI
162162
run: |
163163
for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do

.github/workflows/llvm-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
- name: Install abi-compliance-checker
9393
run: |
9494
sudo apt-get update
95-
sudo apt-get install abi-dumper autoconf pkg-config
95+
sudo apt-get -y install abi-dumper autoconf pkg-config
9696
- name: Install universal-ctags
9797
run: |
9898
git clone https://github.com/universal-ctags/ctags.git
@@ -166,7 +166,7 @@ jobs:
166166
- name: Install abi-compliance-checker
167167
run: |
168168
sudo apt-get update
169-
sudo apt-get install abi-compliance-checker
169+
sudo apt-get -y install abi-compliance-checker
170170
- name: Compare ABI
171171
run: |
172172
if [ -s symbol-list/llvm.symbols ]; then

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,16 @@ class MCPlusBuilder {
577577
return getNoRegister();
578578
}
579579

580+
/// Returns the register used as call destination, or no-register, if not
581+
/// an indirect call. Sets IsAuthenticatedInternally if the instruction
582+
/// accepts a signed pointer as its operand and authenticates it internally.
583+
virtual MCPhysReg
584+
getRegUsedAsCallDest(const MCInst &Inst,
585+
bool &IsAuthenticatedInternally) const {
586+
llvm_unreachable("not implemented");
587+
return getNoRegister();
588+
}
589+
580590
virtual bool isTerminator(const MCInst &Inst) const;
581591

582592
virtual bool isNoop(const MCInst &Inst) const {
@@ -1266,7 +1276,11 @@ class MCPlusBuilder {
12661276

12671277
/// Return MCSymbol extracted from the expression.
12681278
virtual const MCSymbol *getTargetSymbol(const MCExpr *Expr) const {
1269-
if (auto *SymbolRefExpr = dyn_cast<const MCSymbolRefExpr>(Expr))
1279+
if (auto *BinaryExpr = dyn_cast<const MCBinaryExpr>(Expr))
1280+
return getTargetSymbol(BinaryExpr->getLHS());
1281+
1282+
auto *SymbolRefExpr = dyn_cast<const MCSymbolRefExpr>(Expr);
1283+
if (SymbolRefExpr && SymbolRefExpr->getKind() == MCSymbolRefExpr::VK_None)
12701284
return &SymbolRefExpr->getSymbol();
12711285

12721286
return nullptr;
@@ -1737,6 +1751,15 @@ class MCPlusBuilder {
17371751
return {};
17381752
}
17391753

1754+
/// Create a sequence of instructions to compare contents of a register
1755+
/// \p RegNo to immediate \Imm and jump to \p Target if they are different.
1756+
virtual InstructionListType createCmpJNE(MCPhysReg RegNo, int64_t Imm,
1757+
const MCSymbol *Target,
1758+
MCContext *Ctx) const {
1759+
llvm_unreachable("not implemented");
1760+
return {};
1761+
}
1762+
17401763
/// Creates inline memcpy instruction. If \p ReturnEnd is true, then return
17411764
/// (dest + n) instead of dest.
17421765
virtual InstructionListType createInlineMemcpy(bool ReturnEnd) const {

bolt/include/bolt/Passes/PAuthGadgetScanner.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ struct FunctionAnalysisResult {
248248
};
249249

250250
class Analysis : public BinaryFunctionPass {
251+
/// Only search for pac-ret violations.
252+
bool PacRetGadgetsOnly;
253+
251254
void runOnFunction(BinaryFunction &Function,
252255
MCPlusBuilder::AllocatorIdTy AllocatorId);
253256
FunctionAnalysisResult findGadgets(BinaryFunction &BF,
@@ -261,7 +264,8 @@ class Analysis : public BinaryFunctionPass {
261264
std::mutex AnalysisResultsMutex;
262265

263266
public:
264-
explicit Analysis() : BinaryFunctionPass(false) {}
267+
explicit Analysis(bool PacRetGadgetsOnly)
268+
: BinaryFunctionPass(false), PacRetGadgetsOnly(PacRetGadgetsOnly) {}
265269

266270
const char *getName() const override { return "pauth-gadget-scanner"; }
267271

bolt/include/bolt/Utils/CommandLineOpts.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ extern llvm::cl::opt<unsigned> Verbosity;
8181
/// Return true if we should process all functions in the binary.
8282
bool processAllFunctions();
8383

84-
enum GadgetScannerKind { GS_PACRET, GS_ALL };
84+
enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
8585

86-
extern llvm::cl::list<GadgetScannerKind> GadgetScannersToRun;
86+
extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;
8787

8888
} // namespace opts
8989

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,11 @@ void BinaryFunction::handleIndirectBranch(MCInst &Instruction, uint64_t Size,
12191219
case IndirectBranchType::UNKNOWN:
12201220
// Keep processing. We'll do more checks and fixes in
12211221
// postProcessIndirectBranches().
1222+
if (opts::Verbosity > 2) {
1223+
outs() << "BOLT-WARNING: failed to match indirect branch, "
1224+
<< getPrintName() << " at 0x" << Twine::utohexstr(Offset)
1225+
<< " offset\n";
1226+
}
12221227
UnknownIndirectBranchOffsets.emplace(Offset);
12231228
break;
12241229
}

bolt/lib/Passes/PAuthGadgetScanner.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,11 @@ class PacRetAnalysis
401401

402402
public:
403403
std::vector<MCInstReference>
404-
getLastClobberingInsts(const MCInst Ret, BinaryFunction &BF,
405-
const ArrayRef<MCPhysReg> UsedDirtyRegs) const {
404+
getLastClobberingInsts(const MCInst &Inst, BinaryFunction &BF,
405+
const ArrayRef<MCPhysReg> UsedDirtyRegs) {
406406
if (RegsToTrackInstsFor.empty())
407407
return {};
408-
auto MaybeState = getStateAt(Ret);
408+
auto MaybeState = getStateBefore(Inst);
409409
if (!MaybeState)
410410
llvm_unreachable("Expected State to be present");
411411
const State &S = *MaybeState;
@@ -453,6 +453,29 @@ shouldReportReturnGadget(const BinaryContext &BC, const MCInstReference &Inst,
453453
return std::make_shared<GadgetReport>(RetKind, Inst, RetReg);
454454
}
455455

456+
static std::shared_ptr<Report>
457+
shouldReportCallGadget(const BinaryContext &BC, const MCInstReference &Inst,
458+
const State &S) {
459+
static const GadgetKind CallKind("non-protected call found");
460+
if (!BC.MIB->isCall(Inst) && !BC.MIB->isBranch(Inst))
461+
return nullptr;
462+
463+
bool IsAuthenticated = false;
464+
MCPhysReg DestReg = BC.MIB->getRegUsedAsCallDest(Inst, IsAuthenticated);
465+
if (IsAuthenticated || DestReg == BC.MIB->getNoRegister())
466+
return nullptr;
467+
468+
LLVM_DEBUG({
469+
traceInst(BC, "Found call inst", Inst);
470+
traceReg(BC, "Call destination reg", DestReg);
471+
traceRegMask(BC, "SafeToDerefRegs", S.SafeToDerefRegs);
472+
});
473+
if (S.SafeToDerefRegs[DestReg])
474+
return nullptr;
475+
476+
return std::make_shared<GadgetReport>(CallKind, Inst, DestReg);
477+
}
478+
456479
FunctionAnalysisResult
457480
Analysis::findGadgets(BinaryFunction &BF,
458481
MCPlusBuilder::AllocatorIdTy AllocatorId) {
@@ -469,7 +492,7 @@ Analysis::findGadgets(BinaryFunction &BF,
469492
for (BinaryBasicBlock &BB : BF) {
470493
for (int64_t I = 0, E = BB.size(); I < E; ++I) {
471494
MCInstReference Inst(&BB, I);
472-
const State &S = *PRA.getStateAt(Inst);
495+
const State &S = *PRA.getStateBefore(Inst);
473496

474497
// If non-empty state was never propagated from the entry basic block
475498
// to Inst, assume it to be unreachable and report a warning.
@@ -481,6 +504,12 @@ Analysis::findGadgets(BinaryFunction &BF,
481504

482505
if (auto Report = shouldReportReturnGadget(BC, Inst, S))
483506
Result.Diagnostics.push_back(Report);
507+
508+
if (PacRetGadgetsOnly)
509+
continue;
510+
511+
if (auto Report = shouldReportCallGadget(BC, Inst, S))
512+
Result.Diagnostics.push_back(Report);
484513
}
485514
}
486515
return Result;

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,14 @@ static cl::opt<bool> WriteBoltInfoSection(
247247
"bolt-info", cl::desc("write bolt info section in the output binary"),
248248
cl::init(true), cl::Hidden, cl::cat(BoltOutputCategory));
249249

250-
cl::list<GadgetScannerKind>
251-
GadgetScannersToRun("scanners", cl::desc("which gadget scanners to run"),
252-
cl::values(clEnumValN(GS_PACRET, "pacret", "pac-ret"),
253-
clEnumValN(GS_ALL, "all", "all")),
254-
cl::ZeroOrMore, cl::CommaSeparated,
255-
cl::cat(BinaryAnalysisCategory));
250+
cl::bits<GadgetScannerKind> GadgetScannersToRun(
251+
"scanners", cl::desc("which gadget scanners to run"),
252+
cl::values(
253+
clEnumValN(GS_PACRET, "pacret",
254+
"pac-ret: return address protection (subset of \"pauth\")"),
255+
clEnumValN(GS_PAUTH, "pauth", "All Pointer Authentication scanners"),
256+
clEnumValN(GS_ALL, "all", "All implemented scanners")),
257+
cl::ZeroOrMore, cl::CommaSeparated, cl::cat(BinaryAnalysisCategory));
256258

257259
} // namespace opts
258260

@@ -3539,12 +3541,18 @@ void RewriteInstance::runBinaryAnalyses() {
35393541
// FIXME: add a pass that warns about which functions do not have CFG,
35403542
// and therefore, analysis is most likely to be less accurate.
35413543
using GSK = opts::GadgetScannerKind;
3542-
// if no command line option was given, act as if "all" was specified.
3543-
if (opts::GadgetScannersToRun.empty())
3544-
opts::GadgetScannersToRun.addValue(GSK::GS_ALL);
3545-
for (GSK ScannerToRun : opts::GadgetScannersToRun) {
3546-
if (ScannerToRun == GSK::GS_PACRET || ScannerToRun == GSK::GS_ALL)
3547-
Manager.registerPass(std::make_unique<PAuthGadgetScanner::Analysis>());
3544+
using PAuthScanner = PAuthGadgetScanner::Analysis;
3545+
3546+
// If no command line option was given, act as if "all" was specified.
3547+
bool RunAll = !opts::GadgetScannersToRun.getBits() ||
3548+
opts::GadgetScannersToRun.isSet(GSK::GS_ALL);
3549+
3550+
if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PAUTH)) {
3551+
Manager.registerPass(
3552+
std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/false));
3553+
} else if (RunAll || opts::GadgetScannersToRun.isSet(GSK::GS_PACRET)) {
3554+
Manager.registerPass(
3555+
std::make_unique<PAuthScanner>(/*OnlyPacRetChecks=*/true));
35483556
}
35493557

35503558
BC->logBOLTErrorsAndQuitOnFatal(Manager.runPasses());

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,33 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
277277
}
278278
}
279279

280+
MCPhysReg
281+
getRegUsedAsCallDest(const MCInst &Inst,
282+
bool &IsAuthenticatedInternally) const override {
283+
assert(isCall(Inst) || isBranch(Inst));
284+
IsAuthenticatedInternally = false;
285+
286+
switch (Inst.getOpcode()) {
287+
case AArch64::BR:
288+
case AArch64::BLR:
289+
return Inst.getOperand(0).getReg();
290+
case AArch64::BRAA:
291+
case AArch64::BRAB:
292+
case AArch64::BRAAZ:
293+
case AArch64::BRABZ:
294+
case AArch64::BLRAA:
295+
case AArch64::BLRAB:
296+
case AArch64::BLRAAZ:
297+
case AArch64::BLRABZ:
298+
IsAuthenticatedInternally = true;
299+
return Inst.getOperand(0).getReg();
300+
default:
301+
if (isIndirectCall(Inst) || isIndirectBranch(Inst))
302+
llvm_unreachable("Unhandled indirect branch");
303+
return getNoRegister();
304+
}
305+
}
306+
280307
bool isADRP(const MCInst &Inst) const override {
281308
return Inst.getOpcode() == AArch64::ADRP;
282309
}
@@ -862,20 +889,12 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
862889
if (AArchExpr && AArchExpr->getSubExpr())
863890
return getTargetSymbol(AArchExpr->getSubExpr());
864891

865-
auto *BinExpr = dyn_cast<MCBinaryExpr>(Expr);
866-
if (BinExpr)
867-
return getTargetSymbol(BinExpr->getLHS());
868-
869-
auto *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr);
870-
if (SymExpr && SymExpr->getKind() == MCSymbolRefExpr::VK_None)
871-
return &SymExpr->getSymbol();
872-
873-
return nullptr;
892+
return MCPlusBuilder::getTargetSymbol(Expr);
874893
}
875894

876895
const MCSymbol *getTargetSymbol(const MCInst &Inst,
877896
unsigned OpNum = 0) const override {
878-
if (!getSymbolRefOperandNum(Inst, OpNum))
897+
if (!OpNum && !getSymbolRefOperandNum(Inst, OpNum))
879898
return nullptr;
880899

881900
const MCOperand &Op = Inst.getOperand(OpNum);
@@ -1342,17 +1361,47 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
13421361

13431362
int getUncondBranchEncodingSize() const override { return 28; }
13441363

1364+
// This helper function creates the snippet of code that compares a register
1365+
// RegNo with an immedaite Imm, and jumps to Target if they are equal.
1366+
// cmp RegNo, #Imm
1367+
// b.eq Target
1368+
// where cmp is an alias for subs, which results in the code below:
1369+
// subs xzr, RegNo, #Imm
1370+
// b.eq Target.
13451371
InstructionListType createCmpJE(MCPhysReg RegNo, int64_t Imm,
13461372
const MCSymbol *Target,
13471373
MCContext *Ctx) const override {
13481374
InstructionListType Code;
13491375
Code.emplace_back(MCInstBuilder(AArch64::SUBSXri)
1350-
.addReg(RegNo)
1376+
.addReg(AArch64::XZR)
13511377
.addReg(RegNo)
13521378
.addImm(Imm)
13531379
.addImm(0));
13541380
Code.emplace_back(MCInstBuilder(AArch64::Bcc)
1381+
.addImm(AArch64CC::EQ)
1382+
.addExpr(MCSymbolRefExpr::create(
1383+
Target, MCSymbolRefExpr::VK_None, *Ctx)));
1384+
return Code;
1385+
}
1386+
1387+
// This helper function creates the snippet of code that compares a register
1388+
// RegNo with an immedaite Imm, and jumps to Target if they are not equal.
1389+
// cmp RegNo, #Imm
1390+
// b.ne Target
1391+
// where cmp is an alias for subs, which results in the code below:
1392+
// subs xzr, RegNo, #Imm
1393+
// b.ne Target.
1394+
InstructionListType createCmpJNE(MCPhysReg RegNo, int64_t Imm,
1395+
const MCSymbol *Target,
1396+
MCContext *Ctx) const override {
1397+
InstructionListType Code;
1398+
Code.emplace_back(MCInstBuilder(AArch64::SUBSXri)
1399+
.addReg(AArch64::XZR)
1400+
.addReg(RegNo)
13551401
.addImm(Imm)
1402+
.addImm(0));
1403+
Code.emplace_back(MCInstBuilder(AArch64::Bcc)
1404+
.addImm(AArch64CC::NE)
13561405
.addExpr(MCSymbolRefExpr::create(
13571406
Target, MCSymbolRefExpr::VK_None, *Ctx)));
13581407
return Code;

bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -338,15 +338,7 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
338338
if (RISCVExpr && RISCVExpr->getSubExpr())
339339
return getTargetSymbol(RISCVExpr->getSubExpr());
340340

341-
auto *BinExpr = dyn_cast<MCBinaryExpr>(Expr);
342-
if (BinExpr)
343-
return getTargetSymbol(BinExpr->getLHS());
344-
345-
auto *SymExpr = dyn_cast<MCSymbolRefExpr>(Expr);
346-
if (SymExpr && SymExpr->getKind() == MCSymbolRefExpr::VK_None)
347-
return &SymExpr->getSymbol();
348-
349-
return nullptr;
341+
return MCPlusBuilder::getTargetSymbol(Expr);
350342
}
351343

352344
const MCSymbol *getTargetSymbol(const MCInst &Inst,

0 commit comments

Comments
 (0)