[llvm] r271547 - [esan|cfrag] Create the cfrag struct array for the runtime

Qin Zhao via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 2 10:30:47 PDT 2016


Author: zhaoqin
Date: Thu Jun  2 12:30:47 2016
New Revision: 271547

URL: http://llvm.org/viewvc/llvm-project?rev=271547&view=rev
Log:
[esan|cfrag] Create the cfrag struct array for the runtime

Summary:
Fills the cfrag struct variable with an array of struct information
variables.

Reviewers: aizatsky, bruening

Subscribers: bruening, kcc, vitalybuka, eugenis, llvm-commits, zhaoqin

Differential Revision: http://reviews.llvm.org/D20661

Modified:
    llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp

Modified: llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp?rev=271547&r1=271546&r2=271547&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp Thu Jun  2 12:30:47 2016
@@ -30,6 +30,7 @@
 #include "llvm/IR/Type.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 
@@ -61,6 +62,7 @@ STATISTIC(NumInstrumentedStores, "Number
 STATISTIC(NumFastpaths, "Number of instrumented fastpaths");
 STATISTIC(NumAccessesWithIrregularSize,
           "Number of accesses with a size outside our targeted callout sizes");
+STATISTIC(NumIgnoredStructs, "Number of ignored structs");
 
 static const uint64_t EsanCtorAndDtorPriority = 0;
 static const char *const EsanModuleCtorName = "esan.module_ctor";
@@ -85,6 +87,10 @@ static const int ShadowScale[] = {
   6, // ESAN_WorkingSet: 64B:1B, so 64 to 1 == >>6.
 };
 
+// MaxStructCounterNameSize is a soft size limit to avoid insanely long
+// names for those extremely large structs.
+static const unsigned MaxStructCounterNameSize = 512;
+
 namespace {
 
 static EfficiencySanitizerOptions
@@ -130,6 +136,9 @@ public:
 private:
   bool initOnModule(Module &M);
   void initializeCallbacks(Module &M);
+  bool shouldIgnoreStructType(StructType *StructTy);
+  void createStructCounterName(
+      StructType *StructTy, SmallString<MaxStructCounterNameSize> &NameStr);
   GlobalVariable *createCacheFragInfoGV(Module &M, Constant *UnitName);
   Constant *createEsanInitToolInfoArg(Module &M);
   void createDestructor(Module &M, Constant *ToolInfoArg);
@@ -220,6 +229,39 @@ void EfficiencySanitizer::initializeCall
                             IRB.getInt32Ty(), IntptrTy, nullptr));
 }
 
