OSDN Git Service

Inserted local redzones.
authorThomas Lively <tlively@google.com>
Tue, 21 Jun 2016 18:43:07 +0000 (11:43 -0700)
committerThomas Lively <tlively@google.com>
Tue, 21 Jun 2016 18:43:07 +0000 (11:43 -0700)
BUG=chromium:https://bugs.chromium.org/p/nativeclient/issues/detail?id=4374
R=kschimpf@google.com, stichnot@chromium.org

Review URL: https://codereview.chromium.org/2086593002 .

docs/ASAN.rst
runtime/szrt_asan.c
src/IceASanInstrumentation.cpp
src/IceASanInstrumentation.h
src/IceInstrumentation.cpp
src/IceInstrumentation.h
tests_lit/asan_tests/instrumentload.ll
tests_lit/asan_tests/instrumentlocals.ll [new file with mode: 0644]
tests_lit/asan_tests/instrumentstore.ll

index cd9748a..5526c59 100644 (file)
@@ -27,7 +27,3 @@ AddressSanitizer and properly linked into a final executable using
 subzero/pydir/szbuild.py with the --fsanitize-address flag, i.e.::
 
     pydir/szbuild.py --fsanitize-address hello.pexe
-
-
-
-
index 47b6abc..9f62e28 100644 (file)
 ///
 //===----------------------------------------------------------------------===//
 
+#include <assert.h>
 #include <stddef.h>
+#include <stdio.h>
 #include <stdlib.h>
 
+static __thread int behind_malloc = 0;
+
 // TODO(tlively): Define and implement this library
 void __asan_init(void) {
-  printf("Set up shadow memory here\n");
-  return;
+  if (behind_malloc == 0)
+    printf("set up shadow memory here\n");
 }
 
 void __asan_check(void *addr, int size) {
-  printf("Check %d bytes at %p\n", size, addr);
-  return;
+  if (behind_malloc == 0)
+    printf("check %d bytes at %p\n", size, addr);
 }
 
 void *__asan_malloc(size_t size) {
-  printf("malloc() called with size %d\n", size);
-  return malloc(size);
+  if (behind_malloc == 0)
+    printf("malloc() called with size %d\n", size);
+  ++behind_malloc;
+  void *ret = malloc(size);
+  --behind_malloc;
+  assert(behind_malloc >= 0);
+  return ret;
 }
 
 void __asan_free(void *ptr) {
-  printf("free() called on %p\n", ptr);
+  if (behind_malloc == 0)
+    printf("free() called on %p\n", ptr);
+  ++behind_malloc;
   free(ptr);
+  --behind_malloc;
+  assert(behind_malloc >= 0);
+}
+
+void __asan_alloca(void *ptr, int size) {
+  if (behind_malloc == 0)
+    printf("alloca of %d bytes at %p\n", size, ptr);
+}
+
+void __asan_unalloca(void *ptr, int size) {
+  if (behind_malloc == 0)
+    printf("unalloca of %d bytes as %p\n", size, ptr);
 }
index 9bd9555..f4b47e1 100644 (file)
@@ -15,6 +15,7 @@
 #include "IceASanInstrumentation.h"
 
 #include "IceBuildDefs.h"
+#include "IceCfg.h"
 #include "IceCfgNode.h"
 #include "IceGlobalInits.h"
 #include "IceInst.h"
@@ -122,6 +123,43 @@ ASanInstrumentation::createRz(VariableDeclarationList *List,
   return Rz;
 }
 
