Skip to content

Commit 86beb1d

Browse files
authored
Merge branch 'main' into pr/riscv-xqciint-push-pop
2 parents 2ec11ea + ad9f15a commit 86beb1d

File tree

1,199 files changed

+27807
-14228
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,199 files changed

+27807
-14228
lines changed

.ci/monolithic-linux.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ targets="${2}"
5353
lit_args="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --use-unique-output-file-name --timeout=1200 --time-tests"
5454

5555
echo "--- cmake"
56+
export PIP_BREAK_SYSTEM_PACKAGES=1
5657
pip install -q -r "${MONOREPO_ROOT}"/mlir/python/requirements.txt
5758
pip install -q -r "${MONOREPO_ROOT}"/lldb/test/requirements.txt
5859
pip install -q -r "${MONOREPO_ROOT}"/.ci/requirements.txt

.github/new-prs-labeler.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,12 @@ backend:DirectX:
660660
- '**/*dxil*/**'
661661
- '**/*DXContainer*'
662662
- '**/*DXContainer*/**'
663+
- clang/lib/Sema/SemaDirectX.cpp
664+
- clang/include/clang/Sema/SemaDirectX.h
665+
- clang/include/clang/Basic/BuiltinsDirectX.td
666+
- clang/lib/CodeGen/TargetBuiltins/DirectX.cpp
667+
- clang/test/CodeGenDirectX/**
668+
- clang/test/SemaDirectX/**
663669

664670
backend:SPIR-V:
665671
- clang/lib/Driver/ToolChains/SPIRV.*

.github/workflows/containers/github-action-ci-windows/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ RUN choco install -y handle
108108
109109
RUN pip3 install pywin32 buildbot-worker==2.8.4
110110
111-
ARG RUNNER_VERSION=2.322.0
111+
ARG RUNNER_VERSION=2.323.0
112112
ENV RUNNER_VERSION=$RUNNER_VERSION
113113
114114
RUN powershell -Command \

.github/workflows/containers/github-action-ci/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ WORKDIR /home/gha
9595

9696
FROM ci-container as ci-container-agent
9797

98-
ENV GITHUB_RUNNER_VERSION=2.322.0
98+
ENV GITHUB_RUNNER_VERSION=2.323.0
9999

100100
RUN mkdir actions-runner && \
101101
cd actions-runner && \

.github/workflows/libcxx-build-and-test.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,20 @@ jobs:
197197
os: macos-15
198198
- config: apple-configuration
199199
os: macos-15
200+
# TODO: These jobs are intended to test back-deployment (building against ToT libc++ but running against an
201+
# older system-provided libc++.dylib). Doing this properly would require building the test suite on a
202+
# recent macOS using a recent Clang (hence recent Xcode), and then running the actual test suite on an
203+
# older mac. We could do that by e.g. sharing artifacts between the two jobs.
204+
#
205+
# However, our Lit configuration currently doesn't provide a good way to do that in a batch, so our only
206+
# alternative is to actually build on the same host that we're going to run on. Sadly, that doesn't work
207+
# since older macOSes don't support newer Xcodes. For now, we run the "backdeployment" jobs on recent
208+
# macOS versions as a way to avoid rotting that configuration, but it doesn't provide a lot of additional
209+
# coverage.
200210
- config: apple-system
201-
os: macos-13
211+
os: macos-15
202212
- config: apple-system-hardened
203-
os: macos-13
213+
os: macos-15
204214
runs-on: ${{ matrix.os }}
205215
steps:
206216
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,41 @@ class MCPlusBuilder {
587587
return getNoRegister();
588588
}
589589

590+
/// Returns the register containing an address safely materialized by `Inst`
591+
/// under the Pointer Authentication threat model.
592+
///
593+
/// Returns the register `Inst` writes to if:
594+
/// 1. the register is a materialized address, and
595+
/// 2. the register has been materialized safely, i.e. cannot be attacker-
596+
/// controlled, under the Pointer Authentication threat model.
597+
///
598+
/// If the instruction does not write to any register satisfying the above
599+
/// two conditions, NoRegister is returned.
600+
///
601+
/// The Pointer Authentication threat model assumes an attacker is able to
602+
/// modify any writable memory, but not executable code (due to W^X).
603+
virtual MCPhysReg
604+
getMaterializedAddressRegForPtrAuth(const MCInst &Inst) const {
605+
llvm_unreachable("not implemented");
606+
return getNoRegister();
607+
}
608+
609+
/// Analyzes if this instruction can safely perform address arithmetics
610+
/// under Pointer Authentication threat model.
611+
///
612+
/// If an (OutReg, InReg) pair is returned, then after Inst is executed,
613+
/// OutReg is as trusted as InReg is.
614+
///
615+
/// The arithmetic instruction is considered safe if OutReg is not attacker-
616+
/// controlled, provided InReg and executable code are not. Please note that
617+
/// registers other than InReg as well as the contents of memory which is
618+
/// writable by the process should be considered attacker-controlled.
619+
virtual std::optional<std::pair<MCPhysReg, MCPhysReg>>
620+
analyzeAddressArithmeticsForPtrAuth(const MCInst &Inst) const {
621+
llvm_unreachable("not implemented");
622+
return std::make_pair(getNoRegister(), getNoRegister());
623+
}
624+
590625
virtual bool isTerminator(const MCInst &Inst) const;
591626

592627
virtual bool isNoop(const MCInst &Inst) 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/DataflowAnalysis.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,14 +292,17 @@ class DataflowAnalysis {
292292
/// Relies on a ptr map to fetch the previous instruction and then retrieve
293293
/// state. WARNING: Watch out for invalidated pointers. Do not use this
294294
/// function if you invalidated pointers after the analysis has been completed
295-
ErrorOr<const StateTy &> getStateBefore(const MCInst &Point) {
296-
return getStateAt(PrevPoint[&Point]);
295+
ErrorOr<const StateTy &> getStateBefore(const MCInst &Point) const {
296+
auto It = PrevPoint.find(&Point);
297+
if (It == PrevPoint.end())
298+
return make_error_code(std::errc::result_out_of_range);
299+
return getStateAt(It->getSecond());
297300
}
298301

299-
ErrorOr<const StateTy &> getStateBefore(ProgramPoint Point) {
302+
ErrorOr<const StateTy &> getStateBefore(ProgramPoint Point) const {
300303
if (Point.isBB())
301304
return getStateAt(*Point.getBB());
302-
return getStateAt(PrevPoint[Point.getInst()]);
305+
return getStateBefore(*Point.getInst());
303306
}
304307

305308
/// Remove any state annotations left by this analysis

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: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,49 @@ class PacRetAnalysis
335335
});
336336
}
337337

338+
BitVector getClobberedRegs(const MCInst &Point) const {
339+
BitVector Clobbered(NumRegs, false);
340+
// Assume a call can clobber all registers, including callee-saved
341+
// registers. There's a good chance that callee-saved registers will be
342+
// saved on the stack at some point during execution of the callee.
343+
// Therefore they should also be considered as potentially modified by an
344+
// attacker/written to.
345+
// Also, not all functions may respect the AAPCS ABI rules about
346+
// caller/callee-saved registers.
347+
if (BC.MIB->isCall(Point))
348+
Clobbered.set();
349+
else
350+
BC.MIB->getClobberedRegs(Point, Clobbered);
351+
return Clobbered;
352+
}
353+
354+
// Returns all registers that can be treated as if they are written by an
355+
// authentication instruction.
356+
SmallVector<MCPhysReg> getRegsMadeSafeToDeref(const MCInst &Point,
357+
const State &Cur) const {
358+
SmallVector<MCPhysReg> Regs;
359+
const MCPhysReg NoReg = BC.MIB->getNoRegister();
360+
361+
// A signed pointer can be authenticated, or
362+
ErrorOr<MCPhysReg> AutReg = BC.MIB->getAuthenticatedReg(Point);
363+
if (AutReg && *AutReg != NoReg)
364+
Regs.push_back(*AutReg);
365+
366+
// ... a safe address can be materialized, or
367+
MCPhysReg NewAddrReg = BC.MIB->getMaterializedAddressRegForPtrAuth(Point);
368+
if (NewAddrReg != NoReg)
369+
Regs.push_back(NewAddrReg);
370+
371+
// ... an address can be updated in a safe manner, producing the result
372+
// which is as trusted as the input address.
373+
if (auto DstAndSrc = BC.MIB->analyzeAddressArithmeticsForPtrAuth(Point)) {
374+
if (Cur.SafeToDerefRegs[DstAndSrc->second])
375+
Regs.push_back(DstAndSrc->first);
376+
}
377+
378+
return Regs;
379+
}
380+
338381
State computeNext(const MCInst &Point, const State &Cur) {
339382
PacStatePrinter P(BC);
340383
LLVM_DEBUG({
@@ -355,37 +398,35 @@ class PacRetAnalysis
355398
return State();
356399
}
357400

401+
// First, compute various properties of the instruction, taking the state
402+
// before its execution into account, if necessary.
403+
404+
BitVector Clobbered = getClobberedRegs(Point);
405+
SmallVector<MCPhysReg> NewSafeToDerefRegs =
406+
getRegsMadeSafeToDeref(Point, Cur);
407+
408+
// Then, compute the state after this instruction is executed.
358409
State Next = Cur;
359-
BitVector Clobbered(NumRegs, false);
360-
// Assume a call can clobber all registers, including callee-saved
361-
// registers. There's a good chance that callee-saved registers will be
362-
// saved on the stack at some point during execution of the callee.
363-
// Therefore they should also be considered as potentially modified by an
364-
// attacker/written to.
365-
// Also, not all functions may respect the AAPCS ABI rules about
366-
// caller/callee-saved registers.
367-
if (BC.MIB->isCall(Point))
368-
Clobbered.set();
369-
else
370-
BC.MIB->getClobberedRegs(Point, Clobbered);
410+
371411
Next.SafeToDerefRegs.reset(Clobbered);
372412
// Keep track of this instruction if it writes to any of the registers we
373413
// need to track that for:
374414
for (MCPhysReg Reg : RegsToTrackInstsFor.getRegisters())
375415
if (Clobbered[Reg])
376416
lastWritingInsts(Next, Reg) = {&Point};
377417

378-
ErrorOr<MCPhysReg> AutReg = BC.MIB->getAuthenticatedReg(Point);
379-
if (AutReg && *AutReg != BC.MIB->getNoRegister()) {
380-
// The sub-registers of *AutReg are also trusted now, but not its
381-
// super-registers (as they retain untrusted register units).
382-
BitVector AuthenticatedSubregs =
383-
BC.MIB->getAliases(*AutReg, /*OnlySmaller=*/true);
384-
for (MCPhysReg Reg : AuthenticatedSubregs.set_bits()) {
385-
Next.SafeToDerefRegs.set(Reg);
386-
if (RegsToTrackInstsFor.isTracked(Reg))
387-
lastWritingInsts(Next, Reg).clear();
388-
}
418+
// After accounting for clobbered registers in general, override the state
419+
// according to authentication and other *special cases* of clobbering.
420+
421+
// The sub-registers are also safe-to-dereference now, but not their
422+
// super-registers (as they retain untrusted register units).
423+
BitVector NewSafeSubregs(NumRegs);
424+
for (MCPhysReg SafeReg : NewSafeToDerefRegs)
425+
NewSafeSubregs |= BC.MIB->getAliases(SafeReg, /*OnlySmaller=*/true);
426+
for (MCPhysReg Reg : NewSafeSubregs.set_bits()) {
427+
Next.SafeToDerefRegs.set(Reg);
428+
if (RegsToTrackInstsFor.isTracked(Reg))
429+
lastWritingInsts(Next, Reg).clear();
389430
}
390431

