[llvm] r257970 - Introduce sanstats tool and llvm::CreateSanitizerStatReport function.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 15 16:31:11 PST 2016


Author: pcc
Date: Fri Jan 15 18:31:11 2016
New Revision: 257970

URL: http://llvm.org/viewvc/llvm-project?rev=257970&view=rev
Log:
Introduce sanstats tool and llvm::CreateSanitizerStatReport function.

This is part of a new statistics gathering feature for the sanitizers.
See clang/docs/SanitizerStats.rst for further info and docs.

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

Added:
    llvm/trunk/include/llvm/Transforms/Utils/SanitizerStats.h
    llvm/trunk/lib/Transforms/Utils/SanitizerStats.cpp
    llvm/trunk/test/tools/sanstats/
    llvm/trunk/test/tools/sanstats/elf.test
    llvm/trunk/tools/sanstats/
    llvm/trunk/tools/sanstats/CMakeLists.txt
    llvm/trunk/tools/sanstats/Makefile
    llvm/trunk/tools/sanstats/sanstats.cpp
Modified:
    llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
    llvm/trunk/test/CMakeLists.txt
    llvm/trunk/test/lit.cfg
    llvm/trunk/tools/Makefile

Added: llvm/trunk/include/llvm/Transforms/Utils/SanitizerStats.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SanitizerStats.h?rev=257970&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/SanitizerStats.h (added)
+++ llvm/trunk/include/llvm/Transforms/Utils/SanitizerStats.h Fri Jan 15 18:31:11 2016
@@ -0,0 +1,56 @@
+//===- SanitizerStats.h - Sanitizer statistics gathering  -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Declares functions and data structures for sanitizer statistics gathering.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SANITIZERSTATS_H
+#define LLVM_TRANSFORMS_UTILS_SANITIZERSTATS_H
+
+#include "llvm/IR/IRBuilder.h"
+
+namespace llvm {
+
+// Number of bits in data that are used for the sanitizer kind. Needs to match
+// __sanitizer::kKindBits in compiler-rt/lib/stats/stats.h
+enum { kSanitizerStatKindBits = 3 };
+
+enum SanitizerStatKind {
+  SanStat_CFI_VCall,
+  SanStat_CFI_NVCall,
+  SanStat_CFI_DerivedCast,
+  SanStat_CFI_UnrelatedCast,
+  SanStat_CFI_ICall,
+};
+
+struct SanitizerStatReport {
+  SanitizerStatReport(Module *M);
+
+  /// Generates code into B that increments a location-specific counter tagged
+  /// with the given sanitizer kind SK.
+  void create(IRBuilder<> &B, SanitizerStatKind SK);
+
+  /// Finalize module stats array and add global constructor to register it.
+  void finish();
+
+private:
+  Module *M;
+  GlobalVariable *ModuleStatsGV;
+  ArrayType *StatTy;
+  StructType *EmptyModuleStatsTy;
+
+  std::vector<Constant *> Inits;
+  ArrayType *makeModuleStatsArrayTy();
+  StructType *makeModuleStatsTy();
+};
+
+}
+
+#endif

Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=257970&r1=257969&r2=257970&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)
+++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Fri Jan 15 18:31:11 2016
@@ -30,6 +30,7 @@ add_llvm_library(LLVMTransformUtils
   ModuleUtils.cpp
   PromoteMemoryToRegister.cpp
   SSAUpdater.cpp
+  SanitizerStats.cpp
   SimplifyCFG.cpp
   SimplifyIndVar.cpp
   SimplifyInstructions.cpp

Added: llvm/trunk/lib/Transforms/Utils/SanitizerStats.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SanitizerStats.cpp?rev=257970&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SanitizerStats.cpp (added)
+++ llvm/trunk/lib/Transforms/Utils/SanitizerStats.cpp Fri Jan 15 18:31:11 2016
@@ -0,0 +1,108 @@
+//===- SanitizerStats.cpp - Sanitizer statistics gathering ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements code generation for sanitizer statistics gathering.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/SanitizerStats.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+
+using namespace llvm;
+
+SanitizerStatReport::SanitizerStatReport(Module *M) : M(M) {
+  StatTy = ArrayType::get(Type::getInt8PtrTy(M->getContext()), 2);
+  EmptyModuleStatsTy = makeModuleStatsTy();
+
+  ModuleStatsGV = new GlobalVariable(*M, EmptyModuleStatsTy, false,
+                                     GlobalValue::InternalLinkage, 0);
+}
+
+ArrayType *SanitizerStatReport::makeModuleStatsArrayTy() {
+  return ArrayType::get(StatTy, Inits.size());
+}
+
+StructType *SanitizerStatReport::makeModuleStatsTy() {
+  return StructType::get(M->getContext(), {Type::getInt8PtrTy(M->getContext()),
+                                           Type::getInt32Ty(M->getContext()),
+                                           makeModuleStatsArrayTy()});
+}
+
+void SanitizerStatReport::create(IRBuilder<> &B, SanitizerStatKind SK) {
+  Function *F = B.GetInsertBlock()->getParent();
+  Module *M = F->getParent();
+  PointerType *Int8PtrTy = B.getInt8PtrTy();
+  IntegerType *IntPtrTy = B.getIntPtrTy(M->getDataLayout());
+  ArrayType *StatTy = ArrayType::get(Int8PtrTy, 2);
+
+  Inits.push_back(ConstantArray::get(
+      StatTy,
+      {Constant::getNullValue(Int8PtrTy),
+       ConstantExpr::getIntToPtr(
+           ConstantInt::get(IntPtrTy, uint64_t(SK) << (IntPtrTy->getBitWidth() -
+                                                       kSanitizerStatKindBits)),
+           Int8PtrTy)}));
+
+  FunctionType *StatReportTy =
+      FunctionType::get(B.getVoidTy(), Int8PtrTy, false);
+  Constant *StatReport = M->getOrInsertFunction(
+      "__sanitizer_stat_report", StatReportTy);
+
+  auto InitAddr = ConstantExpr::getGetElementPtr(
+      EmptyModuleStatsTy, ModuleStatsGV,
+      ArrayRef<Constant *>{
+          ConstantInt::get(IntPtrTy, 0), ConstantInt::get(B.getInt32Ty(), 2),
+          ConstantInt::get(IntPtrTy, Inits.size() - 1),
+      });
+  B.CreateCall(StatReport, ConstantExpr::getBitCast(InitAddr, Int8PtrTy));
+}
+
+void SanitizerStatReport::finish() {
+  if (Inits.empty()) {
+    ModuleStatsGV->eraseFromParent();
+    return;
+  }
+
+  PointerType *Int8PtrTy = Type::getInt8PtrTy(M->getContext());
+  IntegerType *Int32Ty = Type::getInt32Ty(M->getContext());
+  Type *VoidTy = Type::getVoidTy(M->getContext());
+
+  // Create a new ModuleStatsGV to replace the old one. We can't just set the
+  // old one's initializer because its type is different.
+  auto NewModuleStatsGV = new GlobalVariable(
+      *M, makeModuleStatsTy(), false, GlobalValue::InternalLinkage,
+      ConstantStruct::getAnon(
+          {Constant::getNullValue(Int8PtrTy),
+           ConstantInt::get(Int32Ty, Inits.size()),
+           ConstantArray::get(makeModuleStatsArrayTy(), Inits)}));
+  ModuleStatsGV->replaceAllUsesWith(
+      ConstantExpr::getBitCast(NewModuleStatsGV, ModuleStatsGV->getType()));
+  ModuleStatsGV->eraseFromParent();
+
+  // Create a global constructor to register NewModuleStatsGV.
+  auto F = Function::Create(FunctionType::get(VoidTy, false),
+                            GlobalValue::InternalLinkage, "", M);
+  auto BB = BasicBlock::Create(M->getContext(), "", F);
+  IRBuilder<> B(BB);
+
+  FunctionType *StatInitTy = FunctionType::get(VoidTy, Int8PtrTy, false);
+  Constant *StatInit = M->getOrInsertFunction(
+      "__sanitizer_stat_init", StatInitTy);
+
+  B.CreateCall(StatInit, ConstantExpr::getBitCast(NewModuleStatsGV, Int8PtrTy));
+  B.CreateRetVoid();
+
+  appendToGlobalCtors(*M, F, 0);
+}

Modified: llvm/trunk/test/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CMakeLists.txt?rev=257970&r1=257969&r2=257970&view=diff
==============================================================================
--- llvm/trunk/test/CMakeLists.txt (original)
+++ llvm/trunk/test/CMakeLists.txt Fri Jan 15 18:31:11 2016
@@ -61,6 +61,7 @@ set(LLVM_TEST_DEPENDS
           obj2yaml
           opt
           sancov
+          sanstats
           verify-uselistorder
           yaml-bench
           yaml2obj

Modified: llvm/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/lit.cfg?rev=257970&r1=257969&r2=257970&view=diff
==============================================================================
--- llvm/trunk/test/lit.cfg (original)
+++ llvm/trunk/test/lit.cfg Fri Jan 15 18:31:11 2016
@@ -282,6 +282,7 @@ for pattern in [r"\bbugpoint\b(?!-)",
                 r"\bFileCheck\b",
                 r"\bobj2yaml\b",
                 NOJUNK + r"\bsancov\b",
+                NOJUNK + r"\bsanstats\b",
                 r"\byaml2obj\b",
                 r"\byaml-bench\b",
                 r"\bverify-uselistorder\b",

Added: llvm/trunk/test/tools/sanstats/elf.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/sanstats/elf.test?rev=257970&view=auto
==============================================================================
--- llvm/trunk/test/tools/sanstats/elf.test (added)
+++ llvm/trunk/test/tools/sanstats/elf.test Fri Jan 15 18:31:11 2016
@@ -0,0 +1,210 @@
+# RUN: yaml2obj -format=elf %s > %t1.o
+# RUN: yaml2obj -format=elf %s > %t2.o
+
+# RUN: echo -ne "\x04" > %t.stats
+
+# RUN: echo -n "%t1.o" >> %t.stats
+# RUN: echo -ne "\x00" >> %t.stats
+# RUN: echo -ne "\x01\x00\x00\x00\x01\x00\x00\x00" >> %t.stats
+# RUN: echo -ne "\x11\x00\x00\x00\x02\x00\x00\x20" >> %t.stats
+# RUN: echo -ne "\x21\x00\x00\x00\x03\x00\x00\x40" >> %t.stats
+# RUN: echo -ne "\x01\x00\x00\x00\x04\x00\x00\x60" >> %t.stats
+# RUN: echo -ne "\x11\x00\x00\x00\x05\x00\x00\x80" >> %t.stats
+# RUN: echo -ne "\x21\x00\x00\x00\x06\x00\x00\xa0" >> %t.stats
+# RUN: echo -ne "\x00\x00\x00\x00\x00\x00\x00\x00" >> %t.stats
+
+# RUN: echo -n "%t2.o" >> %t.stats
+# RUN: echo -ne "\x00" >> %t.stats
+# RUN: echo -ne "\x21\x00\x00\x00\x07\x00\x00\x00" >> %t.stats
+# RUN: echo -ne "\x11\x00\x00\x00\x08\x00\x00\x20" >> %t.stats
+# RUN: echo -ne "\x01\x00\x00\x00\x09\x00\x00\x40" >> %t.stats
+# RUN: echo -ne "\x21\x00\x00\x00\x0b\x00\x00\x60" >> %t.stats
+# RUN: echo -ne "\x11\x00\x00\x00\x0c\x00\x00\x80" >> %t.stats
+# RUN: echo -ne "\x01\x00\x00\x00\x0e\x00\x00\xa0" >> %t.stats
+# RUN: echo -ne "\x00\x00\x00\x00\x00\x00\x00\x00" >> %t.stats
+
+# RUN: sanstats %t.stats | FileCheck %s
+
+# CHECK: /tmp{{[/\\]}}f.c:1 f1 cfi-vcall 1
+# CHECK: /tmp{{[/\\]}}f.c:2 f2 cfi-nvcall 2
+# CHECK: /tmp{{[/\\]}}f.c:3 f3 cfi-derived-cast 3
+# CHECK: /tmp{{[/\\]}}f.c:1 f1 cfi-unrelated-cast 4
+# CHECK: /tmp{{[/\\]}}f.c:2 f2 cfi-icall 5
+# CHECK: /tmp{{[/\\]}}f.c:3 f3 <unknown> 6
+
+# CHECK: /tmp{{[/\\]}}f.c:3 f3 cfi-vcall 7
+# CHECK: /tmp{{[/\\]}}f.c:2 f2 cfi-nvcall 8
+# CHECK: /tmp{{[/\\]}}f.c:1 f1 cfi-derived-cast 9
+# CHECK: /tmp{{[/\\]}}f.c:3 f3 cfi-unrelated-cast 11
+# CHECK: /tmp{{[/\\]}}f.c:2 f2 cfi-icall 12
+# CHECK: /tmp{{[/\\]}}f.c:1 f1 <unknown> 14
+
+---
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000010
+    Content:         554889E55DC3662E0F1F840000000000554889E55DC3662E0F1F840000000000554889E55DC3
+  - Name:            .debug_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         636C616E672076657273696F6E20332E382E3020287472756E6B203235353339332920286C6C766D2F7472756E6B203235353734352900662E63002F746D7000663100663200663300
+  - Name:            .debug_loc
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .debug_abbrev
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         011101250E1305030E10171B0E110112060000022E00110112064018030E3A0B3B0B3F19000000
+  - Name:            .debug_info
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         660000000400000000000801000000000C0000000000000000000000000000000000000000002600000002000000000000000006000000015600000000010102000000000000000006000000015600000000010202000000000000000006000000015600000000010300
+  - Name:            .rela.debug_info
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .debug_info
+    Relocations:     
+      - Offset:          0x0000000000000006
+        Symbol:          ''
+        Type:            R_X86_64_32
+      - Offset:          0x000000000000000C
+        Symbol:          ''
+        Type:            R_X86_64_32
+      - Offset:          0x0000000000000012
+        Symbol:          ''
+        Type:            R_X86_64_32
+        Addend:          55
+      - Offset:          0x0000000000000016
+        Symbol:          ''
+        Type:            R_X86_64_32
+      - Offset:          0x000000000000001A
+        Symbol:          ''
+        Type:            R_X86_64_32
+        Addend:          59
+      - Offset:          0x000000000000001E
+        Symbol:          ''
+        Type:            R_X86_64_64
+      - Offset:          0x000000000000002B
+        Symbol:          ''
+        Type:            R_X86_64_64
+      - Offset:          0x0000000000000039
+        Symbol:          ''
+        Type:            R_X86_64_32
+        Addend:          64
+      - Offset:          0x0000000000000040
+        Symbol:          ''
+        Type:            R_X86_64_64
+        Addend:          16
+      - Offset:          0x000000000000004E
+        Symbol:          ''
+        Type:            R_X86_64_32
+        Addend:          67
+      - Offset:          0x0000000000000055
+        Symbol:          ''
+        Type:            R_X86_64_64
+        Addend:          32
+      - Offset:          0x0000000000000063
+        Symbol:          ''
+        Type:            R_X86_64_32
+        Addend:          70
+  - Name:            .debug_ranges
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .debug_pubnames
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         230000000200000000006A0000002A0000006631003F0000006632005400000066330000000000
+  - Name:            .rela.debug_pubnames
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .debug_pubnames
+    Relocations:     
+      - Offset:          0x0000000000000006
+        Symbol:          ''
+        Type:            R_X86_64_32
+  - Name:            .comment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         00636C616E672076657273696F6E20332E382E3020287472756E6B203235353339332920286C6C766D2F7472756E6B203235353734352900
+  - Name:            .note.GNU-stack
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .eh_frame
+    Type:            SHT_X86_64_UNWIND
+    Flags:           [ SHF_ALLOC ]
+    AddressAlign:    0x0000000000000008
+    Content:         1400000000000000017A5200017810011B0C070890010000180000001C000000000000000600000000410E108602430D060000001800000038000000000000000600000000410E108602430D060000001C00000054000000000000000600000000410E108602430D0600000000000000
+  - Name:            .rela.eh_frame
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .eh_frame
+    Relocations:     
+      - Offset:          0x0000000000000020
+        Symbol:          ''
+        Type:            R_X86_64_PC32
+      - Offset:          0x000000000000003C
+        Symbol:          ''
+        Type:            R_X86_64_PC32
+        Addend:          16
+      - Offset:          0x0000000000000058
+        Symbol:          ''
+        Type:            R_X86_64_PC32
+        Addend:          32
+  - Name:            .debug_line
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         4300000002001A0000000101FB0E0D00010101010000000100000100662E630000000000000902000000000000000001050C0A4A0500BB050C0A4A0500BB050C0A4A0202000101
+  - Name:            .rela.debug_line
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .debug_line
+    Relocations:     
+      - Offset:          0x0000000000000027
+        Symbol:          ''
+        Type:            R_X86_64_64
+Symbols:         
+  Local:           
+    - Name:            f.c
+      Type:            STT_FILE
+    - Type:            STT_SECTION
+      Section:         .text
+    - Type:            STT_SECTION
+      Section:         .debug_str
+    - Type:            STT_SECTION
+      Section:         .debug_abbrev
+    - Type:            STT_SECTION
+      Section:         .debug_info
+    - Type:            STT_SECTION
+      Section:         .debug_line
+  Global:          
+    - Name:            f1
+      Type:            STT_FUNC
+      Section:         .text
+      Size:            0x0000000000000006
+    - Name:            f2
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000010
+      Size:            0x0000000000000006
+    - Name:            f3
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000020
+      Size:            0x0000000000000006
+...

Modified: llvm/trunk/tools/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=257970&r1=257969&r2=257970&view=diff
==============================================================================
--- llvm/trunk/tools/Makefile (original)
+++ llvm/trunk/tools/Makefile Fri Jan 15 18:31:11 2016
@@ -33,7 +33,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis ll
                  llvm-dwarfdump llvm-cov llvm-size llvm-stress llvm-mcmarkup \
                  llvm-profdata llvm-symbolizer obj2yaml yaml2obj llvm-c-test \
                  llvm-cxxdump verify-uselistorder dsymutil llvm-pdbdump \
-                 llvm-split sancov llvm-dwp
+                 llvm-split sancov sanstats llvm-dwp
 
 # If Intel JIT Events support is configured, build an extra tool to test it.
 ifeq ($(USE_INTEL_JITEVENTS), 1)

Added: llvm/trunk/tools/sanstats/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/sanstats/CMakeLists.txt?rev=257970&view=auto
==============================================================================
--- llvm/trunk/tools/sanstats/CMakeLists.txt (added)
+++ llvm/trunk/tools/sanstats/CMakeLists.txt Fri Jan 15 18:31:11 2016
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS
+  Support
+  Symbolize
+  )
+
+add_llvm_tool(sanstats
+  sanstats.cpp
+  )

Added: llvm/trunk/tools/sanstats/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/sanstats/Makefile?rev=257970&view=auto
==============================================================================
--- llvm/trunk/tools/sanstats/Makefile (added)
+++ llvm/trunk/tools/sanstats/Makefile Fri Jan 15 18:31:11 2016
@@ -0,0 +1,17 @@
+##===- tools/sanstats/Makefile -----------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../..
+TOOLNAME := sanstats
+LINK_COMPONENTS := Support Symbolize
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LEVEL)/Makefile.common

Added: llvm/trunk/tools/sanstats/sanstats.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/sanstats/sanstats.cpp?rev=257970&view=auto
==============================================================================
--- llvm/trunk/tools/sanstats/sanstats.cpp (added)
+++ llvm/trunk/tools/sanstats/sanstats.cpp Fri Jan 15 18:31:11 2016
@@ -0,0 +1,138 @@
+//===- sanstats.cpp - Sanitizer statistics dumper -------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tool dumps statistics information from files in the format produced
+// by clang's -fsanitize-stats feature.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Transforms/Utils/SanitizerStats.h"
+#include <stdint.h>
+
+using namespace llvm;
+
+static cl::opt<std::string> ClInputFile(cl::Positional, cl::Required,
+                                        cl::desc("<filename>"));
+
+static cl::opt<bool> ClDemangle("demangle", cl::init(false),
+                                cl::desc("Print demangled function name."));
+
+inline uint64_t KindFromData(uint64_t Data, char SizeofPtr) {
+  return Data >> (SizeofPtr * 8 - kSanitizerStatKindBits);
+}
+
+inline uint64_t CountFromData(uint64_t Data, char SizeofPtr) {
+  return Data & ((1ull << (SizeofPtr * 8 - kSanitizerStatKindBits)) - 1);
+}
+
+uint64_t ReadLE(char Size, const char *Begin, const char *End) {
+  uint64_t Result = 0;
+  char Pos = 0;
+  while (Begin < End && Pos != Size) {
+    Result |= uint64_t(uint8_t(*Begin)) << (Pos * 8);
+    ++Begin;
+    ++Pos;
+  }
+  return Result;
+}
+
+const char *ReadModule(char SizeofPtr, const char *Begin, const char *End) {
+  const char *FilenameBegin = Begin;
+  while (Begin != End && *Begin)
+    ++Begin;
+  if (Begin == End)
+    return 0;
+  StringRef Filename(FilenameBegin, Begin - FilenameBegin);
+
+  ++Begin;
+  if (Begin == End)
+    return 0;
+
+  symbolize::LLVMSymbolizer::Options SymbolizerOptions;
+  SymbolizerOptions.Demangle = ClDemangle;
+  SymbolizerOptions.UseSymbolTable = true;
+  symbolize::LLVMSymbolizer Symbolizer(SymbolizerOptions);
+
+  while (1) {
+    uint64_t Addr = ReadLE(SizeofPtr, Begin, End);
+    Begin += SizeofPtr;
+    uint64_t Data = ReadLE(SizeofPtr, Begin, End);
+    Begin += SizeofPtr;
+
+    if (Begin > End)
+      return 0;
+    if (Addr == 0 && Data == 0)
+      return Begin;
+    if (Begin == End)
+      return 0;
+
+    ErrorOr<DILineInfo> LineInfo = Symbolizer.symbolizeCode(Filename, Addr);
+    if (LineInfo) {
+      llvm::outs() << LineInfo->FileName << ':' << LineInfo->Line << ' '
+                   << LineInfo->FunctionName << ' ';
+    } else {
+      llvm::outs() << "<error> ";
+    }
+
+    switch (KindFromData(Data, SizeofPtr)) {
+    case SanStat_CFI_VCall:
+      llvm::outs() << "cfi-vcall";
+      break;
+    case SanStat_CFI_NVCall:
+      llvm::outs() << "cfi-nvcall";
+      break;
+    case SanStat_CFI_DerivedCast:
+      llvm::outs() << "cfi-derived-cast";
+      break;
+    case SanStat_CFI_UnrelatedCast:
+      llvm::outs() << "cfi-unrelated-cast";
+      break;
+    case SanStat_CFI_ICall:
+      llvm::outs() << "cfi-icall";
+      break;
+    default:
+      llvm::outs() << "<unknown>";
+      break;
+    }
+
+    llvm::outs() << " " << CountFromData(Data, SizeofPtr) << '\n';
+  }
+}
+
+int main(int argc, char **argv) {
+  cl::ParseCommandLineOptions(argc, argv,
+                              "Sanitizer Statistics Processing Tool");
+
+  ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
+      MemoryBuffer::getFile(ClInputFile, -1, false);
+  if (!MBOrErr) {
+    errs() << argv[0] << ": " << ClInputFile << ": "
+           << MBOrErr.getError().message() << '\n';
+    return 1;
+  }
+  std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+  const char *Begin = MB->getBufferStart(), *End = MB->getBufferEnd();
+  if (Begin == End) {
+    errs() << argv[0] << ": " << ClInputFile << ": short read\n";
+    return 1;
+  }
+  char SizeofPtr = *Begin++;
+  while (Begin != End) {
+    Begin = ReadModule(SizeofPtr, Begin, End);
+    if (Begin == 0) {
+      errs() << argv[0] << ": " << ClInputFile << ": short read\n";
+      return 1;
+    }
+    assert(Begin <= End);
+  }
+}




More information about the llvm-commits mailing list