Skip to content

Commit

Permalink
[esan|cfrag] Create the cfrag struct array for the runtime
Browse files Browse the repository at this point in the history
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271547 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
zhaoqin committed Jun 2, 2016
1 parent 408a761 commit 5682914
Showing 1 changed file with 115 additions and 5 deletions.
120 changes: 115 additions & 5 deletions lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -61,6 +62,7 @@ STATISTIC(NumInstrumentedStores, "Number of instrumented stores");
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";
Expand All @@ -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
Expand Down Expand Up @@ -130,6 +136,9 @@ class EfficiencySanitizer : public ModulePass {
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);
Expand Down Expand Up @@ -220,6 +229,39 @@ void EfficiencySanitizer::initializeCallbacks(Module &M) {
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) {
Expand All @@ -228,12 +270,13 @@ GlobalVariable *EfficiencySanitizer::createCacheFragInfoGV(
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;
// };
Expand All @@ -244,20 +287,87 @@ GlobalVariable *EfficiencySanitizer::createCacheFragInfoGV(
// 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;
}
Expand Down

0 comments on commit 5682914

Please sign in to comment.