forked from OSchip/llvm-project
[sancov] Fix map update logic on Android.
dlopen()/dlclose() are not interceptable on Android, so we update .sancov.map in module constructor callbacks. llvm-svn: 210098
This commit is contained in:
parent
114a2bc9d2
commit
bb2fc7e4bb
|
@ -146,6 +146,12 @@ void CoverageData::Extend(uptr npcs) {
|
|||
}
|
||||
|
||||
atomic_store(&pc_array_size, size, memory_order_release);
|
||||
|
||||
if (SANITIZER_ANDROID) {
|
||||
// dlopen/dlclose interceptors do not work on Android, so we rely on
|
||||
// Extend() calls to update .sancov.map.
|
||||
CovUpdateMapping();
|
||||
}
|
||||
}
|
||||
|
||||
// Simply add the pc into the vector under lock. If the function is called more
|
||||
|
|
|
@ -37,9 +37,39 @@ namespace __sanitizer {
|
|||
|
||||
static const uptr kMaxNumberOfModules = 1 << 14;
|
||||
|
||||
static char *last_mapping;
|
||||
static StaticSpinMutex mapping_mu;
|
||||
|
||||
void CovUpdateMapping() {
|
||||
if (!common_flags()->coverage || !common_flags()->coverage_direct) return;
|
||||
|
||||
SpinMutexLock l(&mapping_mu);
|
||||
|
||||
const uptr kMaxTextSize = 64 * 1024;
|
||||
InternalScopedString text(kMaxTextSize);
|
||||
InternalScopedBuffer<char> modules_data(kMaxNumberOfModules *
|
||||
sizeof(LoadedModule));
|
||||
LoadedModule *modules = (LoadedModule *)modules_data.data();
|
||||
CHECK(modules);
|
||||
int n_modules = GetListOfModules(modules, kMaxNumberOfModules,
|
||||
/* filter */ 0);
|
||||
|
||||
text.append("%d\n", sizeof(uptr) * 8);
|
||||
for (int i = 0; i < n_modules; ++i) {
|
||||
char *module_name = StripModuleName(modules[i].full_name());
|
||||
for (unsigned j = 0; j < modules[i].n_ranges(); ++j) {
|
||||
text.append("%zx %zx %zx %s\n", modules[i].address_range_start(j),
|
||||
modules[i].address_range_end(j), modules[i].base_address(),
|
||||
module_name);
|
||||
}
|
||||
InternalFree(module_name);
|
||||
}
|
||||
|
||||
// Do not write mapping if it is the same as the one we've wrote last time.
|
||||
if (last_mapping && (internal_strcmp(last_mapping, text.data()) == 0)) return;
|
||||
if (!last_mapping) last_mapping = (char *)InternalAlloc(kMaxTextSize);
|
||||
internal_strncpy(last_mapping, text.data(), kMaxTextSize);
|
||||
|
||||
int err;
|
||||
InternalScopedString tmp_path(64 +
|
||||
internal_strlen(common_flags()->coverage_dir));
|
||||
|
@ -53,38 +83,11 @@ void CovUpdateMapping() {
|
|||
Die();
|
||||
}
|
||||
|
||||
InternalScopedBuffer<char> modules_data(kMaxNumberOfModules *
|
||||
sizeof(LoadedModule));
|
||||
LoadedModule *modules = (LoadedModule *)modules_data.data();
|
||||
CHECK(modules);
|
||||
int n_modules = GetListOfModules(modules, kMaxNumberOfModules,
|
||||
/* filter */ 0);
|
||||
|
||||
InternalScopedString line(4096);
|
||||
line.append("%d\n", sizeof(uptr) * 8);
|
||||
res = internal_write(map_fd, line.data(), line.length());
|
||||
res = internal_write(map_fd, text.data(), text.length());
|
||||
if (internal_iserror(res, &err)) {
|
||||
Printf("sancov.map write failed: %d\n", err);
|
||||
Die();
|
||||
}
|
||||
line.clear();
|
||||
|
||||
for (int i = 0; i < n_modules; ++i) {
|
||||
char *module_name = StripModuleName(modules[i].full_name());
|
||||
for (unsigned j = 0; j < modules[i].n_ranges(); ++j) {
|
||||
line.append("%zx %zx %zx %s\n", modules[i].address_range_start(j),
|
||||
modules[i].address_range_end(j), modules[i].base_address(),
|
||||
module_name);
|
||||
res = internal_write(map_fd, line.data(), line.length());
|
||||
if (internal_iserror(res, &err)) {
|
||||
Printf("sancov.map write failed: %d\n", err);
|
||||
Die();
|
||||
}
|
||||
line.clear();
|
||||
}
|
||||
InternalFree(module_name);
|
||||
}
|
||||
|
||||
internal_close(map_fd);
|
||||
|
||||
InternalScopedString path(64 + internal_strlen(common_flags()->coverage_dir));
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// Test for direct coverage writing with dlopen.
|
||||
// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSHARED %s -shared -o %T/libcoverage_direct_test_1.so -fPIC
|
||||
// RUN: %clangxx_asan -mllvm -asan-coverage=1 -DSO_DIR=\"%device\" %s -o %t
|
||||
|
||||
// RUN: adb shell rm -rf %device/coverage-direct
|
||||
// RUN: rm -rf %T/coverage-direct
|
||||
|
||||
// RUN: adb shell mkdir -p %device/coverage-direct/direct
|
||||
// RUN: mkdir -p %T/coverage-direct/direct
|
||||
// RUN: ASAN_OPTIONS=coverage=1:coverage_direct=1:coverage_dir=%device/coverage-direct/direct:verbosity=1 %run %t
|
||||
// RUN: adb pull %device/coverage-direct/direct %T/coverage-direct/direct
|
||||
// RUN: ls; pwd
|
||||
// RUN: cd %T/coverage-direct/direct
|
||||
// RUN: %sancov rawunpack *.sancov.raw
|
||||
// RUN: %sancov print *.sancov |& FileCheck %s
|
||||
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef SHARED
|
||||
extern "C" {
|
||||
void bar() { printf("bar\n"); }
|
||||
}
|
||||
#else
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
fprintf(stderr, "PID: %d\n", getpid());
|
||||
void *handle1 =
|
||||
dlopen(SO_DIR "/libcoverage_direct_test_1.so", RTLD_LAZY);
|
||||
assert(handle1);
|
||||
void (*bar1)() = (void (*)())dlsym(handle1, "bar");
|
||||
assert(bar1);
|
||||
bar1();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CHECK: 2 PCs total
|
|
@ -0,0 +1,11 @@
|
|||
def getRoot(config):
|
||||
if not config.parent:
|
||||
return config
|
||||
return getRoot(config.parent)
|
||||
|
||||
root = getRoot(config)
|
||||
|
||||
if root.android != "TRUE":
|
||||
config.unsupported = True
|
||||
|
||||
config.substitutions.append( ("%device", "/data/local/tmp/Output") )
|
Loading…
Reference in New Issue