Instrumented local variables and implemented runtime. BUG=https://bugs.chromium.org/p/nativeclient/issues/detail?id=4374 R=kschimpf@google.com Review URL: https://codereview.chromium.org/2095763002 .
diff --git a/runtime/szrt_asan.c b/runtime/szrt_asan.c index 9f62e28..6fab295 100644 --- a/runtime/szrt_asan.c +++ b/runtime/szrt_asan.c
@@ -16,48 +16,133 @@ //===----------------------------------------------------------------------===// #include <assert.h> +#include <errno.h> +#include <limits.h> +#include <stdbool.h> #include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <sys/mman.h> -static __thread int behind_malloc = 0; +#define RZ_SIZE (32) +#define SHADOW_SCALE_LOG2 (3) +#define SHADOW_SCALE ((size_t)1 << SHADOW_SCALE_LOG2) -// TODO(tlively): Define and implement this library +// Assuming 48 bit address space on 64 bit systems +#define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) +#define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) +#define IS_32_BIT (sizeof(void *) == 4) + +#define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) +#define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) + +#define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) +#define SHADOW2MEM(p) \ + ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) + +#define POISON_VAL (-1) + +static char *shadow_offset = NULL; + +void __asan_init(void); +void __asan_check(char *, int); +void *__asan_malloc(size_t); +void __asan_free(char *); +void __asan_poison(char *, int); +void __asan_unpoison(char *, int); + void __asan_init(void) { - if (behind_malloc == 0) - printf("set up shadow memory here\n"); + // ensure the redzones are large enough to hold metadata + assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); + assert(shadow_offset == NULL); + size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + int fd = -1; + off_t offset = 0; + shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); + if (shadow_offset == NULL) + fprintf(stderr, "unable to allocate shadow memory\n"); + else + printf("set up shadow memory at %p\n", shadow_offset); + if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, + PROT_NONE)) + fprintf(stderr, "could not protect bad region\n"); + else + printf("protected bad region\n"); } -void __asan_check(void *addr, int size) { - if (behind_malloc == 0) - printf("check %d bytes at %p\n", size, addr); +void __asan_check(char *ptr, int size) { + printf("check %d bytes at %p\n", size, ptr); + char *end = ptr + size; + for (; ptr < end; ++ptr) { + char shadow = *(char *)MEM2SHADOW(ptr); + printf("checking %p with shadow %d\n", ptr, shadow); + assert(shadow == 0 || (shadow > 0 && SHADOW_OFFSET(ptr) <= shadow)); + } } void *__asan_malloc(size_t 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); + printf("malloc() called with size %d\n", size); + size_t padding = + (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); + size_t rz_left_size = RZ_SIZE; + size_t rz_right_size = RZ_SIZE + padding; + void *rz_left; + int err = posix_memalign(&rz_left, SHADOW_SCALE, + rz_left_size + size + rz_right_size); + if (err != 0) { + assert(err == ENOMEM); + return NULL; + } + void *ret = rz_left + rz_left_size; + void *rz_right = ret + size; + __asan_poison(rz_left, rz_left_size); + __asan_poison(rz_right, rz_right_size); + // record size and location data so we can find it again + *(void **)rz_left = rz_right; + *(size_t *)rz_right = rz_right_size; + assert((uintptr_t)ret % 8 == 0); return ret; } -void __asan_free(void *ptr) { - if (behind_malloc == 0) - printf("free() called on %p\n", ptr); - ++behind_malloc; - free(ptr); - --behind_malloc; - assert(behind_malloc >= 0); +void __asan_free(char *ptr) { + printf("free() called on %p\n", ptr); + void *rz_left = ptr - RZ_SIZE; + void *rz_right = *(void **)rz_left; + size_t rz_right_size = *(size_t *)rz_right; + __asan_unpoison(rz_left, RZ_SIZE); + __asan_unpoison(rz_right, rz_right_size); + free(rz_left); } -void __asan_alloca(void *ptr, int size) { - if (behind_malloc == 0) - printf("alloca of %d bytes at %p\n", size, ptr); +void __asan_poison(char *ptr, int size) { + char *end = ptr + size; + assert(IS_SHADOW_ALIGNED(end)); + // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment + assert(size < 2 * RZ_SIZE); + printf("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), + MEM2SHADOW(end)); + size_t offset = SHADOW_OFFSET(ptr); + *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset; + ptr += SHADOW_OFFSET(size); + assert(IS_SHADOW_ALIGNED(ptr)); + for (; ptr != end; ptr += SHADOW_SCALE) { + *(char *)MEM2SHADOW(ptr) = POISON_VAL; + } } -void __asan_unalloca(void *ptr, int size) { - if (behind_malloc == 0) - printf("unalloca of %d bytes as %p\n", size, ptr); +void __asan_unpoison(char *ptr, int size) { + char *end = ptr + size; + assert(IS_SHADOW_ALIGNED(end)); + assert(size < 2 * RZ_SIZE); + printf("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), + MEM2SHADOW(end)); + *(char *)MEM2SHADOW(ptr) = 0; + ptr += SHADOW_OFFSET(size); + assert(IS_SHADOW_ALIGNED(ptr)); + for (; ptr != end; ptr += SHADOW_SCALE) { + *(char *)MEM2SHADOW(ptr) = 0; + } }
diff --git a/src/IceASanInstrumentation.cpp b/src/IceASanInstrumentation.cpp index f4b47e1..83ebc19 100644 --- a/src/IceASanInstrumentation.cpp +++ b/src/IceASanInstrumentation.cpp
@@ -24,10 +24,12 @@ #include <sstream> #include <unordered_map> +#include <vector> namespace Ice { namespace { + constexpr SizeT RzSize = 32; const std::string RzPrefix = "__$rz"; const llvm::NaClBitcodeRecord::RecordVector RzContents = @@ -42,6 +44,9 @@ } // end of anonymous namespace +ICE_TLS_DEFINE_FIELD(std::vector<InstCall *> *, ASanInstrumentation, + LocalDtors); + // Create redzones around all global variables, ensuring that the initializer // types of the redzones and their associated globals match so that they are // laid out together in memory. @@ -126,38 +131,95 @@ // 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; + if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr) + ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>()); - 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; + bool HasLocals = false; + LoweringContext C; + C.init(Context.getNode()); + std::vector<Inst *> Initializations; + Constant *InitFunc = + Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_poison")); + Constant *DestroyFunc = + Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_unpoison")); + + InstAlloca *Cur; + ConstantInteger32 *VarSizeOp; + while ( + (Cur = llvm::dyn_cast<InstAlloca>(iteratorToInst(C.getCur()))) && + (VarSizeOp = llvm::dyn_cast<ConstantInteger32>(Cur->getSizeInBytes()))) { + HasLocals = true; + + // create the new alloca that includes a redzone + SizeT VarSize = VarSizeOp->getValue(); + Variable *Dest = Cur->getDest(); + SizeT RzPadding = RzSize + Utils::OffsetToAlignment(VarSize, RzSize); + auto *ByteCount = + ConstantInteger32::create(Ctx, IceType_i32, VarSize + RzPadding); + constexpr SizeT Alignment = 8; + auto *NewVar = InstAlloca::create(Func, Dest, ByteCount, Alignment); + + // calculate the redzone offset + Variable *RzLocVar = Func->makeVariable(IceType_i32); + RzLocVar->setName(Func, nextRzName()); + auto *Offset = ConstantInteger32::create(Ctx, IceType_i32, VarSize); + auto *RzLoc = InstArithmetic::create(Func, InstArithmetic::Add, RzLocVar, + Dest, Offset); + + // instructions to poison and unpoison the redzone + constexpr SizeT NumArgs = 2; + constexpr Variable *Void = nullptr; + constexpr bool NoTailcall = false; + auto *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall); + auto *Destroy = + InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall); + Init->addArg(RzLocVar); + Destroy->addArg(RzLocVar); + auto *RzSizeConst = ConstantInteger32::create(Ctx, IceType_i32, RzPadding); + Init->addArg(RzSizeConst); + Destroy->addArg(RzSizeConst); + + Cur->setDeleted(); + C.insert(NewVar); + ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy); + Initializations.emplace_back(RzLoc); + Initializations.emplace_back(Init); + + C.advanceCur(); + C.advanceNext(); + } + + C.setInsertPoint(C.getCur()); + + // add the leftmost redzone + if (HasLocals) { + Variable *LastRz = Func->makeVariable(IceType_i32); + LastRz->setName(Func, nextRzName()); + auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, RzSize); + constexpr SizeT Alignment = 8; + auto *RzAlloca = InstAlloca::create(Func, LastRz, ByteCount, Alignment); + + constexpr SizeT NumArgs = 2; + constexpr Variable *Void = nullptr; + constexpr bool NoTailcall = false; + auto *Init = InstCall::create(Func, NumArgs, Void, InitFunc, NoTailcall); + auto *Destroy = + InstCall::create(Func, NumArgs, Void, DestroyFunc, NoTailcall); + Init->addArg(LastRz); + Destroy->addArg(LastRz); + Init->addArg(RzAlloca->getSizeInBytes()); + Destroy->addArg(RzAlloca->getSizeInBytes()); + + ICE_TLS_GET_FIELD(LocalDtors)->emplace_back(Destroy); + C.insert(RzAlloca); + C.insert(Init); + } + + // insert initializers for the redzones + for (Inst *Init : Initializations) { + C.insert(Init); + } } void ASanInstrumentation::instrumentCall(LoweringContext &Context, @@ -214,6 +276,15 @@ Context.setNext(Next); } +void ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) { + InstList::iterator Next = Context.getNext(); + Context.setInsertPoint(Context.getCur()); + for (InstCall *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) { + Context.insert(RzUnpoison); + } + Context.setNext(Next); +} + void ASanInstrumentation::instrumentStart(Cfg *Func) { Constant *ShadowMemInit = Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_init")); @@ -224,4 +295,10 @@ Func->getEntryNode()->getInsts().push_front(Call); } +// TODO(tlively): make this more efficient with swap idiom +void ASanInstrumentation::finishFunc(Cfg *Func) { + (void)Func; + ICE_TLS_GET_FIELD(LocalDtors)->clear(); +} + } // end of namespace Ice
diff --git a/src/IceASanInstrumentation.h b/src/IceASanInstrumentation.h index 2cf5c59..de250d4 100644 --- a/src/IceASanInstrumentation.h +++ b/src/IceASanInstrumentation.h
@@ -31,7 +31,9 @@ ASanInstrumentation &operator=(const ASanInstrumentation &) = delete; public: - ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx), RzNum(0) {} + ASanInstrumentation(GlobalContext *Ctx) : Instrumentation(Ctx), RzNum(0) { + ICE_TLS_INIT_FIELD(LocalDtors); + } void instrumentGlobals(VariableDeclarationList &Globals) override; private: @@ -40,15 +42,15 @@ 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 instrumentRet(LoweringContext &Context, InstRet *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; + void finishFunc(Cfg *Func) override; + ICE_TLS_DECLARE_FIELD(std::vector<InstCall *> *, LocalDtors); bool DidInsertRedZones = false; std::atomic<uint32_t> RzNum; };
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp index a113b95..c2b4d06 100644 --- a/src/IceCfg.cpp +++ b/src/IceCfg.cpp
@@ -645,16 +645,19 @@ getTarget()->lowerArguments(); } -void Cfg::sortAndCombineAllocas(CfgVector<Inst *> &Allocas, +void Cfg::sortAndCombineAllocas(CfgVector<InstAlloca *> &Allocas, uint32_t CombinedAlignment, InstList &Insts, AllocaBaseVariableType BaseVariableType) { if (Allocas.empty()) return; // Sort by decreasing alignment. - std::sort(Allocas.begin(), Allocas.end(), [](Inst *I1, Inst *I2) { - auto *A1 = llvm::dyn_cast<InstAlloca>(I1); - auto *A2 = llvm::dyn_cast<InstAlloca>(I2); - return A1->getAlignInBytes() > A2->getAlignInBytes(); + std::sort(Allocas.begin(), Allocas.end(), [](InstAlloca *A1, InstAlloca *A2) { + uint32_t Align1 = A1->getAlignInBytes(); + uint32_t Align2 = A2->getAlignInBytes(); + if (Align1 == Align2) + return A1->getNumber() > A2->getNumber(); + else + return Align1 > Align2; }); // Process the allocas in order of decreasing stack alignment. This allows // us to pack less-aligned pieces after more-aligned ones, resulting in less @@ -746,6 +749,8 @@ bool HasLargeAlignment = false; bool HasDynamicAllocation = false; for (Inst &Instr : EntryNode->getInsts()) { + if (Instr.isDeleted()) + continue; if (auto *Alloca = llvm::dyn_cast<InstAlloca>(&Instr)) { uint32_t AlignmentParam = Alloca->getAlignInBytes(); if (AlignmentParam > StackAlignment) @@ -769,6 +774,8 @@ if (Node == EntryNode) continue; for (Inst &Instr : Node->getInsts()) { + if (Instr.isDeleted()) + continue; if (llvm::isa<InstAlloca>(&Instr)) { // Allocations outside the entry block require a frame pointer. HasDynamicAllocation = true; @@ -784,13 +791,15 @@ // Collect the Allocas into the two vectors. // Allocas in the entry block that have constant size and alignment less // than or equal to the function's stack alignment. - CfgVector<Inst *> FixedAllocas; + CfgVector<InstAlloca *> FixedAllocas; // Allocas in the entry block that have constant size and alignment greater // than the function's stack alignment. - CfgVector<Inst *> AlignedAllocas; + CfgVector<InstAlloca *> AlignedAllocas; // Maximum alignment used by any alloca. uint32_t MaxAlignment = StackAlignment; for (Inst &Instr : EntryNode->getInsts()) { + if (Instr.isDeleted()) + continue; if (auto *Alloca = llvm::dyn_cast<InstAlloca>(&Instr)) { if (!llvm::isa<Constant>(Alloca->getSizeInBytes())) continue;
diff --git a/src/IceCfg.h b/src/IceCfg.h index e3f29c7..c656961 100644 --- a/src/IceCfg.h +++ b/src/IceCfg.h
@@ -295,7 +295,7 @@ BVT_FramePointer, BVT_UserPointer }; - void sortAndCombineAllocas(CfgVector<Inst *> &Allocas, + void sortAndCombineAllocas(CfgVector<InstAlloca *> &Allocas, uint32_t CombinedAlignment, InstList &Insts, AllocaBaseVariableType BaseVariableType); void findRematerializable();
diff --git a/src/IceInstrumentation.cpp b/src/IceInstrumentation.cpp index 64a6212..c911a0b 100644 --- a/src/IceInstrumentation.cpp +++ b/src/IceInstrumentation.cpp
@@ -51,6 +51,8 @@ std::string FuncName = Func->getFunctionName().toStringOrEmpty(); if (FuncName == "_start") instrumentStart(Func); + + finishFunc(Func); } void Instrumentation::instrumentInst(LoweringContext &Context) {
diff --git a/src/IceInstrumentation.h b/src/IceInstrumentation.h index 60afef7..3a18542 100644 --- a/src/IceInstrumentation.h +++ b/src/IceInstrumentation.h
@@ -44,8 +44,10 @@ virtual void instrumentGlobals(VariableDeclarationList &) {} void instrumentFunc(Cfg *Func); +protected: + virtual void instrumentInst(LoweringContext &Context); + private: - void instrumentInst(LoweringContext &Context); virtual void instrumentFuncStart(LoweringContext &) {} virtual void instrumentAlloca(LoweringContext &, class InstAlloca *) {} virtual void instrumentArithmetic(LoweringContext &, class InstArithmetic *) { @@ -71,6 +73,7 @@ class InstUnreachable *) {} virtual void instrumentStart(Cfg *) {} virtual void instrumentLocalVars(Cfg *) {} + virtual void finishFunc(Cfg *) {} protected: GlobalContext *Ctx;
diff --git a/tests_lit/asan_tests/alignment.ll b/tests_lit/asan_tests/alignment.ll new file mode 100644 index 0000000..53e96b3 --- /dev/null +++ b/tests_lit/asan_tests/alignment.ll
@@ -0,0 +1,43 @@ +; Translate with -fsanitize-address and -O2 to test alignment and ordering of +; redzones when allocas are coalesced. + +; REQUIRES: no_minimal_build + +; RUN: %p2i --filetype=obj --disassemble --target x8632 -i %s --args -O2 \ +; RUN: -allow-externally-defined-symbols -fsanitize-address | FileCheck %s + +define internal i32 @func(i32 %arg1, i32 %arg2) { + %l1 = alloca i8, i32 4, align 4 + %l2 = alloca i8, i32 5, align 1 + ret i32 42 +} + +; CHECK: func +; CHECK-NEXT: sub esp,0xbc +; CHECK-NEXT: lea eax,[esp+0x10] +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x4],0x20 +; CHECK-NEXT: __asan_poison +; CHECK-NEXT: lea eax,[esp+0x74] +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x4],0x3c +; CHECK-NEXT: __asan_poison +; CHECK-NEXT: lea eax,[esp+0x35] +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x4],0x3b +; CHECK-NEXT: __asan_poison +; CHECK-NEXT: lea eax,[esp+0x74] +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x4],0x3c +; CHECK-NEXT: __asan_unpoison +; CHECK-NEXT: lea eax,[esp+0x35] +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x4],0x3b +; CHECK-NEXT: __asan_unpoison +; CHECK-NEXT: lea eax,[esp+0x10] +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x4],0x20 +; CHECK-NEXT: __asan_unpoison +; CHECK-NEXT: mov eax,0x2a +; CHECK-NEXT: add esp,0xbc +; CHECK-NEXT: ret
diff --git a/tests_lit/asan_tests/instrumentload.ll b/tests_lit/asan_tests/instrumentload.ll index 55a11df..037e71c 100644 --- a/tests_lit/asan_tests/instrumentload.ll +++ b/tests_lit/asan_tests/instrumentload.ll
@@ -69,7 +69,7 @@ ; DUMP-LABEL: ================ Instrumented CFG ================ ; DUMP-NEXT: define internal void @doLoads() { ; DUMP-NEXT: __0: -; DUMP: 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 @@ -99,5 +99,5 @@ ; DUMP-NEXT: %dest14 = load i64, i64* %srcLocal64, align 1 ; DUMP-NEXT: call void @__asan_check(i32 %srcLocal128, i32 16) ; DUMP-NEXT: %dest15 = load <4 x i32>, <4 x i32>* %srcLocal128, align 4 -; DUMP-NEXT: ret void -; DUMP-NEXT } +; DUMP: ret void +; DUMP-NEXT: }
diff --git a/tests_lit/asan_tests/instrumentlocals.ll b/tests_lit/asan_tests/instrumentlocals.ll index 1031382..b8b7a03 100644 --- a/tests_lit/asan_tests/instrumentlocals.ll +++ b/tests_lit/asan_tests/instrumentlocals.ll
@@ -1,4 +1,4 @@ -; Test for insertion of redzones around global variables +; Test for insertion of redzones around local variables ; REQUIRES: allow_dump @@ -7,42 +7,39 @@ ; 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 + %local1 = alloca i8, i32 4, align 4 + %local2 = alloca i8, i32 32, align 1 + %local3 = alloca i8, i32 13, align 2 + %local4 = alloca i8, i32 75, align 4 + %local5 = alloca i8, i32 64, align 8 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: %local1 = alloca i8, i32 64, align 8 +; DUMP-NEXT: %local2 = alloca i8, i32 64, align 8 +; DUMP-NEXT: %local3 = alloca i8, i32 64, align 8 +; DUMP-NEXT: %local4 = alloca i8, i32 128, align 8 +; DUMP-NEXT: %local5 = alloca i8, i32 96, align 8 +; DUMP-NEXT: %__$rz[[RZ0:[0-9]+]] = alloca i8, i32 32, align 8 +; DUMP-NEXT: call void @__asan_poison(i32 %__$rz[[RZ0]], i32 32) +; DUMP-NEXT: %__$rz[[RZ1:[0-9]+]] = add i32 %local1, 4 +; DUMP-NEXT: call void @__asan_poison(i32 %__$rz[[RZ1]], i32 60) +; DUMP-NEXT: %__$rz[[RZ2:[0-9]+]] = add i32 %local2, 32 +; DUMP-NEXT: call void @__asan_poison(i32 %__$rz[[RZ2]], i32 32) +; DUMP-NEXT: %__$rz[[RZ3:[0-9]+]] = add i32 %local3, 13 +; DUMP-NEXT: call void @__asan_poison(i32 %__$rz[[RZ3]], i32 51) +; DUMP-NEXT: %__$rz[[RZ4:[0-9]+]] = add i32 %local4, 75 +; DUMP-NEXT: call void @__asan_poison(i32 %__$rz[[RZ4]], i32 53) +; DUMP-NEXT: %__$rz[[RZ5:[0-9]+]] = add i32 %local5, 64 +; DUMP-NEXT: call void @__asan_poison(i32 %__$rz[[RZ5]], i32 32) +; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz[[RZ1]], i32 60) +; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz[[RZ2]], i32 32) +; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz[[RZ3]], i32 51) +; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz[[RZ4]], i32 53) +; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz[[RZ5]], i32 32) +; DUMP-NEXT: call void @__asan_unpoison(i32 %__$rz[[RZ0]], i32 32) ; DUMP-NEXT: ret void ; DUMP-NEXT: }
diff --git a/tests_lit/asan_tests/instrumentstore.ll b/tests_lit/asan_tests/instrumentstore.ll index c81edac..0a4c94d 100644 --- a/tests_lit/asan_tests/instrumentstore.ll +++ b/tests_lit/asan_tests/instrumentstore.ll
@@ -70,5 +70,5 @@ ; DUMP-NEXT: store i64 42, i64* %destLocal64, align 1 ; DUMP-NEXT: call void @__asan_check(i32 %destLocal128, i32 16) ; DUMP-NEXT: store <4 x i32> %vecSrc, <4 x i32>* %destLocal128, align 4 -; DUMP-NEXT: ret void +; DUMP: ret void ; DUMP-NEXT: }
diff --git a/tests_lit/llvm2ice_tests/fused-alloca-arg.ll b/tests_lit/llvm2ice_tests/fused-alloca-arg.ll index 1b009ba..d76755e 100644 --- a/tests_lit/llvm2ice_tests/fused-alloca-arg.ll +++ b/tests_lit/llvm2ice_tests/fused-alloca-arg.ll
@@ -49,16 +49,16 @@ ; CHECK-LABEL: caller2 ; CHECK-NEXT: sub esp,0x6c ; CHECK-NEXT: mov eax,DWORD PTR [esp+0x70] -; CHECK-NEXT: mov DWORD PTR [esp+0x20],eax ; CHECK-NEXT: mov DWORD PTR [esp+0x40],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x20],eax ; CHECK-NEXT: mov DWORD PTR [esp],eax -; CHECK-NEXT: lea eax,[esp+0x20] +; CHECK-NEXT: lea eax,[esp+0x40] ; CHECK-NEXT: mov DWORD PTR [esp+0x4],eax -; CHECK-NEXT: lea eax,[esp+0x40] -; CHECK-NEXT: mov DWORD PTR [esp+0x8],eax ; CHECK-NEXT: lea eax,[esp+0x20] -; CHECK-NEXT: mov DWORD PTR [esp+0xc],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x8],eax ; CHECK-NEXT: lea eax,[esp+0x40] +; CHECK-NEXT: mov DWORD PTR [esp+0xc],eax +; CHECK-NEXT: lea eax,[esp+0x20] ; CHECK-NEXT: mov DWORD PTR [esp+0x10],eax ; CHECK-NEXT: call ; CHECK-NEXT: add esp,0x6c
diff --git a/tests_lit/llvm2ice_tests/fused-alloca.ll b/tests_lit/llvm2ice_tests/fused-alloca.ll index 42e644b..3b37ada 100644 --- a/tests_lit/llvm2ice_tests/fused-alloca.ll +++ b/tests_lit/llvm2ice_tests/fused-alloca.ll
@@ -21,8 +21,8 @@ ; CHECK-LABEL: fused_small_align ; CHECK-NEXT: sub esp,0x30 ; CHECK-NEXT: mov eax,DWORD PTR [esp+0x34] +; CHECK-NEXT: mov DWORD PTR [esp+0x1c],eax ; CHECK-NEXT: mov DWORD PTR [esp+0x10],eax -; CHECK-NEXT: mov DWORD PTR [esp+0x18],eax ; CHECK-NEXT: mov DWORD PTR [esp],eax ; CHECK-NEXT: add esp,0x30 @@ -46,9 +46,9 @@ ; CHECK-NEXT: sub esp,0x80 ; CHECK-NEXT: and esp,0xffffffc0 ; CHECK-NEXT: mov eax,DWORD PTR [ebp+0x8] -; CHECK-NEXT: mov DWORD PTR [esp+0x40],eax -; CHECK-NEXT: mov DWORD PTR [esp],eax ; CHECK-NEXT: mov DWORD PTR [esp+0x60],eax +; CHECK-NEXT: mov DWORD PTR [esp],eax +; CHECK-NEXT: mov DWORD PTR [esp+0x40],eax ; CHECK-NEXT: mov esp,ebp ; CHECK-NEXT: pop ebp @@ -154,10 +154,10 @@ ; CHECK-NEXT: add ecx,0x0 ; CHECK-NEXT: sub esp,0x10 ; CHECK-NEXT: mov ebx,esp -; CHECK-NEXT: mov DWORD PTR [ecx],eax ; CHECK-NEXT: mov DWORD PTR [edx],eax -; CHECK-NEXT: mov DWORD PTR [ebp-0x14],eax +; CHECK-NEXT: mov DWORD PTR [ecx],eax ; CHECK-NEXT: mov DWORD PTR [ebp-0x24],eax +; CHECK-NEXT: mov DWORD PTR [ebp-0x14],eax ; CHECK-NEXT: mov DWORD PTR [ebx],eax ; CHECK-NEXT: mov esp,ebp ; CHECK-NEXT: pop ebp