11
11
#include " AArch64InstrInfo.h"
12
12
#include " AArch64Subtarget.h"
13
13
#include " AArch64TargetMachine.h"
14
+ #include " llvm/ADT/APInt.h"
14
15
#include " llvm/ADT/MapVector.h"
15
16
#include " llvm/ADT/SmallVector.h"
16
17
#include " llvm/ADT/Statistic.h"
@@ -82,6 +83,26 @@ static cl::opt<size_t> ClMaxLifetimes(
82
83
cl::desc(" How many lifetime ends to handle for a single alloca." ),
83
84
cl::Optional);
84
85
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
+
85
106
static const Align kTagGranuleSize = Align(16 );
86
107
87
108
namespace {
@@ -309,6 +330,7 @@ class AArch64StackTagging : public FunctionPass {
309
330
uint64_t Size , InitializerBuilder &IB);
310
331
311
332
Instruction *insertBaseTaggedPointer (
333
+ const Module &M,
312
334
const MapVector<AllocaInst *, memtag::AllocaInfo> &Allocas,
313
335
const DominatorTree *DT);
314
336
bool runOnFunction (Function &F) override ;
@@ -437,6 +459,7 @@ void AArch64StackTagging::untagAlloca(AllocaInst *AI, Instruction *InsertBefore,
437
459
}
438
460
439
461
Instruction *AArch64StackTagging::insertBaseTaggedPointer (
462
+ const Module &M,
440
463
const MapVector<AllocaInst *, memtag::AllocaInfo> &AllocasToInstrument,
441
464
const DominatorTree *DT) {
442
465
BasicBlock *PrologueBB = nullptr ;
@@ -458,6 +481,37 @@ Instruction *AArch64StackTagging::insertBaseTaggedPointer(
458
481
Instruction *Base =
459
482
IRB.CreateCall (IRG_SP, {Constant::getNullValue (IRB.getInt64Ty ())});
460
483
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
+ }
461
515
return Base;
462
516
}
463
517
@@ -513,7 +567,8 @@ bool AArch64StackTagging::runOnFunction(Function &Fn) {
513
567
SetTagFunc =
514
568
Intrinsic::getDeclaration (F->getParent (), Intrinsic::aarch64_settag);
515
569
516
- Instruction *Base = insertBaseTaggedPointer (SInfo.AllocasToInstrument , DT);
570
+ Instruction *Base =
571
+ insertBaseTaggedPointer (*Fn.getParent (), SInfo.AllocasToInstrument , DT);
517
572
518
573
int NextTag = 0 ;
519
574
for (auto &I : SInfo.AllocasToInstrument ) {
0 commit comments