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: }