[asan] fix a bug (issue 19) where dlclose and the following mmap caused a false positive. run-time part.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@146687 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_globals.cc b/lib/asan/asan_globals.cc
index d62b547..f53bf38 100644
--- a/lib/asan/asan_globals.cc
+++ b/lib/asan/asan_globals.cc
@@ -106,10 +106,10 @@
// so we store the globals in a map.
static void RegisterGlobal(const Global *g) {
CHECK(asan_inited);
- if (!FLAG_report_globals) return;
- ScopedLock lock(&mu_for_globals);
+ CHECK(FLAG_report_globals);
CHECK(AddrIsInMem(g->beg));
CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
PoisonRedZones(*g);
ListOfGlobals *l =
(ListOfGlobals*)allocator_for_globals.Allocate(sizeof(ListOfGlobals));
@@ -121,6 +121,18 @@
g->beg, g->size, g->name);
}
+static void UnregisterGlobal(const Global *g) {
+ CHECK(asan_inited);
+ CHECK(FLAG_report_globals);
+ CHECK(AddrIsInMem(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->beg));
+ CHECK(AddrIsAlignedByGranularity(g->size_with_redzone));
+ PoisonShadow(g->beg, g->size_with_redzone, 0);
+ // We unpoison the shadow memory for the global but we do not remove it from
+ // the list because that would require O(n^2) time with the current list
+ // implementation. It might not be worth doing anyway.
+}
+
} // namespace __asan
// ---------------------- Interface ---------------- {{{1
@@ -129,17 +141,31 @@
// Register one global with a default redzone.
void __asan_register_global(uintptr_t addr, size_t size,
const char *name) {
- Global g;
- g.beg = addr;
- g.size = size;
- g.size_with_redzone = GetAlignedSize(size) + kGlobalAndStackRedzone;
- g.name = name;
- RegisterGlobal(&g);
+ if (!FLAG_report_globals) return;
+ ScopedLock lock(&mu_for_globals);
+ Global *g = (Global *)allocator_for_globals.Allocate(sizeof(Global));
+ g->beg = addr;
+ g->size = size;
+ g->size_with_redzone = GetAlignedSize(size) + kGlobalAndStackRedzone;
+ g->name = name;
+ RegisterGlobal(g);
}
// Register an array of globals.
void __asan_register_globals(__asan_global *globals, size_t n) {
+ if (!FLAG_report_globals) return;
+ ScopedLock lock(&mu_for_globals);
for (size_t i = 0; i < n; i++) {
RegisterGlobal(&globals[i]);
}
}
+
+// Unregister an array of globals.
+// We must do it when a shared objects gets dlclosed.
+void __asan_unregister_globals(__asan_global *globals, size_t n) {
+ if (!FLAG_report_globals) return;
+ ScopedLock lock(&mu_for_globals);
+ for (size_t i = 0; i < n; i++) {
+ UnregisterGlobal(&globals[i]);
+ }
+}
diff --git a/lib/asan/asan_interface.h b/lib/asan/asan_interface.h
index 7265a69..72ec126 100644
--- a/lib/asan/asan_interface.h
+++ b/lib/asan/asan_interface.h
@@ -40,10 +40,12 @@
const char *name; // Name as a C string.
};
- // This function should be called by the instrumented code.
- // gets an array of structures describing globals.
+ // These two functions should be called by the instrumented code.
+ // 'globals' is an array of structures describing 'n' globals.
void __asan_register_globals(__asan_global *globals, size_t n)
__attribute__((visibility("default")));
+ void __asan_unregister_globals(__asan_global *globals, size_t n)
+ __attribute__((visibility("default")));
// These two functions are used by the instrumented code in the
// use-after-return mode. __asan_stack_malloc allocates size bytes of
diff --git a/lib/asan/tests/dlclose-test.tmpl b/lib/asan/tests/dlclose-test.tmpl
new file mode 100644
index 0000000..7ef22e9
--- /dev/null
+++ b/lib/asan/tests/dlclose-test.tmpl
@@ -0,0 +1 @@
+PASS
diff --git a/lib/asan/tests/shared-lib-test.cc b/lib/asan/tests/shared-lib-test.cc
index 087f694..e492572 100644
--- a/lib/asan/tests/shared-lib-test.cc
+++ b/lib/asan/tests/shared-lib-test.cc
@@ -18,18 +18,11 @@
using std::string;
-const char kMyName[] = "shared-lib-test";
-const char kSoName[] = "shared-lib-test-so";
-
typedef void (fun_t)(int x);
int main(int argc, char *argv[]) {
- string path = strdup(argv[0]);
- size_t start = path.find(kMyName);
- if (start == string::npos) return 1;
- path.replace(start, strlen(kMyName), kSoName);
- path += ".so";
- // printf("opening %s ... ", path.c_str());
+ string path = string(argv[0]) + "-so.so";
+ printf("opening %s ... \n", path.c_str());
void *lib = dlopen(path.c_str(), RTLD_NOW);
if (!lib) {
printf("error in dlopen(): %s\n", dlerror());
@@ -37,7 +30,7 @@
}
fun_t *inc = (fun_t*)dlsym(lib, "inc");
if (!inc) return 1;
- // printf("ok\n");
+ printf("ok\n");
inc(1);
inc(-1);
return 0;
diff --git a/lib/asan/tests/test_output.sh b/lib/asan/tests/test_output.sh
index 594394d..433d94f 100755
--- a/lib/asan/tests/test_output.sh
+++ b/lib/asan/tests/test_output.sh
@@ -25,7 +25,8 @@
c=`basename $t .tmpl`
c_so=$c-so
exe=$c.$b.O$O
- so=$c_so.$b.O$O.so
+ so=$c.$b.O$O-so.so
+ echo testing $exe
$CXX $CXXFLAGS -g -m$b -faddress-sanitizer -O$O $c.cc -o $exe
[ -e "$c_so.cc" ] && $CXX $CXXFLAGS -g -m$b -faddress-sanitizer -O$O $c_so.cc -fPIC -shared -o $so
# If there's an OS-specific template, use it.
@@ -37,9 +38,8 @@
actual_t="$t"
fi
./$exe 2>&1 | $SYMBOLIZER 2> /dev/null | c++filt | ./match_output.py $actual_t
- echo $exe
- rm ./$exe
- [ -e "$so" ] && rm ./$so
+ #rm ./$exe
+ #[ -e "$so" ] && rm ./$so
done
done
done