391432
LLVM_DEBUG({
@@ -402,7 +443,7 @@ class PacRetAnalysis
402443
public:
403444
std::vector<MCInstReference>
404445
getLastClobberingInsts(const MCInst &Inst, BinaryFunction &BF,
405-
const ArrayRef<MCPhysReg> UsedDirtyRegs) {
446+
const ArrayRef<MCPhysReg> UsedDirtyRegs) const {
406447
if (RegsToTrackInstsFor.empty())
407448
return {};
408449
auto MaybeState = getStateBefore(Inst);

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2827,9 +2827,10 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection,
28272827
if (SymbolAddress == 0)
28282828
ReferencedSymbol = BC->registerNameAtAddress(SymbolName, 0, 0, 0);
28292829

2830-
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: forcing relocation against symbol "
2831-
<< ReferencedSymbol->getName() << " with addend "
2832-
<< Addend << '\n');
2830+
LLVM_DEBUG(
2831+
dbgs() << "BOLT-DEBUG: forcing relocation against symbol "
2832+
<< (ReferencedSymbol ? ReferencedSymbol->getName() : "<none>")
2833+
<< " with addend " << Addend << '\n');
28332834
} else if (ReferencedBF) {
28342835
ReferencedSymbol = ReferencedBF->getSymbol();
28352836
uint64_t RefFunctionOffset = 0;

0 commit comments

Comments
 (0)