+bool EfficiencySanitizer::shouldIgnoreStructType(StructType *StructTy) {
+  if (StructTy == nullptr || StructTy->isOpaque() /* no struct body */)
+    return true;
+  return false;
+}
+
+void EfficiencySanitizer::createStructCounterName(
+    StructType *StructTy, SmallString<MaxStructCounterNameSize> &NameStr) {
+  // Append NumFields and field type ids to avoid struct conflicts
+  // with the same name but different fields.
+  if (StructTy->hasName())
+    NameStr += StructTy->getName();
+  else
+    NameStr += "struct.anon";
+  // We allow the actual size of the StructCounterName to be larger than
+  // MaxStructCounterNameSize and append #NumFields and at least one
+  // field type id.
+  // Append #NumFields.
+  NameStr += "#";
+  Twine(StructTy->getNumElements()).toVector(NameStr);
+  // Append struct field type ids in the reverse order.
+  for (int i = StructTy->getNumElements() - 1; i >= 0; --i) {
+    NameStr += "#";
+    Twine(StructTy->getElementType(i)->getTypeID()).toVector(NameStr);
+    if (NameStr.size() >= MaxStructCounterNameSize)
+      break;
+  }
+  if (StructTy->isLiteral()) {
+    // End with # for literal struct.
+    NameStr += "#";
+  }
+}
+
 // Create the global variable for the cache-fragmentation tool.
 GlobalVariable *EfficiencySanitizer::createCacheFragInfoGV(
     Module &M, Constant *UnitName) {
@@ -228,12 +270,13 @@ GlobalVariable *EfficiencySanitizer::cre
   auto *Int8PtrTy = Type::getInt8PtrTy(*Ctx);
   auto *Int8PtrPtrTy = Int8PtrTy->getPointerTo();
   auto *Int32Ty = Type::getInt32Ty(*Ctx);
+  auto *Int64Ty = Type::getInt64Ty(*Ctx);
   auto *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
   // This structure should be kept consistent with the StructInfo struct
   // in the runtime library.
   // struct StructInfo {
   //   const char *StructName;
-  //   u32 NumOfFields;
+  //   u32 NumFields;
   //   u64 *FieldCounters;
   //   const char **FieldTypeNames;
   // };
@@ -244,20 +287,87 @@ GlobalVariable *EfficiencySanitizer::cre
   // in the runtime library.
   // struct CacheFragInfo {
   //   const char *UnitName;
-  //   u32 NumOfStructs;
+  //   u32 NumStructs;
   //   StructInfo *Structs;
   // };
   auto *CacheFragInfoTy =
     StructType::get(Int8PtrTy, Int32Ty, StructInfoPtrTy, nullptr);
 
   std::vector<StructType *> Vec = M.getIdentifiedStructTypes();
-  // FIXME: iterate over Vec and create the StructInfo array.
+  unsigned NumStructs = 0;
+  SmallVector<Constant *, 16> Initializers;
+
+  for (auto &StructTy : Vec) {
+    if (shouldIgnoreStructType(StructTy)) {
+      ++NumIgnoredStructs;
+      continue;
+    }
+    ++NumStructs;
+
+    // StructName.
+    SmallString<MaxStructCounterNameSize> CounterNameStr;
+    createStructCounterName(StructTy, CounterNameStr);
+    GlobalVariable *StructCounterName = createPrivateGlobalForString(
+        M, CounterNameStr, /*AllowMerging*/true);
+
+    // FieldCounters.
+    // We create the counter array with StructCounterName and weak linkage
+    // so that the structs with the same name and layout from different
+    // compilation units will be merged into one.
+    auto *CounterArrayTy = ArrayType::get(Int64Ty, StructTy->getNumElements());
+    GlobalVariable *Counters =
+      new GlobalVariable(M, CounterArrayTy, false,
+                         GlobalVariable::WeakAnyLinkage,
+                         ConstantAggregateZero::get(CounterArrayTy),
+                         CounterNameStr);
+
+    // FieldTypeNames.
+    // We pass the field type name array to the runtime for better reporting.
+    auto *TypeNameArrayTy = ArrayType::get(Int8PtrTy, StructTy->getNumElements());
+    GlobalVariable *TypeName =
+      new GlobalVariable(M, TypeNameArrayTy, true,
+                         GlobalVariable::InternalLinkage, nullptr);
+    SmallVector<Constant *, 16> TypeNameVec;
+    for (unsigned i = 0; i < StructTy->getNumElements(); ++i) {
+      Type *Ty = StructTy->getElementType(i);
+      std::string Str;
+      raw_string_ostream StrOS(Str);
+      Ty->print(StrOS);
+      TypeNameVec.push_back(
+          ConstantExpr::getPointerCast(
+              createPrivateGlobalForString(M, StrOS.str(), true),
+              Int8PtrTy));
+    }
+    TypeName->setInitializer(ConstantArray::get(TypeNameArrayTy, TypeNameVec));
+
+    Initializers.push_back(
+        ConstantStruct::get(
+            StructInfoTy,
+            ConstantExpr::getPointerCast(StructCounterName, Int8PtrTy),
+            ConstantInt::get(Int32Ty, StructTy->getNumElements()),
+            ConstantExpr::getPointerCast(Counters, Int64PtrTy),
+            ConstantExpr::getPointerCast(TypeName, Int8PtrPtrTy),
+            nullptr));
+  }
+  // Structs.
+  Constant *StructInfo;
+  if (NumStructs == 0) {
+    StructInfo = ConstantPointerNull::get(StructInfoPtrTy);
+  } else {
+    auto *StructInfoArrayTy = ArrayType::get(StructInfoTy, NumStructs);
+    StructInfo = ConstantExpr::getPointerCast(
+        new GlobalVariable(M, StructInfoArrayTy, false,
+                           GlobalVariable::InternalLinkage,
+                           ConstantArray::get(StructInfoArrayTy, Initializers)),
+        StructInfoPtrTy);
+  }
+
   auto *CacheFragInfoGV = new GlobalVariable(
       M, CacheFragInfoTy, true, GlobalVariable::InternalLinkage,
       ConstantStruct::get(CacheFragInfoTy,
                           UnitName,
-                          ConstantInt::get(Int32Ty, Vec.size()),
-                          ConstantPointerNull::get(StructInfoPtrTy),
+                          ConstantInt::get(Int32Ty, NumStructs),
+                          StructInfo,
                           nullptr));
   return CacheFragInfoGV;
 }




More information about the llvm-commits mailing list