summaryrefslogtreecommitdiff
path: root/lib/esan
diff options
context:
space:
mode:
authorQin Zhao <zhaoqin@google.com>2016-06-02 18:45:25 +0000
committerQin Zhao <zhaoqin@google.com>2016-06-02 18:45:25 +0000
commita2e782d69b1919336711eabe42eee6ac3ae60641 (patch)
tree03a17b40f2987d0a45e6739e5e0611d47b943f52 /lib/esan
parent4deefb03523c51ca2eba3fabff692a47f24e1bfa (diff)
[esan|cfrag] Add struct info registration
Summary: Adds StructInfo to CacheFragInfo to match the LLVM's EfficiencySanitizer structs. Uses StructHashMap to keep track of the struct info used by the app. Adds registerStructInfo/unregisterStructInfo to add/remove struct infos to/from StructHashMap. updates test struct-simple.cpp with more C structs. Reviewers: aizatsky, filcab Subscribers: filcab, zhaoqin, llvm-commits, eugenis, vitalybuka, kcc, bruening, kubabrecka Differential Revision: http://reviews.llvm.org/D20590 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@271564 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/esan')
-rw-r--r--lib/esan/cache_frag.cpp75
1 files changed, 69 insertions, 6 deletions
diff --git a/lib/esan/cache_frag.cpp b/lib/esan/cache_frag.cpp
index da168dc0c..af36d90bb 100644
--- a/lib/esan/cache_frag.cpp
+++ b/lib/esan/cache_frag.cpp
@@ -13,13 +13,17 @@
//===----------------------------------------------------------------------===//
#include "esan.h"
+#include "sanitizer_common/sanitizer_addrhashmap.h"
+#include "sanitizer_common/sanitizer_placement_new.h"
namespace __esan {
+//===-- Struct field access counter runtime -------------------------------===//
+
// This should be kept consistent with LLVM's EfficiencySanitizer StructInfo.
struct StructInfo {
const char *StructName;
- u32 NumOfFields;
+ u32 NumFields;
u64 *FieldCounters;
const char **FieldTypeNames;
};
@@ -28,32 +32,91 @@ struct StructInfo {
// The tool-specific information per compilation unit (module).
struct CacheFragInfo {
const char *UnitName;
- u32 NumOfStructs;
+ u32 NumStructs;
StructInfo *Structs;
};
+struct StructCounter {
+ StructInfo *Struct;
+ u64 Count; // The total access count of the struct.
+ u32 Variance; // Variance score for the struct layout access.
+};
+
+// We use StructHashMap to keep track of an unique copy of StructCounter.
+typedef AddrHashMap<StructCounter, 31051> StructHashMap;
+struct Context {
+ StructHashMap StructMap;
+ u32 NumStructs;
+ u64 TotalCount; // The total access count of all structs.
+};
+static Context *Ctx;
+
+static void registerStructInfo(CacheFragInfo *CacheFrag) {
+ for (u32 i = 0; i < CacheFrag->NumStructs; ++i) {
+ StructInfo *Struct = &CacheFrag->Structs[i];
+ StructHashMap::Handle H(&Ctx->StructMap, (uptr)Struct->FieldCounters);
+ if (H.created()) {
+ VPrintf(2, " Register %s: %u fields\n",
+ Struct->StructName, Struct->NumFields);
+ H->Struct = Struct;
+ ++Ctx->NumStructs;
+ } else {
+ VPrintf(2, " Duplicated %s: %u fields\n",
+ Struct->StructName, Struct->NumFields);
+ }
+ }
+}
+
+static void unregisterStructInfo(CacheFragInfo *CacheFrag) {
+ // FIXME: if the library is unloaded before finalizeCacheFrag, we should
+ // collect the result for later report.
+ for (u32 i = 0; i < CacheFrag->NumStructs; ++i) {
+ StructInfo *Struct = &CacheFrag->Structs[i];
+ StructHashMap::Handle H(&Ctx->StructMap, (uptr)Struct->FieldCounters, true);
+ if (H.exists()) {
+ VPrintf(2, " Unregister %s: %u fields\n",
+ Struct->StructName, Struct->NumFields);
+ --Ctx->NumStructs;
+ } else {
+ VPrintf(2, " Duplicated %s: %u fields\n",
+ Struct->StructName, Struct->NumFields);
+ }
+ }
+}
+
+static void reportStructSummary() {
+ // FIXME: iterate StructHashMap and generate the final report.
+ Report("%s is not finished: nothing yet to report\n", SanitizerToolName);
+}
+
//===-- Init/exit functions -----------------------------------------------===//
void processCacheFragCompilationUnitInit(void *Ptr) {
CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr;
VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n",
- __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumOfStructs);
+ __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumStructs);
+ registerStructInfo(CacheFrag);
}
void processCacheFragCompilationUnitExit(void *Ptr) {
CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr;
VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n",
- __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumOfStructs);
+ __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumStructs);
+ unregisterStructInfo(CacheFrag);
}
void initializeCacheFrag() {
VPrintf(2, "in esan::%s\n", __FUNCTION__);
+ // We use placement new to initialize Ctx before C++ static initializaion.
+ // We make CtxMem 8-byte aligned for atomic operations in AddrHashMap.
+ static u64 CtxMem[sizeof(Context) / sizeof(u64) + 1];
+ Ctx = new(CtxMem) Context();
+ Ctx->NumStructs = 0;
}
int finalizeCacheFrag() {
VPrintf(2, "in esan::%s\n", __FUNCTION__);
- // FIXME: add the cache fragmentation final report.
- Report("%s is not finished: nothing yet to report\n", SanitizerToolName);
+ reportStructSummary();
return 0;
}