@@ -247,13 +247,6 @@ bool shouldDetectUseAfterScope(const Triple &TargetTriple) {
247
247
// / An instrumentation pass implementing detection of addressability bugs
248
248
// / using tagged pointers.
249
249
class HWAddressSanitizer {
250
- private:
251
- struct AllocaInfo {
252
- AllocaInst *AI;
253
- SmallVector<IntrinsicInst *, 2 > LifetimeStart;
254
- SmallVector<IntrinsicInst *, 2 > LifetimeEnd;
255
- };
256
-
257
250
public:
258
251
HWAddressSanitizer (Module &M, bool CompileKernel, bool Recover,
259
252
const StackSafetyGlobalInfo *SSI)
@@ -269,7 +262,7 @@ class HWAddressSanitizer {
269
262
void setSSI (const StackSafetyGlobalInfo *S) { SSI = S; }
270
263
271
264
DenseMap<AllocaInst *, AllocaInst *> padInterestingAllocas (
272
- const MapVector<AllocaInst *, AllocaInfo> &AllocasToInstrument);
265
+ const MapVector<AllocaInst *, memtag:: AllocaInfo> &AllocasToInstrument);
273
266
bool sanitizeFunction (Function &F,
274
267
llvm::function_ref<const DominatorTree &()> GetDT,
275
268
llvm::function_ref<const PostDominatorTree &()> GetPDT);
@@ -304,14 +297,10 @@ class HWAddressSanitizer {
304
297
void tagAlloca (IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, size_t Size);
305
298
Value *tagPointer (IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
306
299
Value *untagPointer (IRBuilder<> &IRB, Value *PtrLong);
307
- bool instrumentStack (
308
- bool ShouldDetectUseAfterScope,
309
- MapVector<AllocaInst *, AllocaInfo> &AllocasToInstrument,
310
- SmallVector<Instruction *, 4 > &UnrecognizedLifetimes,
311
- DenseMap<AllocaInst *, std::vector<DbgVariableIntrinsic *>> &AllocaDbgMap,
312
- SmallVectorImpl<Instruction *> &RetVec, Value *StackTag,
313
- llvm::function_ref<const DominatorTree &()> GetDT,
314
- llvm::function_ref<const PostDominatorTree &()> GetPDT);
300
+ bool instrumentStack (bool ShouldDetectUseAfterScope, memtag::StackInfo &Info,
301
+ Value *StackTag,
302
+ llvm::function_ref<const DominatorTree &()> GetDT,
303
+ llvm::function_ref<const PostDominatorTree &()> GetPDT);
315
304
Value *readRegister (IRBuilder<> &IRB, StringRef Name);
316
305
bool instrumentLandingPads (SmallVectorImpl<Instruction *> &RetVec);
317
306
Value *getNextTagWithCall (IRBuilder<> &IRB);
@@ -1325,11 +1314,7 @@ bool HWAddressSanitizer::instrumentLandingPads(
1325
1314
}
1326
1315
1327
1316
bool HWAddressSanitizer::instrumentStack (
1328
- bool ShouldDetectUseAfterScope,
1329
- MapVector<AllocaInst *, AllocaInfo> &AllocasToInstrument,
1330
- SmallVector<Instruction *, 4 > &UnrecognizedLifetimes,
1331
- DenseMap<AllocaInst *, std::vector<DbgVariableIntrinsic *>> &AllocaDbgMap,
1332
- SmallVectorImpl<Instruction *> &RetVec, Value *StackTag,
1317
+ bool ShouldDetectUseAfterScope, memtag::StackInfo &SInfo, Value *StackTag,
1333
1318
llvm::function_ref<const DominatorTree &()> GetDT,
1334
1319
llvm::function_ref<const PostDominatorTree &()> GetPDT) {
1335
1320
// Ideally, we want to calculate tagged stack base pointer, and rewrite all
@@ -1339,10 +1324,10 @@ bool HWAddressSanitizer::instrumentStack(
1339
1324
// This generates one extra instruction per alloca use.
1340
1325
unsigned int I = 0 ;
1341
1326
1342
- for (auto &KV : AllocasToInstrument) {
1327
+ for (auto &KV : SInfo. AllocasToInstrument ) {
1343
1328
auto N = I++;
1344
1329
auto *AI = KV.first ;
1345
- AllocaInfo &Info = KV.second ;
1330
+ memtag:: AllocaInfo &Info = KV.second ;
1346
1331
IRBuilder<> IRB (AI->getNextNode ());
1347
1332
1348
1333
// Replace uses of the alloca with tagged address.
@@ -1356,7 +1341,7 @@ bool HWAddressSanitizer::instrumentStack(
1356
1341
AI->replaceUsesWithIf (Replacement,
1357
1342
[AILong](Use &U) { return U.getUser () != AILong; });
1358
1343
1359
- for (auto *DDI : AllocaDbgMap.lookup (AI)) {
1344
+ for (auto *DDI : SInfo. AllocaDbgMap .lookup (AI)) {
1360
1345
// Prepend "tag_offset, N" to the dwarf expression.
1361
1346
// Tag offset logically applies to the alloca pointer, and it makes sense
1362
1347
// to put it at the beginning of the expression.
@@ -1376,21 +1361,22 @@ bool HWAddressSanitizer::instrumentStack(
1376
1361
tagAlloca (IRB, AI, UARTag, AlignedSize);
1377
1362
};
1378
1363
bool StandardLifetime =
1379
- UnrecognizedLifetimes.empty () &&
1380
- isStandardLifetime (Info.LifetimeStart , Info.LifetimeEnd , & GetDT () ,
1381
- ClMaxLifetimes);
1364
+ SInfo. UnrecognizedLifetimes .empty () &&
1365
+ memtag:: isStandardLifetime (Info.LifetimeStart , Info.LifetimeEnd ,
1366
+ & GetDT (), ClMaxLifetimes);
1382
1367
if (ShouldDetectUseAfterScope && StandardLifetime) {
1383
1368
IntrinsicInst *Start = Info.LifetimeStart [0 ];
1384
1369
IRB.SetInsertPoint (Start->getNextNode ());
1385
1370
tagAlloca (IRB, AI, Tag, Size);
1386
- if (!forAllReachableExits (GetDT (), GetPDT (), Start, Info.LifetimeEnd ,
1387
- RetVec, TagEnd)) {
1371
+ if (!memtag::forAllReachableExits (GetDT (), GetPDT (), Start,
1372
+ Info.LifetimeEnd , SInfo.RetVec ,
1373
+ TagEnd)) {
1388
1374
for (auto *End : Info.LifetimeEnd )
1389
1375
End->eraseFromParent ();
1390
1376
}
1391
1377
} else {
1392
1378
tagAlloca (IRB, AI, Tag, Size);
1393
- for (auto *RI : RetVec)
1379
+ for (auto *RI : SInfo. RetVec )
1394
1380
TagEnd (RI);
1395
1381
if (!StandardLifetime) {
1396
1382
for (auto &II : Info.LifetimeStart )
@@ -1400,7 +1386,7 @@ bool HWAddressSanitizer::instrumentStack(
1400
1386
}
1401
1387
}
1402
1388
}
1403
- for (auto &I : UnrecognizedLifetimes)
1389
+ for (auto &I : SInfo. UnrecognizedLifetimes )
1404
1390
I->eraseFromParent ();
1405
1391
return true ;
1406
1392
}
@@ -1424,7 +1410,7 @@ bool HWAddressSanitizer::isInterestingAlloca(const AllocaInst &AI) {
1424
1410
}
1425
1411
1426
1412
DenseMap<AllocaInst *, AllocaInst *> HWAddressSanitizer::padInterestingAllocas (
1427
- const MapVector<AllocaInst *, AllocaInfo> &AllocasToInstrument) {
1413
+ const MapVector<AllocaInst *, memtag:: AllocaInfo> &AllocasToInstrument) {
1428
1414
DenseMap<AllocaInst *, AllocaInst *> AllocaToPaddedAllocaMap;
1429
1415
for (auto &KV : AllocasToInstrument) {
1430
1416
AllocaInst *AI = KV.first ;
@@ -1469,52 +1455,13 @@ bool HWAddressSanitizer::sanitizeFunction(
1469
1455
1470
1456
SmallVector<InterestingMemoryOperand, 16 > OperandsToInstrument;
1471
1457
SmallVector<MemIntrinsic *, 16 > IntrinToInstrument;
1472
- MapVector<AllocaInst *, AllocaInfo> AllocasToInstrument;
1473
- SmallVector<Instruction *, 8 > RetVec;
1474
1458
SmallVector<Instruction *, 8 > LandingPadVec;
1475
- SmallVector<Instruction *, 4 > UnrecognizedLifetimes;
1476
- DenseMap<AllocaInst *, std::vector<DbgVariableIntrinsic *>> AllocaDbgMap;
1477
- bool CallsReturnTwice = false ;
1459
+
1460
+ memtag::StackInfoBuilder SIB (
1461
+ [ this ]( const AllocaInst &AI) { return isInterestingAlloca (AI); }) ;
1478
1462
for (auto &Inst : instructions (F)) {
1479
- if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
1480
- if (CI->canReturnTwice ()) {
1481
- CallsReturnTwice = true ;
1482
- }
1483
- }
1484
1463
if (InstrumentStack) {
1485
- if (AllocaInst *AI = dyn_cast<AllocaInst>(&Inst)) {
1486
- if (isInterestingAlloca (*AI))
1487
- AllocasToInstrument.insert ({AI, {}});
1488
- continue ;
1489
- }
1490
- auto *II = dyn_cast<IntrinsicInst>(&Inst);
1491
- if (II && (II->getIntrinsicID () == Intrinsic::lifetime_start ||
1492
- II->getIntrinsicID () == Intrinsic::lifetime_end)) {
1493
- AllocaInst *AI = findAllocaForValue (II->getArgOperand (1 ));
1494
- if (!AI) {
1495
- UnrecognizedLifetimes.push_back (&Inst);
1496
- continue ;
1497
- }
1498
- if (!isInterestingAlloca (*AI))
1499
- continue ;
1500
- if (II->getIntrinsicID () == Intrinsic::lifetime_start)
1501
- AllocasToInstrument[AI].LifetimeStart .push_back (II);
1502
- else
1503
- AllocasToInstrument[AI].LifetimeEnd .push_back (II);
1504
- continue ;
1505
- }
1506
- }
1507
-
1508
- Instruction *ExitUntag = getUntagLocationIfFunctionExit (Inst);
1509
- if (ExitUntag)
1510
- RetVec.push_back (ExitUntag);
1511
-
1512
- if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&Inst)) {
1513
- for (Value *V : DVI->location_ops ()) {
1514
- if (auto *Alloca = dyn_cast_or_null<AllocaInst>(V))
1515
- if (!AllocaDbgMap.count (Alloca) || AllocaDbgMap[Alloca].back () != DVI)
1516
- AllocaDbgMap[Alloca].push_back (DVI);
1517
- }
1464
+ SIB.visit (Inst);
1518
1465
}
1519
1466
1520
1467
if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
@@ -1527,22 +1474,24 @@ bool HWAddressSanitizer::sanitizeFunction(
1527
1474
IntrinToInstrument.push_back (MI);
1528
1475
}
1529
1476
1477
+ memtag::StackInfo &SInfo = SIB.get ();
1478
+
1530
1479
initializeCallbacks (*F.getParent ());
1531
1480
1532
1481
bool Changed = false ;
1533
1482
1534
1483
if (!LandingPadVec.empty ())
1535
1484
Changed |= instrumentLandingPads (LandingPadVec);
1536
1485
1537
- if (AllocasToInstrument.empty () && F.hasPersonalityFn () &&
1486
+ if (SInfo. AllocasToInstrument .empty () && F.hasPersonalityFn () &&
1538
1487
F.getPersonalityFn ()->getName () == kHwasanPersonalityThunkName ) {
1539
1488
// __hwasan_personality_thunk is a no-op for functions without an
1540
1489
// instrumented stack, so we can drop it.
1541
1490
F.setPersonalityFn (nullptr );
1542
1491
Changed = true ;
1543
1492
}
1544
1493
1545
- if (AllocasToInstrument.empty () && OperandsToInstrument.empty () &&
1494
+ if (SInfo. AllocasToInstrument .empty () && OperandsToInstrument.empty () &&
1546
1495
IntrinToInstrument.empty ())
1547
1496
return Changed;
1548
1497
@@ -1552,24 +1501,24 @@ bool HWAddressSanitizer::sanitizeFunction(
1552
1501
IRBuilder<> EntryIRB (InsertPt);
1553
1502
emitPrologue (EntryIRB,
1554
1503
/* WithFrameRecord*/ ClRecordStackHistory &&
1555
- Mapping.WithFrameRecord && !AllocasToInstrument.empty ());
1504
+ Mapping.WithFrameRecord &&
1505
+ !SInfo.AllocasToInstrument .empty ());
1556
1506
1557
- if (!AllocasToInstrument.empty ()) {
1507
+ if (!SInfo. AllocasToInstrument .empty ()) {
1558
1508
Value *StackTag =
1559
1509
ClGenerateTagsWithCalls ? nullptr : getStackBaseTag (EntryIRB);
1560
1510
// Calls to functions that may return twice (e.g. setjmp) confuse the
1561
1511
// postdominator analysis, and will leave us to keep memory tagged after
1562
1512
// function return. Work around this by always untagging at every return
1563
1513
// statement if return_twice functions are called.
1564
- instrumentStack (DetectUseAfterScope && !CallsReturnTwice,
1565
- AllocasToInstrument, UnrecognizedLifetimes, AllocaDbgMap,
1566
- RetVec, StackTag, GetDT, GetPDT);
1514
+ instrumentStack (DetectUseAfterScope && !SInfo.CallsReturnTwice , SIB.get (),
1515
+ StackTag, GetDT, GetPDT);
1567
1516
}
1568
1517
// Pad and align each of the allocas that we instrumented to stop small
1569
1518
// uninteresting allocas from hiding in instrumented alloca's padding and so
1570
1519
// that we have enough space to store real tags for short granules.
1571
1520
DenseMap<AllocaInst *, AllocaInst *> AllocaToPaddedAllocaMap =
1572
- padInterestingAllocas (AllocasToInstrument);
1521
+ padInterestingAllocas (SInfo. AllocasToInstrument );
1573
1522
1574
1523
if (!AllocaToPaddedAllocaMap.empty ()) {
1575
1524
for (auto &Inst : instructions (F)) {
0 commit comments