Skip to content

Commit 0eeaa14

Browse files
committed
Merge branch 'extend_sg_map' into xegpu_simt_2d_to_1d
2 parents 8b490f6 + fb28ce8 commit 0eeaa14

File tree

1,642 files changed

+49818
-23489
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,642 files changed

+49818
-23489
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()

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 19 additions & 0 deletions
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 {
@@ -1741,6 +1751,15 @@ class MCPlusBuilder {
17411751
return {};
17421752
}
17431753

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+
17441763
/// Creates inline memcpy instruction. If \p ReturnEnd is true, then return
17451764
/// (dest + n) instead of dest.
17461765
virtual InstructionListType createInlineMemcpy(bool ReturnEnd) const {

bolt/include/bolt/Core/Relocation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ class Relocation {
8686
/// Adjust value depending on relocation type (make it PC relative or not).
8787
static uint64_t encodeValue(uint32_t Type, uint64_t Value, uint64_t PC);
8888

89+
/// Return true if there are enough bits to encode the relocation value.
90+
static bool canEncodeValue(uint32_t Type, uint64_t Value, uint64_t PC);
91+
8992
/// Extract current relocated value from binary contents. This is used for
9093
/// RISC architectures where values are encoded in specific bits depending
9194
/// on the relocation value. For X86, we limit to sign extending the value

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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,8 @@ bool BinaryFunction::scanExternalRefs() {
17951795
// Create relocation for every fixup.
17961796
for (const MCFixup &Fixup : Fixups) {
17971797
std::optional<Relocation> Rel = BC.MIB->createRelocation(Fixup, *BC.MAB);
1798+
// Can be skipped in case of overlow during relocation value encoding.
1799+
Rel->setOptional();
17981800
if (!Rel) {
17991801
Success = false;
18001802
continue;

bolt/lib/Core/BinarySection.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "bolt/Core/BinarySection.h"
1414
#include "bolt/Core/BinaryContext.h"
15+
#include "bolt/Utils/CommandLineOpts.h"
1516
#include "bolt/Utils/Utils.h"
1617
#include "llvm/MC/MCStreamer.h"
1718
#include "llvm/Support/CommandLine.h"
@@ -22,8 +23,8 @@ using namespace llvm;
2223
using namespace bolt;
2324

2425
namespace opts {
25-
extern cl::opt<bool> PrintRelocations;
2626
extern cl::opt<bool> HotData;
27+
extern cl::opt<bool> PrintRelocations;
2728
} // namespace opts
2829

2930
uint64_t BinarySection::Count = 0;
@@ -174,11 +175,30 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
174175
OS.pwrite(Patch.Bytes.data(), Patch.Bytes.size(),
175176
SectionFileOffset + Patch.Offset);
176177

178+
uint64_t SkippedPendingRelocations = 0;
177179
for (Relocation &Reloc : PendingRelocations) {
178180
uint64_t Value = Reloc.Addend;
179181
if (Reloc.Symbol)
180182
Value += Resolver(Reloc.Symbol);
181183

184+
// Safely skip any optional pending relocation that cannot be encoded.
185+
if (Reloc.isOptional() &&
186+
!Relocation::canEncodeValue(Reloc.Type, Value,
187+
SectionAddress + Reloc.Offset)) {
188+
189+
// A successful run of 'scanExternalRefs' means that all pending
190+
// relocations are flushed. Otherwise, PatchEntries should run.
191+
if (!opts::ForcePatch) {
192+
BC.errs()
193+
<< "BOLT-ERROR: cannot encode relocation for symbol "
194+
<< Reloc.Symbol->getName()
195+
<< " as it is out-of-range. To proceed must use -force-patch\n";
196+
exit(1);
197+
}
198+
199+
++SkippedPendingRelocations;
200+
continue;
201+
}
182202
Value = Relocation::encodeValue(Reloc.Type, Value,
183203
SectionAddress + Reloc.Offset);
184204

@@ -197,6 +217,11 @@ void BinarySection::flushPendingRelocations(raw_pwrite_stream &OS,
197217
}
198218

199219
clearList(PendingRelocations);
220+
221+
if (SkippedPendingRelocations > 0 && opts::Verbosity >= 1) {
222+
BC.outs() << "BOLT-INFO: skipped " << SkippedPendingRelocations
223+
<< " out-of-range optional relocations\n";
224+
}
200225
}
201226

202227
BinarySection::~BinarySection() { updateContents(nullptr, 0); }

bolt/lib/Core/Relocation.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ static uint64_t encodeValueX86(uint32_t Type, uint64_t Value, uint64_t PC) {
271271
return Value;
272272
}
273273

274+
static bool canEncodeValueAArch64(uint32_t Type, uint64_t Value, uint64_t PC) {
275+
switch (Type) {
276+
default:
277+
llvm_unreachable("unsupported relocation");
278+
case ELF::R_AARCH64_CALL26:
279+
case ELF::R_AARCH64_JUMP26:
280+
return isInt<28>(Value - PC);
281+
}
282+
}
283+
274284
static uint64_t encodeValueAArch64(uint32_t Type, uint64_t Value, uint64_t PC) {
275285
switch (Type) {
276286
default:
@@ -303,6 +313,16 @@ static uint64_t encodeValueAArch64(uint32_t Type, uint64_t Value, uint64_t PC) {
303313
return Value;
304314
}
305315

316+
static uint64_t canEncodeValueRISCV(uint32_t Type, uint64_t Value,
317+
uint64_t PC) {
318+
switch (Type) {
319+
default:
320+
llvm_unreachable("unsupported relocation");
321+
case ELF::R_RISCV_64:
322+
return true;
323+
}
324+
}
325+
306326
static uint64_t encodeValueRISCV(uint32_t Type, uint64_t Value, uint64_t PC) {
307327
switch (Type) {
308328
default:
@@ -739,6 +759,19 @@ uint64_t Relocation::encodeValue(uint32_t Type, uint64_t Value, uint64_t PC) {
739759
}
740760
}
741761

762+
bool Relocation::canEncodeValue(uint32_t Type, uint64_t Value, uint64_t PC) {
763+
switch (Arch) {
764+
default:
765+
llvm_unreachable("Unsupported architecture");
766+
case Triple::aarch64:
767+
return canEncodeValueAArch64(Type, Value, PC);
768+
case Triple::riscv64:
769+
return canEncodeValueRISCV(Type, Value, PC);
770+
case Triple::x86_64:
771+
return true;
772+
}
773+
}
774+
742775
uint64_t Relocation::extractValue(uint32_t Type, uint64_t Contents,
743776
uint64_t PC) {
744777
switch (Arch) {

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());

0 commit comments

Comments
 (0)