llvm.org GIT mirror llvm / bf93163
[esan|cfrag] Handle complex GEP instr in the cfrag tool Summary: Iterates all (except the first and the last) operands within each GEP instruction for instrumentation. Adds test struct_field_gep.ll. Reviewers: aizatsky Subscribers: vitalybuka, zhaoqin, kcc, eugenis, bruening, llvm-commits Differential Revision: http://reviews.llvm.org/D21242 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272442 91177308-0d34-0410-b5e6-96231b3b80d8 Qin Zhao 4 years ago
2 changed file(s) with 80 addition(s) and 35 deletion(s). Raw diff Collapse all Expand all
655655
656656 bool EfficiencySanitizer::instrumentGetElementPtr(Instruction *I, Module &M) {
657657 GetElementPtrInst *GepInst = dyn_cast(I);
658 if (GepInst == nullptr || !isa(GepInst->getSourceElementType()) ||
659 StructTyMap.count(GepInst->getSourceElementType()) == 0 ||
660 !GepInst->hasAllConstantIndices() ||
661 // Only handle simple struct field GEP.
662 GepInst->getNumIndices() != 2) {
658 bool Res = false;
659 if (GepInst == nullptr || GepInst->getNumIndices() == 1) {
663660 ++NumIgnoredGEPs;
664661 return false;
665662 }
666 StructType *StructTy = dyn_cast(GepInst->getSourceElementType());
667 if (shouldIgnoreStructType(StructTy)) {
663 Type *SourceTy = GepInst->getSourceElementType();
664 // Iterate all (except the first and the last) idx within each GEP instruction
665 // for possible nested struct field address calculation.
666 for (unsigned i = 1; i < GepInst->getNumIndices(); ++i) {
667 SmallVector IdxVec(GepInst->idx_begin(),
668 GepInst->idx_begin() + i);
669 StructType *StructTy = dyn_cast(
670 GetElementPtrInst::getIndexedType(SourceTy, IdxVec));
671 if (StructTy == nullptr || shouldIgnoreStructType(StructTy) ||
672 StructTyMap.count(StructTy) == 0)
673 continue;
674 // Get the StructTy's subfield index.
675 ConstantInt *Idx = dyn_cast(GepInst->getOperand(i+1));
676 if (Idx == nullptr || Idx->getZExtValue() > StructTy->getNumElements())
677 continue;
678 GlobalVariable *CounterArray = StructTyMap[StructTy];
679 if (CounterArray == nullptr)
680 return false;
681 IRBuilder<> IRB(I);
682 Constant *Indices[2];
683 // Xref http://llvm.org/docs/LangRef.html#i-getelementptr and
684 // http://llvm.org/docs/GetElementPtr.html.
685 // The first index of the GEP instruction steps through the first operand,
686 // i.e., the array itself.
687 Indices[0] = ConstantInt::get(IRB.getInt32Ty(), 0);
688 // The second index is the index within the array.
689 Indices[1] = ConstantInt::get(IRB.getInt32Ty(), Idx->getZExtValue());
690 Constant *Counter =
691 ConstantExpr::getGetElementPtr(
692 ArrayType::get(IRB.getInt64Ty(), StructTy->getNumElements()),
693 CounterArray, Indices);
694 Value *Load = IRB.CreateLoad(Counter);
695 IRB.CreateStore(IRB.CreateAdd(Load, ConstantInt::get(IRB.getInt64Ty(), 1)),
696 Counter);
697 Res = true;
698 }
699 if (Res)
700 ++NumInstrumentedGEPs;
701 else
668702 ++NumIgnoredGEPs;
669 return false;
670 }
671 ++NumInstrumentedGEPs;
672 // Use the last index as the index within the struct.
673 ConstantInt *Idx = dyn_cast(GepInst->getOperand(2));
674 if (Idx == nullptr || Idx->getZExtValue() > StructTy->getNumElements())
675 return false;
676
677 GlobalVariable *CounterArray = StructTyMap[StructTy];
678 if (CounterArray == nullptr)
679 return false;
680 IRBuilder<> IRB(I);
681 Constant *Indices[2];
682 // Xref http://llvm.org/docs/LangRef.html#i-getelementptr and
683 // http://llvm.org/docs/GetElementPtr.html.
684 // The first index of the GEP instruction steps through the first operand,
685 // i.e., the array itself.
686 Indices[0] = ConstantInt::get(IRB.getInt32Ty(), 0);
687 // The second index is the index within the array.
688 Indices[1] = ConstantInt::get(IRB.getInt32Ty(), Idx->getZExtValue());
689 Constant *Counter =
690 ConstantExpr::getGetElementPtr(ArrayType::get(IRB.getInt64Ty(),
691 StructTy->getNumElements()),
692 CounterArray, Indices);
693 Value *Load = IRB.CreateLoad(Counter);
694 IRB.CreateStore(IRB.CreateAdd(Load, ConstantInt::get(IRB.getInt64Ty(), 1)),
695 Counter);
696 return true;
703 return Res;
697704 }
698705
699706 int EfficiencySanitizer::getMemoryAccessFuncIndex(Value *Addr,
0 ; Test the complex GetElementPtr instruction handling in the EfficiencySanitizer
1 ; cache fragmentation tool.
2 ;
3 ; RUN: opt < %s -esan -esan-cache-frag -S | FileCheck %s
4
5 ; Code from http://llvm.org/docs/LangRef.html#getelementptr-instruction
6 ; struct RT {
7 ; char A;
8 ; int B[10][20];
9 ; char C;
10 ; };
11 ; struct ST {
12 ; int X;
13 ; double Y;
14 ; struct RT Z;
15 ; };
16 ;
17 ; int *foo(struct ST *s) {
18 ; return &s[1].Z.B[5][13];
19 ; }
20
21 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
22 %struct.ST = type { i32, double, %struct.RT }
23
24 define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp {
25 entry:
26 %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
27 ret i32* %arrayidx
28 }
29
30 ; CHECK: %0 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @"struct.ST#3#13#3#11", i32 0, i32 2)
31 ; CHECK-NEXT: %1 = add i64 %0, 1
32 ; CHECK-NEXT: store i64 %1, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @"struct.ST#3#13#3#11", i32 0, i32 2)
33 ; CHECK-NEXT: %2 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @"struct.RT#3#11#14#11", i32 0, i32 1)
34 ; CHECK-NEXT: %3 = add i64 %2, 1
35 ; CHECK-NEXT: store i64 %3, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @"struct.RT#3#11#14#11", i32 0, i32 1)
36 ; CHECK-NEXT: %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13
37 ; CHECK-NEXT: ret i32* %arrayidx