Implemented linking to a dummy ASan runtime BUG=https://bugs.chromium.org/p/nativeclient/issues/detail?id=4374 R=kschimpf@google.com Review URL: https://codereview.chromium.org/2068593003 .
diff --git a/Makefile.standalone b/Makefile.standalone index 9c10dce..201a8e4 100644 --- a/Makefile.standalone +++ b/Makefile.standalone
@@ -501,13 +501,15 @@ RT_SRC := runtime/szrt.c runtime/szrt_ll.ll runtime/szrt_profiler.c \ runtime/szrt_asm_x8632.s runtime/szrt_asm_x8664.s \ - runtime/szrt_asm_arm32.s + runtime/szrt_asm_arm32.s runtime/szrt_asan.c RT_OBJ := build/runtime/szrt_native_x8632.o build/runtime/szrt_sb_x8632.o \ build/runtime/szrt_nonsfi_x8632.o \ build/runtime/szrt_native_x8664.o build/runtime/szrt_sb_x8664.o \ build/runtime/szrt_nonsfi_x8664.o \ build/runtime/szrt_native_arm32.o build/runtime/szrt_sb_arm32.o \ - build/runtime/szrt_nonsfi_arm32.o + build/runtime/szrt_nonsfi_arm32.o \ + build/runtime/szrt_asan_x8632.o build/runtime/szrt_asan_x8664.o \ + build/runtime/szrt_asan_arm32.o runtime: $(RT_OBJ)
diff --git a/pydir/build-runtime.py b/pydir/build-runtime.py index cb923ba..caed297 100755 --- a/pydir/build-runtime.py +++ b/pydir/build-runtime.py
@@ -84,6 +84,14 @@ shellcmd([GetObjcopyCmd(), '--strip-symbol=NATIVE', OutFile('{rtdir}/szrt_native_{target}.o')]) + # Compile srcdir/szrt_asan.c to szrt_asan_{target}.o + shellcmd(['clang', + '-O2', + '-target=' + target_info.triple, + '-c', + '{srcdir}/szrt_asan.c'.format(srcdir=srcdir), + '-o', OutFile('{rtdir}/szrt_asan_{target}.o') + ], echo=verbose) # Helper function for building the sandboxed runtime. def MakeSandboxedRuntime():
diff --git a/pydir/szbuild.py b/pydir/szbuild.py index 558db48..7333729 100755 --- a/pydir/szbuild.py +++ b/pydir/szbuild.py
@@ -103,6 +103,9 @@ default=[], help='Extra arguments for llc') argparser.add_argument('--no-sz', dest='nosz', action='store_true', help='Run only post-Subzero build steps') + argparser.add_argument('--fsanitize-address', dest='asan', + action='store_true', + help='Instrument with AddressSanitizer') def LinkSandbox(objs, exe, target, verbose=True): assert target in ('x8632', 'x8664', 'arm32'), \ @@ -263,6 +266,11 @@ args = argparser.parse_args() pexe = args.pexe exe = args.output + if args.asan: + if args.sandbox or args.nonsfi: + print 'Can only use AddressSanitizer with a native build' + exit(1) + args.sz_args.append('-fsanitize-address') ProcessPexe(args, pexe, exe) def ProcessPexe(args, pexe, exe): @@ -446,7 +454,13 @@ elif args.nonsfi: LinkNonsfi([obj_partial], exe, args.target, args.verbose) else: - LinkNative([obj_partial], exe, args.target, args.verbose) + objs = [obj_partial] + if args.asan: + objs.append( + ('{root}/toolchain_build/src/subzero/build/runtime/' + + 'szrt_asan_{target}.o').format(root=nacl_root, + target=args.target)) + LinkNative(objs, exe, args.target, args.verbose) # Put the extra verbose printing at the end. if args.verbose and hybrid:
diff --git a/runtime/szrt_asan.c b/runtime/szrt_asan.c new file mode 100644 index 0000000..f89f04b --- /dev/null +++ b/runtime/szrt_asan.c
@@ -0,0 +1,24 @@ +//===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===// +// +// The Subzero Code Generator +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Provides the AddressSanitizer runtime. +/// +/// Exposes functions for initializing the shadow memory region and managing it +/// on loads, stores, and allocations. +/// +//===----------------------------------------------------------------------===// + +#include <stdio.h> + +// TODO(tlively): Define and implement this library +void __asan_init(void) { + printf("Set up shadow memory here\n"); + return; +}
diff --git a/src/IceASanInstrumentation.cpp b/src/IceASanInstrumentation.cpp index 45ec038..1cda875 100644 --- a/src/IceASanInstrumentation.cpp +++ b/src/IceASanInstrumentation.cpp
@@ -15,7 +15,9 @@ #include "IceASanInstrumentation.h" #include "IceBuildDefs.h" +#include "IceCfgNode.h" #include "IceGlobalInits.h" +#include "IceInst.h" #include <sstream> @@ -109,4 +111,15 @@ return Rz; } +void ASanInstrumentation::instrumentStart(Cfg *Func) { + Constant *ShadowMemInit = + Ctx->getConstantExternSym(Ctx->getGlobalString("__asan_init")); + constexpr SizeT NumArgs = 0; + constexpr Variable *Void = nullptr; + constexpr bool NoTailCall = false; + + auto *Call = InstCall::create(Func, NumArgs, Void, ShadowMemInit, NoTailCall); + Func->getEntryNode()->getInsts().push_front(Call); +} + } // end of namespace Ice
diff --git a/src/IceASanInstrumentation.h b/src/IceASanInstrumentation.h index ee20e7d..29f279d 100644 --- a/src/IceASanInstrumentation.h +++ b/src/IceASanInstrumentation.h
@@ -40,6 +40,7 @@ VariableDeclaration *RzArray, SizeT &RzArraySize, VariableDeclaration *Global); + void instrumentStart(Cfg *Func) override; bool DidInsertRedZones = false; uint32_t RzNum = 0; };
diff --git a/src/IceInstrumentation.cpp b/src/IceInstrumentation.cpp index 0d56100..fc2a4a5 100644 --- a/src/IceInstrumentation.cpp +++ b/src/IceInstrumentation.cpp
@@ -41,6 +41,9 @@ Context.advanceNext(); } } + + if (Func->getFunctionName().toStringOrEmpty() == "_start") + instrumentStart(Func); } void Instrumentation::instrumentInst(LoweringContext &Context) {
diff --git a/src/IceInstrumentation.h b/src/IceInstrumentation.h index a7e099b..8b7e2e7 100644 --- a/src/IceInstrumentation.h +++ b/src/IceInstrumentation.h
@@ -69,6 +69,7 @@ virtual void instrumentSwitch(LoweringContext &, const class InstSwitch *) {} virtual void instrumentUnreachable(LoweringContext &, const class InstUnreachable *) {} + virtual void instrumentStart(Cfg *) {} virtual void instrumentLocalVars(Cfg *) {} protected:
diff --git a/tests_lit/asan_tests/globalredzones.ll b/tests_lit/asan_tests/globalredzones.ll index a4052e7..623ce60 100644 --- a/tests_lit/asan_tests/globalredzones.ll +++ b/tests_lit/asan_tests/globalredzones.ll
@@ -3,9 +3,9 @@ ; REQUIRES: allow_dump ; RUN: %p2i -i %s --args -threads=0 -fsanitize-address \ -; RUN: | %iflc FileCheck %s +; RUN: | FileCheck %s ; RUN: %p2i -i %s --args -verbose=global_init,inst -threads=0 \ -; RUN: -fsanitize-address | %iflc FileCheck --check-prefix=DUMP %s +; RUN: -fsanitize-address | FileCheck --check-prefix=DUMP %s ; The array of redzones
diff --git a/tests_lit/asan_tests/startinitcall.ll b/tests_lit/asan_tests/startinitcall.ll new file mode 100644 index 0000000..2a1a7a3 --- /dev/null +++ b/tests_lit/asan_tests/startinitcall.ll
@@ -0,0 +1,28 @@ +; Test for a call to __asan_init in _start + +; REQUIRES: allow_dump + +; RUN: %p2i -i %s --args -verbose=inst -threads=0 -fsanitize-address \ +; RUN: | FileCheck --check-prefix=DUMP %s + +; notStart() should not be instrumented +define internal void @notStart() { + ret void +} + +; DUMP-LABEL: define internal void @notStart() { # notStart(i=1:b=1) +; DUMP-NEXT: __0: +; DUMP-NOT: __asan_init() +; DUMP: ret void +; DUMP-NEXT: } + +; _start() should be instrumented +define void @_start() { + ret void +} + +; DUMP-LABEL: define void @_start() { # _start(i=2:b=1) +; DUMP-NEXT: __0: +; DUMP-NEXT: call void @__asan_init() +; DUMP-NEXT: ret void +; DUMP-NEXT: }