+// Check for an alloca signaling the presence of local variables and add a
+// redzone if it is found
+void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) {
+  auto *FirstAlloca = llvm::dyn_cast<InstAlloca>(Context.getCur());
+  if (FirstAlloca == nullptr)
+    return;
+
+  constexpr SizeT Alignment = 4;
+  InstAlloca *RzAlloca = createLocalRz(Context, RzSize, Alignment);
+
+  // insert before the current instruction
+  InstList::iterator Next = Context.getNext();
+  Context.setInsertPoint(Context.getCur());
+  Context.insert(RzAlloca);
+  Context.setNext(Next);
+}
+
+void ASanInstrumentation::instrumentAlloca(LoweringContext &Context,
+                                           InstAlloca *Instr) {
+  auto *VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Instr->getSizeInBytes());
+  SizeT VarSize = (VarSizeOp == nullptr) ? RzSize : VarSizeOp->getValue();
+  SizeT Padding = Utils::OffsetToAlignment(VarSize, RzSize);
+  constexpr SizeT Alignment = 1;
+  InstAlloca *Rz = createLocalRz(Context, RzSize + Padding, Alignment);
+  Context.insert(Rz);
+}
+
+InstAlloca *ASanInstrumentation::createLocalRz(LoweringContext &Context,
+                                               SizeT Size, SizeT Alignment) {
+  Cfg *Func = Context.getNode()->getCfg();
+  Variable *Rz = Func->makeVariable(IceType_i32);
+  Rz->setName(Func, nextRzName());
+  auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, Size);
+  auto *RzAlloca = InstAlloca::create(Func, Rz, ByteCount, Alignment);
+  return RzAlloca;
+}
+
 void ASanInstrumentation::instrumentCall(LoweringContext &Context,
                                          InstCall *Instr) {
   auto *CallTarget =
index e1222b4..2cf5c59 100644 (file)
@@ -31,7 +31,7 @@ class ASanInstrumentation : public Instrumentation {
   ASanInstrumentation &operator=(const ASanInstrumentation &) = delete;
 
 public:
-  ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx) {}
+  ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx), RzNum(0) {}
   void instrumentGlobals(VariableDeclarationList &Globals) override;
 
 private:
@@ -40,13 +40,17 @@ private:
                                 VariableDeclaration *RzArray,
                                 SizeT &RzArraySize,
                                 VariableDeclaration *Global);
+  InstAlloca *createLocalRz(LoweringContext &Context, SizeT Size,
+                            SizeT Alignment);
+  void instrumentFuncStart(LoweringContext &Context) override;
+  void instrumentAlloca(LoweringContext &Context, InstAlloca *Instr) override;
   void instrumentCall(LoweringContext &Context, InstCall *Instr) override;
   void instrumentLoad(LoweringContext &Context, InstLoad *Instr) override;
   void instrumentStore(LoweringContext &Context, InstStore *Instr) override;
   void instrumentAccess(LoweringContext &Context, Operand *Op, SizeT Size);
   void instrumentStart(Cfg *Func) override;
   bool DidInsertRedZones = false;
-  uint32_t RzNum = 0;
+  std::atomic<uint32_t> RzNum;
 };
 } // end of namespace Ice
 
