Skip to content

Commit 67bbc48

Browse files
committed
WIP MTE stack record
Pull Request: llvm#86356
1 parent 12c7371 commit 67bbc48

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

llvm/lib/Target/AArch64/AArch64StackTagging.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "AArch64InstrInfo.h"
1212
#include "AArch64Subtarget.h"
1313
#include "AArch64TargetMachine.h"
14+
#include "llvm/ADT/APInt.h"
1415
#include "llvm/ADT/MapVector.h"
1516
#include "llvm/ADT/SmallVector.h"
1617
#include "llvm/ADT/Statistic.h"
@@ -82,6 +83,26 @@ static cl::opt<size_t> ClMaxLifetimes(
8283
cl::desc("How many lifetime ends to handle for a single alloca."),
8384
cl::Optional);
8485

86+
// Mode for selecting how to insert frame record info into the stack ring
87+
// buffer.
88+
enum RecordStackHistoryMode {
89+
// Do not record frame record info.
90+
none,
91+
92+
// Insert instructions into the prologue for storing into the stack ring
93+
// buffer directly.
94+
instr,
95+
};
96+
97+
static cl::opt<RecordStackHistoryMode> ClRecordStackHistory(
98+
"stack-tagging-record-stack-history",
99+
cl::desc("Record stack frames with tagged allocations in a thread-local "
100+
"ring buffer"),
101+
cl::values(clEnumVal(none, "Do not record stack ring history"),
102+
clEnumVal(instr, "Insert instructions into the prologue for "
103+
"storing into the stack ring buffer")),
104+
cl::Hidden, cl::init(instr));
105+
85106
static const Align kTagGranuleSize = Align(16);
86107

87108
namespace {
@@ -309,6 +330,7 @@ class AArch64StackTagging : public FunctionPass {
309330
uint64_t Size, InitializerBuilder &IB);
310331

311332
Instruction *insertBaseTaggedPointer(
333+
const Module &M,
312334
const MapVector<AllocaInst *, memtag::AllocaInfo> &Allocas,
313335
const DominatorTree *DT);
314336
bool runOnFunction(Function &F) override;
@@ -437,6 +459,7 @@ void AArch64StackTagging::untagAlloca(AllocaInst *AI, Instruction *InsertBefore,
437459
}
438460

439461
Instruction *AArch64StackTagging::insertBaseTaggedPointer(
462+
const Module &M,
440463
const MapVector<AllocaInst *, memtag::AllocaInfo> &AllocasToInstrument,
441464
const DominatorTree *DT) {
442465
BasicBlock *PrologueBB = nullptr;
@@ -458,6 +481,37 @@ Instruction *AArch64StackTagging::insertBaseTaggedPointer(
458481
Instruction *Base =
459482
IRB.CreateCall(IRG_SP, {Constant::getNullValue(IRB.getInt64Ty())});
460483
Base->setName("basetag");
484+
auto TargetTriple = Triple(M.getTargetTriple());
485+
if (ClRecordStackHistory == instr && TargetTriple.isAndroid() &&
486+
TargetTriple.isAArch64() && !TargetTriple.isAndroidVersionLT(35)) {
487+
constexpr int StackMteSlot = -3;
488+
constexpr uint64_t TagMask = 0xFULL << 56;
489+
490+
auto *IntptrTy = IRB.getIntPtrTy(M.getDataLayout());
491+
Value *SlotPtr = memtag::getAndroidSlotPtr(IRB, StackMteSlot);
492+
auto *ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);
493+
Value *TaggedFP = IRB.CreateOr(
494+
memtag::getFP(IRB),
495+
IRB.CreateAnd(IRB.CreatePtrToInt(Base, IntptrTy), TagMask));
496+
Value *PC = memtag::getPC(TargetTriple, IRB);
497+
498+
Value *RecordPtr = IRB.CreateIntToPtr(ThreadLong, IRB.getPtrTy(0));
499+
IRB.CreateStore(PC, RecordPtr);
500+
IRB.CreateStore(TaggedFP, IRB.CreateConstGEP1_64(IntptrTy, RecordPtr, 1));
501+
// Update the ring buffer. Top byte of ThreadLong defines the size of the
502+
// buffer in pages, it must be a power of two, and the start of the buffer
503+
// must be aligned by twice that much. Therefore wrap around of the ring
504+
// buffer is simply Addr &= ~((ThreadLong >> 56) << 12).
505+
// The use of AShr instead of LShr is due to
506+
// https://bugs.llvm.org/show_bug.cgi?id=39030
507+
// Runtime library makes sure not to use the highest bit.
508+
Value *WrapMask = IRB.CreateXor(
509+
IRB.CreateShl(IRB.CreateAShr(ThreadLong, 56), 12, "", true, true),
510+
ConstantInt::get(IntptrTy, (uint64_t)-1));
511+
Value *ThreadLongNew = IRB.CreateAnd(
512+
IRB.CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 16)), WrapMask);
513+
IRB.CreateStore(ThreadLongNew, SlotPtr);
514+
}
461515
return Base;
462516
}
463517

@@ -513,7 +567,8 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {
513567
SetTagFunc =
514568
Intrinsic::getDeclaration(F->getParent(), Intrinsic::aarch64_settag);
515569

516-
Instruction *Base = insertBaseTaggedPointer(SInfo.AllocasToInstrument, DT);
570+
Instruction *Base =
571+
insertBaseTaggedPointer(*Fn.getParent(), SInfo.AllocasToInstrument, DT);
517572

518573
int NextTag = 0;
519574
for (auto &I : SInfo.AllocasToInstrument) {

0 commit comments

Comments
 (0)