subzero/pydir/szbuild.py with the --fsanitize-address flag, i.e.::
pydir/szbuild.py --fsanitize-address hello.pexe
-
-
-
-
///
//===----------------------------------------------------------------------===//
+#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);
}
#include "IceASanInstrumentation.h"
#include "IceBuildDefs.h"
+#include "IceCfg.h"
#include "IceCfgNode.h"
#include "IceGlobalInits.h"
#include "IceInst.h"
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 =
ASanInstrumentation &operator=(const ASanInstrumentation &) = delete;
public:
- ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx) {}
+ ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx), RzNum(0) {}
void instrumentGlobals(VariableDeclarationList &Globals) override;
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
// 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();
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 *) {}
; 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
--- /dev/null
+; 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: }
; 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