index b4229f6..64a6212 100644 (file)
@@ -31,12 +31,16 @@ void Instrumentation::instrumentFunc(Cfg *Func) {
 
   // TODO(tlively): More selectively instrument functions so that shadow memory
   // represents user accessibility more and library accessibility less.
+  bool DidInstrumentStart = false;
   LoweringContext Context;
   Context.init(Func->getNodes().front());
-  instrumentFuncStart(Context);
   for (CfgNode *Node : Func->getNodes()) {
     Context.init(Node);
     while (!Context.atEnd()) {
+      if (!DidInstrumentStart) {
+        instrumentFuncStart(Context);
+        DidInstrumentStart = true;
+      }
       instrumentInst(Context);
       // go to next undeleted instruction
       Context.advanceCur();
index d41a7ee..60afef7 100644 (file)
@@ -47,7 +47,7 @@ public:
 private:
   void instrumentInst(LoweringContext &Context);
   virtual void instrumentFuncStart(LoweringContext &) {}
-  virtual void instrumentAlloca(LoweringContext &, const class InstAlloca *) {}
+  virtual void instrumentAlloca(LoweringContext &, class InstAlloca *) {}
   virtual void instrumentArithmetic(LoweringContext &, class InstArithmetic *) {
   }
   virtual void instrumentBr(LoweringContext &, class InstBr *) {}
index f3c02bf..55a11df 100644 (file)
@@ -69,12 +69,7 @@ define internal void @doLoads() {
 ; DUMP-LABEL: ================ Instrumented CFG ================
 ; DUMP-NEXT: define internal void @doLoads() {
 ; DUMP-NEXT: __0:
-; DUMP-NEXT: %srcLocal8 = alloca i8, i32 1, align 4
-; DUMP-NEXT: %srcLocal16 = alloca i8, i32 2, align 4
-; DUMP-NEXT: %srcLocal32 = alloca i8, i32 4, align 4
-; DUMP-NEXT: %srcLocal64 = alloca i8, i32 8, align 4
-; DUMP-NEXT: %srcLocal128 = alloca i8, i32 16, align 4
-; DUMP-NEXT: call void @__asan_check(i32 @srcConst8, i32 1)
+; DUMP: call void @__asan_check(i32 @srcConst8, i32 1)
 ; DUMP-NEXT: %dest1 = load i8, i8* @srcConst8, align 1
 ; DUMP-NEXT: call void @__asan_check(i32 @srcConst16, i32 2)
 ; DUMP-NEXT: %dest2 = load i16, i16* @srcConst16, align 1
diff --git a/tests_lit/asan_tests/instrumentlocals.ll b/tests_lit/asan_tests/instrumentlocals.ll
new file mode 100644 (file)
index 0000000..1031382
--- /dev/null
@@ -0,0 +1,48 @@
+; Test for insertion of redzones around global variables
+
+; REQUIRES: allow_dump
+
+; RUN: %p2i -i %s --args -verbose=inst -threads=0 -fsanitize-address \
+; RUN:     | FileCheck --check-prefix=DUMP %s
+
+; Function with local variables to be instrumented
+define internal void @func() {
+  %local0 = alloca i8, i32 4, align 4
+  %local1 = alloca i8, i32 32, align 4
+  %local2 = alloca i8, i32 13, align 4
+  %local3 = alloca i8, i32 75, align 4
+  %local4 = alloca i8, i32 64, align 4
+  %local5 = alloca i8, i32 4, align 1
+  %local6 = alloca i8, i32 32, align 1
+  %local7 = alloca i8, i32 13, align 1
+  %local8 = alloca i8, i32 75, align 1
+  %local9 = alloca i8, i32 64, align 1
+  ret void
+}
+
+; DUMP-LABEL: ================ Instrumented CFG ================
+; DUMP-NEXT: define internal void @func() {
+; DUMP-NEXT: __0:
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 4
+; DUMP-NEXT: %local0 = alloca i8, i32 4, align 4
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 60, align 1
+; DUMP-NEXT: %local1 = alloca i8, i32 32, align 4
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
+; DUMP-NEXT: %local2 = alloca i8, i32 13, align 4
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 51, align 1
+; DUMP-NEXT: %local3 = alloca i8, i32 75, align 4
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 53, align 1
+; DUMP-NEXT: %local4 = alloca i8, i32 64, align 4
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
+; DUMP-NEXT: %local5 = alloca i8, i32 4, align 1
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 60, align 1
+; DUMP-NEXT: %local6 = alloca i8, i32 32, align 1
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
+; DUMP-NEXT: %local7 = alloca i8, i32 13, align 1
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 51, align 1
+; DUMP-NEXT: %local8 = alloca i8, i32 75, align 1
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 53, align 1
+; DUMP-NEXT: %local9 = alloca i8, i32 64, align 
+; DUMP-NEXT: %__$rz{{[0-9]+}} = alloca i8, i32 32, align 1
+; DUMP-NEXT: ret void
+; DUMP-NEXT: }
index 73d0b9e..c81edac 100644 (file)
@@ -50,12 +50,7 @@ define internal void @doStores(<4 x i32> %vecSrc) {
 ; DUMP-LABEL: ================ Instrumented CFG ================
 ; DUMP-NEXT: define internal void @doStores(<4 x i32> %vecSrc) {
 ; DUMP-NEXT: __0:
-; DUMP-NEXT: %destLocal8 = alloca i8, i32 1, align 4
-; DUMP-NEXT: %destLocal16 = alloca i8, i32 2, align 4
-; DUMP-NEXT: %destLocal32 = alloca i8, i32 4, align 4
-; DUMP-NEXT: %destLocal64 = alloca i8, i32 8, align 4
-; DUMP-NEXT: %destLocal128 = alloca i8, i32 16, align 4
-; DUMP-NEXT: call void @__asan_check(i32 @destGlobal8, i32 1)
+; DUMP:      call void @__asan_check(i32 @destGlobal8, i32 1)
 ; DUMP-NEXT: store i8 42, i8* @destGlobal8, align 1
 ; DUMP-NEXT: call void @__asan_check(i32 @destGlobal16, i32 2)
 ; DUMP-NEXT: store i16 42, i16* @destGlobal16, align 1