[compiler-rt] r193643 - [msandr] Add support for standalone test.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Tue Oct 29 12:44:47 PDT 2013


Author: eugenis
Date: Tue Oct 29 14:44:47 2013
New Revision: 193643

URL: http://llvm.org/viewvc/llvm-project?rev=193643&view=rev
Log:
[msandr] Add support for standalone test.

Add macro MSANDR_STANDALONE_TEST for standalone test without msan executables.

Patch by Qin Zhao.

Modified:
    compiler-rt/trunk/lib/msandr/CMakeLists.txt
    compiler-rt/trunk/lib/msandr/msandr.cc

Modified: compiler-rt/trunk/lib/msandr/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msandr/CMakeLists.txt?rev=193643&r1=193642&r2=193643&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msandr/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/msandr/CMakeLists.txt Tue Oct 29 14:44:47 2013
@@ -4,11 +4,6 @@ if(DynamoRIO_DIR AND DrMemoryFramework_D
   find_package(DynamoRIO)
   find_package(DrMemoryFramework)
 
-  option(MSANDR_NATIVE_EXEC "Building msandr client for running in DynamoRIO hybrid mode, which allows some module running natively" OFF)
-  if (MSANDR_NATIVE_EXEC)
-    add_definitions(-DMSANDR_NATIVE_EXEC)
-  endif (MSANDR_NATIVE_EXEC)
-
   set(arch "x86_64")
   add_library(clang_rt.msandr-${arch} SHARED msandr.cc)
   configure_DynamoRIO_client(clang_rt.msandr-${arch})

Modified: compiler-rt/trunk/lib/msandr/msandr.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msandr/msandr.cc?rev=193643&r1=193642&r2=193643&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msandr/msandr.cc (original)
+++ compiler-rt/trunk/lib/msandr/msandr.cc Tue Oct 29 14:44:47 2013
@@ -60,6 +60,35 @@
 
 #define VERBOSITY 0
 
+// XXX: it seems setting macro in CMakeLists.txt does not work,
+// so manually set it here now.
+
+// Building msandr client for running in DynamoRIO hybrid mode,
+// which allows some module running natively.
+// TODO: turn it on by default when hybrid is stable enough
+// #define MSANDR_NATIVE_EXEC
+
+// Building msandr client for standalone test that does not need to
+// run with msan build executables. Disable by default.
+// #define MSANDR_STANDALONE_TEST
+
+#define NUM_TLS_RETVAL 1
+#define NUM_TLS_PARAM  6
+
+#ifdef MSANDR_STANDALONE_TEST
+// For testing purpose, we map app to shadow memory at [0x100000, 0x20000).
+// Normally, the app starts at 0x400000:
+// 00400000-004e0000 r-xp 00000000 fc:00 524343       /bin/bash
+// so there should be no problem.
+# define SHADOW_MEMORY_BASE ((void *)0x100000)
+# define SHADOW_MEMORY_SIZE (0x100000)
+# define SHADOW_MEMORY_MASK (SHADOW_MEMORY_SIZE - 4 /* to avoid overflow */)
+#else
+// shadow memory range [0x200000000000, 0x400000000000)
+// assuming no app memory below 0x200000000000
+# define SHADOW_MEMORY_MASK 0x3fffffffffffULL
+#endif /* MSANDR_STANDALONE_TEST */
+
 namespace {
 
 std::string g_app_path;
@@ -107,13 +136,47 @@ int(*__msan_get_param_tls_offset)();
 void (*__msan_unpoison)(void *base, size_t size);
 bool (*__msan_is_in_loader)();
 
+#ifdef MSANDR_STANDALONE_TEST
+uint mock_msan_retval_tls_offset;
+uint mock_msan_param_tls_offset;
+static int mock_msan_get_retval_tls_offset() {
+  return (int)mock_msan_retval_tls_offset;
+}
+
+static int mock_msan_get_param_tls_offset() {
+  return (int)mock_msan_param_tls_offset;
+}
+
+static void mock_msan_unpoison(void *base, size_t size) {
+  /* do nothing */
+}
+
+static bool mock_msan_is_in_loader() {
+  return false;
+}
+#endif /* MSANDR_STANDALONE_TEST */
+
 static generic_func_t LookupCallback(module_data_t *app, const char *name) {
+#ifdef MSANDR_STANDALONE_TEST
+  if (strcmp("__msan_get_retval_tls_offset", name) == 0) {
+    return (generic_func_t)mock_msan_get_retval_tls_offset;
+  } else if (strcmp("__msan_get_param_tls_offset", name) == 0) {
+    return (generic_func_t)mock_msan_get_param_tls_offset;
+  } else if (strcmp("__msan_unpoison", name) == 0) {
+    return (generic_func_t)mock_msan_unpoison;
+  } else if (strcmp("__msan_is_in_loader", name) == 0) {
+    return (generic_func_t)mock_msan_is_in_loader;
+  }
+  CHECK(false);
+  return NULL;
+#else /* !MSANDR_STANDALONE_TEST */
   generic_func_t callback = dr_get_proc_address(app->handle, name);
   if (callback == NULL) {
     dr_printf("Couldn't find `%s` in %s\n", name, app->full_path);
     CHECK(callback);
   }
   return callback;
+#endif /* !MSANDR_STANDALONE_TEST */
 }
 
 void InitializeMSanCallbacks() {
@@ -243,16 +306,22 @@ void InstrumentMops(void *drcontext, ins
   if (!address_in_R1)
     CHECK(drutil_insert_get_mem_addr(drcontext, bb, instr, op, R1, R2));
   PRE(instr, mov_imm(drcontext, opnd_create_reg(R2),
-                     OPND_CREATE_INT64(0xffffbfffffffffff)));
+                     OPND_CREATE_INT64(SHADOW_MEMORY_MASK)));
   PRE(instr, and(drcontext, opnd_create_reg(R1), opnd_create_reg(R2)));
+#ifdef MSANDR_STANDALONE_TEST
+  PRE(instr, add(drcontext, opnd_create_reg(R1),
+                 OPND_CREATE_INT32(SHADOW_MEMORY_BASE)));
+#endif
   // There is no mov_st of a 64-bit immediate, so...
   opnd_size_t op_size = opnd_get_size(op);
   CHECK(op_size != OPSZ_NA);
   uint access_size = opnd_size_in_bytes(op_size);
-  if (access_size <= 4) {
+  // TODO: optimize it with check-before-write
+  if (access_size <= 4 || op_size == OPSZ_PTR /* x64 support sign extension */) {
     PRE(instr,
         mov_st(drcontext, opnd_create_base_disp(R1, DR_REG_NULL, 0, 0, op_size),
-               opnd_create_immed_int((ptr_int_t) 0, op_size)));
+               opnd_create_immed_int((ptr_int_t) 0,
+                                     (op_size == OPSZ_PTR) ? OPSZ_4 : op_size)));
   } else {
     // FIXME: tail?
     for (uint ofs = 0; ofs < access_size; ofs += 4) {
@@ -280,6 +349,18 @@ void InstrumentMops(void *drcontext, ins
 }
 
 void InstrumentReturn(void *drcontext, instrlist_t *bb, instr_t *instr) {
+#ifdef MSANDR_STANDALONE_TEST
+  PRE(instr,
+      mov_st(drcontext,
+             opnd_create_far_base_disp(DR_SEG_GS /* DR's TLS */,
+                                       DR_REG_NULL, DR_REG_NULL,
+                                       0, msan_retval_tls_offset,
+                                       OPSZ_PTR),
+             OPND_CREATE_INT32(0)));
+#else  /* !MSANDR_STANDALONE_TEST */
+  /* XXX: the code below only works if -mangle_app_seg and -private_loader, 
+   * which is turned of for optimized native exec
+   */
   dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1);
 
   // Clobbers nothing except xax.
@@ -296,10 +377,27 @@ void InstrumentReturn(void *drcontext, i
 
   // The original instruction is left untouched. The above instrumentation is just
   // a prefix.
+#endif  /* !MSANDR_STANDALONE_TEST */
 }
 
 void InstrumentIndirectBranch(void *drcontext, instrlist_t *bb,
                               instr_t *instr) {
+#ifdef MSANDR_STANDALONE_TEST
+  for (int i = 0; i < NUM_TLS_PARAM; ++i) {
+      PRE(instr,
+          mov_st(drcontext,
+                 opnd_create_far_base_disp(DR_SEG_GS /* DR's TLS */,
+                                           DR_REG_NULL, DR_REG_NULL,
+                                           0,
+                                           msan_param_tls_offset +
+                                           i * sizeof(void *),
+                                           OPSZ_PTR),
+                 OPND_CREATE_INT32(0)));
+  }
+#else  /* !MSANDR_STANDALONE_TEST */
+  /* XXX: the code below only works if -mangle_app_seg and -private_loader, 
+   * which is turned off for optimized native exec
+   */
   dr_save_reg(drcontext, bb, instr, DR_REG_XAX, SPILL_SLOT_1);
 
   // Clobbers nothing except xax.
@@ -308,7 +406,7 @@ void InstrumentIndirectBranch(void *drco
   CHECK(res);
 
   // TODO: unpoison more bytes?
-  for (int i = 0; i < 6; ++i) {
+  for (int i = 0; i < NUM_TLS_PARAM; ++i) {
     PRE(instr,
         mov_st(drcontext, OPND_CREATE_MEMPTR(DR_REG_XAX, msan_param_tls_offset +
                                                          i * sizeof(void *)),
@@ -319,6 +417,7 @@ void InstrumentIndirectBranch(void *drco
 
   // The original instruction is left untouched. The above instrumentation is just
   // a prefix.
+#endif  /* !MSANDR_STANDALONE_TEST */
 }
 
 #ifndef MSANDR_NATIVE_EXEC
@@ -376,7 +475,7 @@ bool ShouldInstrumentPc(app_pc pc, Modul
   }
   return true;
 }
-#endif /* !NATIVE_CLIENT */
+#endif /* !MSANDR_NATIVE_CLIENT */
 
 // TODO(rnk): Make sure we instrument after __msan_init.
 dr_emit_flags_t
@@ -525,6 +624,15 @@ void event_exit() {
   drutil_exit();
   drmgr_exit();
 
+#ifdef MSANDR_STANDALONE_TEST
+  /* free tls */
+  bool res;
+  res = dr_raw_tls_cfree(msan_retval_tls_offset, NUM_TLS_RETVAL);
+  CHECK(res);
+  res = dr_raw_tls_cfree(msan_param_tls_offset, NUM_TLS_PARAM);
+  CHECK(res);
+  /* we do not bother to free the shadow memory */
+#endif /* !MSANDR_STANDALONE_TEST */
   if (VERBOSITY > 0)
     dr_printf("==DRMSAN== DONE\n");
 }
@@ -701,6 +809,21 @@ DR_EXPORT void dr_init(client_id_t id) {
   res = drsys_filter_all_syscalls();
   CHECK(res == DRMF_SUCCESS);
 
+#ifdef MSANDR_STANDALONE_TEST
+  reg_id_t reg_seg;
+  /* alloc tls */
+  if (!dr_raw_tls_calloc(&reg_seg, &mock_msan_retval_tls_offset, NUM_TLS_RETVAL, 0))
+      CHECK(false);
+  CHECK(reg_seg == DR_SEG_GS /* x64 only! */);
+  if (!dr_raw_tls_calloc(&reg_seg, &mock_msan_param_tls_offset, NUM_TLS_PARAM, 0))
+      CHECK(false);
+  CHECK(reg_seg == DR_SEG_GS /* x64 only! */);
+  /* alloc shadow memory */
+  if (mmap(SHADOW_MEMORY_BASE, SHADOW_MEMORY_SIZE, PROT_READ|PROT_WRITE,
+           MAP_PRIVATE | MAP_ANON, -1, 0) != SHADOW_MEMORY_BASE) {
+      CHECK(false);
+  }
+#endif /* MSANDR_STANDALONE_TEST */
   InitializeMSanCallbacks();
 
   // FIXME: the shadow is initialized earlier when DR calls one of our wrapper





More information about the llvm-commits mailing list