llvm.org GIT mirror llvm / 9ac0d05
[esan|cfrag] Create the skeleton of cfrag variable for the runtime Summary: Creates a global variable containing preliminary information for the cache-fragmentation tool runtime. Passes a pointer to the variable (null if no variable is created) to the compilation unit init and exit routines in the runtime. Reviewers: aizatsky, bruening Subscribers: filcab, kubabrecka, bruening, kcc, vitalybuka, eugenis, llvm-commits, zhaoqin Differential Revision: http://reviews.llvm.org/D20541 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271298 91177308-0d34-0410-b5e6-96231b3b80d8 Qin Zhao 4 years ago
3 changed file(s) with 97 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
101101 return Options;
102102 }
103103
104 // Create a constant for Str so that we can pass it to the run-time lib.
105 static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str,
106 bool AllowMerging) {
107 Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str);
108 // We use private linkage for module-local strings. If they can be merged
109 // with another one, we set the unnamed_addr attribute.
110 GlobalVariable *GV =
111 new GlobalVariable(M, StrConst->getType(), true,
112 GlobalValue::PrivateLinkage, StrConst, "");
113 if (AllowMerging)
114 GV->setUnnamedAddr(true);
115 GV->setAlignment(1); // Strings may not be merged w/o setting align 1.
116 return GV;
117 }
118
104119 /// EfficiencySanitizer: instrument each module to find performance issues.
105120 class EfficiencySanitizer : public ModulePass {
106121 public:
114129 private:
115130 bool initOnModule(Module &M);
116131 void initializeCallbacks(Module &M);
117 GlobalVariable *createEsanInitToolGV(Module &M);
118 void createDestructor(Module &M, GlobalVariable *GV);
132 GlobalVariable *createCacheFragInfoGV(Module &M, Constant *UnitName);
133 Constant *createEsanInitToolInfoArg(Module &M);
134 void createDestructor(Module &M, Constant *ToolInfoArg);
119135 bool runOnFunction(Function &F, Module &M);
120136 bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
121137 bool instrumentMemIntrinsic(MemIntrinsic *MI);
203219 IRB.getInt32Ty(), IntptrTy, nullptr));
204220 }
205221
206 // Create the tool-specific global variable passed to EsanInit and EsanExit.
207 GlobalVariable *EfficiencySanitizer::createEsanInitToolGV(Module &M) {
208 GlobalVariable *GV = nullptr;
209 // FIXME: create the tool specific global variable.
210 if (GV == nullptr) {
211 GV = new GlobalVariable(M, IntptrTy, true, GlobalVariable::InternalLinkage,
212 Constant::getNullValue(IntptrTy));
213 }
214 return GV;
215 }
216
217 void EfficiencySanitizer::createDestructor(Module &M, GlobalVariable *GV) {
222 // Create the global variable for the cache-fragmentation tool.
223 GlobalVariable *EfficiencySanitizer::createCacheFragInfoGV(
224 Module &M, Constant *UnitName) {
225 assert(Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag);
226
227 auto *Int8PtrTy = Type::getInt8PtrTy(*Ctx);
228 auto *Int8PtrPtrTy = Int8PtrTy->getPointerTo();
229 auto *Int32Ty = Type::getInt32Ty(*Ctx);
230 auto *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
231 // This structure should be kept consistent with the StructInfo struct
232 // in the runtime library.
233 // struct StructInfo {
234 // const char *StructName;
235 // u32 NumOfFields;
236 // u64 *FieldCounters;
237 // const char **FieldTypeNames;
238 // };
239 auto *StructInfoTy =
240 StructType::get(Int8PtrTy, Int32Ty, Int64PtrTy, Int8PtrPtrTy, nullptr);
241 auto *StructInfoPtrTy = StructInfoTy->getPointerTo();
242 // This structure should be kept consistent with the CacheFragInfo struct
243 // in the runtime library.
244 // struct CacheFragInfo {
245 // const char *UnitName;
246 // u32 NumOfStructs;
247 // StructInfo *Structs;
248 // };
249 auto *CacheFragInfoTy =
250 StructType::get(Int8PtrTy, Int32Ty, StructInfoPtrTy, nullptr);
251
252 std::vector Vec = M.getIdentifiedStructTypes();
253 // FIXME: iterate over Vec and create the StructInfo array.
254 auto *CacheFragInfoGV = new GlobalVariable(
255 M, CacheFragInfoTy, true, GlobalVariable::InternalLinkage,
256 ConstantStruct::get(CacheFragInfoTy,
257 UnitName,
258 ConstantInt::get(Int32Ty, Vec.size()),
259 ConstantPointerNull::get(StructInfoPtrTy),
260 nullptr));
261 return CacheFragInfoGV;
262 }
263
264 // Create the tool-specific argument passed to EsanInit and EsanExit.
265 Constant *EfficiencySanitizer::createEsanInitToolInfoArg(Module &M) {
266 // This structure contains tool-specific information about each compilation
267 // unit (module) and is passed to the runtime library.
268 GlobalVariable *ToolInfoGV = nullptr;
269
270 auto *Int8PtrTy = Type::getInt8PtrTy(*Ctx);
271 // Compilation unit name.
272 auto *UnitName = ConstantExpr::getPointerCast(
273 createPrivateGlobalForString(M, M.getModuleIdentifier(), true),
274 Int8PtrTy);
275
276 // Create the tool-specific variable.
277 if (Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag)
278 ToolInfoGV = createCacheFragInfoGV(M, UnitName);
279
280 if (ToolInfoGV != nullptr)
281 return ConstantExpr::getPointerCast(ToolInfoGV, Int8PtrTy);
282
283 // Create the null pointer if no tool-specific variable created.
284 return ConstantPointerNull::get(Int8PtrTy);
285 }
286
287 void EfficiencySanitizer::createDestructor(Module &M, Constant *ToolInfoArg) {
288 PointerType *Int8PtrTy = Type::getInt8PtrTy(*Ctx);
218289 EsanDtorFunction = Function::Create(FunctionType::get(Type::getVoidTy(*Ctx),
219290 false),
220291 GlobalValue::InternalLinkage,
223294 IRBuilder<> IRB_Dtor(EsanDtorFunction->getEntryBlock().getTerminator());
224295 Function *EsanExit = checkSanitizerInterfaceFunction(
225296 M.getOrInsertFunction(EsanExitName, IRB_Dtor.getVoidTy(),
226 IntptrTy, nullptr));
297 Int8PtrTy, nullptr));
227298 EsanExit->setLinkage(Function::ExternalLinkage);
228 IRB_Dtor.CreateCall(EsanExit,
229 {IRB_Dtor.CreatePointerCast(GV, IntptrTy)});
299 IRB_Dtor.CreateCall(EsanExit, {ToolInfoArg});
230300 appendToGlobalDtors(M, EsanDtorFunction, EsanCtorAndDtorPriority);
231301 }
232302
235305 const DataLayout &DL = M.getDataLayout();
236306 IRBuilder<> IRB(M.getContext());
237307 IntegerType *OrdTy = IRB.getInt32Ty();
308 PointerType *Int8PtrTy = Type::getInt8PtrTy(*Ctx);
238309 IntptrTy = DL.getIntPtrType(M.getContext());
239310 // Create the variable passed to EsanInit and EsanExit.
240 GlobalVariable *GV = createEsanInitToolGV(M);
311 Constant *ToolInfoArg = createEsanInitToolInfoArg(M);
241312 // Constructor
242313 std::tie(EsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions(
243 M, EsanModuleCtorName, EsanInitName, /*InitArgTypes=*/{OrdTy, IntptrTy},
314 M, EsanModuleCtorName, EsanInitName, /*InitArgTypes=*/{OrdTy, Int8PtrTy},
244315 /*InitArgs=*/{
245316 ConstantInt::get(OrdTy, static_cast(Options.ToolType)),
246 ConstantExpr::getPointerCast(GV, IntptrTy)});
317 ToolInfoArg});
247318 appendToGlobalCtors(M, EsanCtorFunction, EsanCtorAndDtorPriority);
248319
249 createDestructor(M, GV);
320 createDestructor(M, ToolInfoArg);
250321 return true;
251322 }
252323
253253 ; Top-level:
254254
255255 ; CHECK: define internal void @esan.module_ctor()
256 ; CHECK: call void @__esan_init(i32 1, i64 ptrtoint (i64* @0 to i64))
256 ; CHECK: call void @__esan_init(i32 1, i8* bitcast ({ i8*, i32, { i8*, i32, i64*, i8** }* }* @1 to i8*))
257257 ; CHECK: define internal void @esan.module_dtor()
258 ; CHECK: call void @__esan_exit(i64 ptrtoint (i64* @0 to i64))
258 ; CHECK: call void @__esan_exit(i8* bitcast ({ i8*, i32, { i8*, i32, i64*, i8** }* }* @1 to i8*))
160160 ; Top-level:
161161
162162 ; CHECK: define internal void @esan.module_ctor()
163 ; CHECK: call void @__esan_init(i32 2, i64 ptrtoint (i64* @0 to i64))
163 ; CHECK: call void @__esan_init(i32 2, i8* null)
164 ; CHECK: define internal void @esan.module_dtor()
165 ; CHECK: call void @__esan_exit(i8* null)