forked from OSchip/llvm-project
parent
9cffc9550b
commit
512a18e518
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SRCS="
|
||||
dd_rtl.cc
|
||||
dd_interceptors.cc
|
||||
../../sanitizer_common/sanitizer_allocator.cc
|
||||
../../sanitizer_common/sanitizer_common.cc
|
||||
../../sanitizer_common/sanitizer_deadlock_detector1.cc
|
||||
../../sanitizer_common/sanitizer_flags.cc
|
||||
../../sanitizer_common/sanitizer_libc.cc
|
||||
../../sanitizer_common/sanitizer_printf.cc
|
||||
../../sanitizer_common/sanitizer_suppressions.cc
|
||||
../../sanitizer_common/sanitizer_thread_registry.cc
|
||||
../../sanitizer_common/sanitizer_posix.cc
|
||||
../../sanitizer_common/sanitizer_posix_libcdep.cc
|
||||
../../sanitizer_common/sanitizer_procmaps_linux.cc
|
||||
../../sanitizer_common/sanitizer_linux.cc
|
||||
../../sanitizer_common/sanitizer_linux_libcdep.cc
|
||||
../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
|
||||
../../sanitizer_common/sanitizer_stackdepot.cc
|
||||
../../sanitizer_common/sanitizer_stacktrace.cc
|
||||
../../sanitizer_common/sanitizer_stacktrace_libcdep.cc
|
||||
../../sanitizer_common/sanitizer_symbolizer.cc
|
||||
../../sanitizer_common/sanitizer_symbolizer_libcdep.cc
|
||||
../../sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
|
||||
../../sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
|
||||
../../interception/interception_linux.cc
|
||||
"
|
||||
|
||||
FLAGS=" -I../.. -I../../sanitizer_common -I../../interception -Wall -fno-exceptions -fno-rtti -DSANITIZER_USE_MALLOC"
|
||||
if [ "$DEBUG" == "" ]; then
|
||||
FLAGS+=" -DDEBUG=0 -O3 -fomit-frame-pointer"
|
||||
else
|
||||
FLAGS+=" -DDEBUG=1 -g"
|
||||
fi
|
||||
|
||||
rm -f dd.cc
|
||||
for F in $SRCS; do
|
||||
g++ $F -c -o dd.o $FLAGS
|
||||
cat $F >> dd.cc
|
||||
done
|
||||
|
||||
g++ dd.cc -c -o dd.o $FLAGS
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,68 @@
|
|||
//===-- dd_interceptors.cc ------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "dd_rtl.h"
|
||||
#include "interception/interception.h"
|
||||
#include <pthread.h>
|
||||
|
||||
using namespace __dsan;
|
||||
|
||||
extern "C" void *__libc_malloc(uptr size);
|
||||
extern "C" void __libc_free(void *ptr);
|
||||
|
||||
static __thread Thread *thr;
|
||||
|
||||
static void InitThread() {
|
||||
if (thr != 0)
|
||||
return;
|
||||
thr = (Thread*)InternalAlloc(sizeof(*thr));
|
||||
internal_memset(thr, 0, sizeof(*thr));
|
||||
ThreadInit(thr);
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, pthread_mutex_destroy, pthread_mutex_t *m) {
|
||||
InitThread();
|
||||
int res = REAL(pthread_mutex_destroy)(m);
|
||||
MutexDestroy(thr, (uptr)m);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *m) {
|
||||
InitThread();
|
||||
int res = REAL(pthread_mutex_lock)(m);
|
||||
if (res == 0)
|
||||
MutexLock(thr, (uptr)m, true, false);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, pthread_mutex_trylock, pthread_mutex_t *m) {
|
||||
InitThread();
|
||||
int res = REAL(pthread_mutex_trylock)(m);
|
||||
if (res == 0)
|
||||
MutexLock(thr, (uptr)m, true, true);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *m) {
|
||||
InitThread();
|
||||
MutexUnlock(thr, (uptr)m, true);
|
||||
int res = REAL(pthread_mutex_unlock)(m);
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace __dsan {
|
||||
|
||||
void InitializeInterceptors() {
|
||||
INTERCEPT_FUNCTION(pthread_mutex_destroy);
|
||||
INTERCEPT_FUNCTION(pthread_mutex_lock);
|
||||
INTERCEPT_FUNCTION(pthread_mutex_trylock);
|
||||
INTERCEPT_FUNCTION(pthread_mutex_unlock);
|
||||
}
|
||||
|
||||
} // namespace __dsan
|
|
@ -0,0 +1,128 @@
|
|||
//===-- dd_rtl.cc ---------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "dd_rtl.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_flags.h"
|
||||
#include "sanitizer_common/sanitizer_stacktrace.h"
|
||||
#include "sanitizer_common/sanitizer_stackdepot.h"
|
||||
|
||||
namespace __dsan {
|
||||
|
||||
static Context ctx0;
|
||||
static Context * const ctx = &ctx0;
|
||||
|
||||
void Initialize() {
|
||||
InitializeInterceptors();
|
||||
//common_flags()->allow_addr2line = true;
|
||||
common_flags()->symbolize = true;
|
||||
ctx->dd = DDetector::Create();
|
||||
}
|
||||
|
||||
void ThreadInit(Thread *thr) {
|
||||
thr->dd_pt = ctx->dd->CreatePhysicalThread();
|
||||
thr->dd_lt = ctx->dd->CreateLogicalThread(0);
|
||||
}
|
||||
|
||||
void ThreadDestroy(Thread *thr) {
|
||||
ctx->dd->DestroyPhysicalThread(thr->dd_pt);
|
||||
ctx->dd->DestroyLogicalThread(thr->dd_lt);
|
||||
}
|
||||
|
||||
static u32 CurrentStackTrace(Thread *thr) {
|
||||
StackTrace trace;
|
||||
thr->in_symbolizer = true;
|
||||
trace.Unwind(1000, 0, 0, 0, 0, 0, false);
|
||||
thr->in_symbolizer = false;
|
||||
const uptr skip = 4;
|
||||
if (trace.size <= skip)
|
||||
return 0;
|
||||
return StackDepotPut(trace.trace + skip, trace.size - skip);
|
||||
}
|
||||
|
||||
static void PrintStackTrace(Thread *thr, u32 stk) {
|
||||
uptr size = 0;
|
||||
const uptr *trace = StackDepotGet(stk, &size);
|
||||
thr->in_symbolizer = true;
|
||||
StackTrace::PrintStack(trace, size);
|
||||
thr->in_symbolizer = false;
|
||||
}
|
||||
|
||||
static Mutex *FindMutex(Thread *thr, uptr m) {
|
||||
SpinMutexLock l(&ctx->mutex_mtx);
|
||||
for (Mutex *mtx = ctx->mutex_list; mtx; mtx = mtx->link) {
|
||||
if (mtx->addr == m)
|
||||
return mtx;
|
||||
}
|
||||
Mutex *mtx = (Mutex*)InternalAlloc(sizeof(*mtx));
|
||||
internal_memset(mtx, 0, sizeof(*mtx));
|
||||
mtx->addr = m;
|
||||
ctx->dd->MutexInit(&mtx->dd, CurrentStackTrace(thr), ctx->mutex_seq++);
|
||||
mtx->link = ctx->mutex_list;
|
||||
ctx->mutex_list = mtx;
|
||||
return mtx;
|
||||
}
|
||||
|
||||
static Mutex *FindMutexAndRemove(uptr m) {
|
||||
SpinMutexLock l(&ctx->mutex_mtx);
|
||||
Mutex **prev = &ctx->mutex_list;
|
||||
for (;;) {
|
||||
Mutex *mtx = *prev;
|
||||
if (mtx == 0)
|
||||
return 0;
|
||||
if (mtx->addr == m) {
|
||||
*prev = mtx->link;
|
||||
return mtx;
|
||||
}
|
||||
prev = &mtx->link;
|
||||
}
|
||||
}
|
||||
|
||||
static void ReportDeadlock(Thread *thr, DDReport *rep) {
|
||||
Printf("==============================\n");
|
||||
Printf("DEADLOCK\n");
|
||||
PrintStackTrace(thr, CurrentStackTrace(thr));
|
||||
for (int i = 0; i < rep->n; i++) {
|
||||
Printf("Mutex %llu created at:\n", rep->loop[i].mtx_ctx0);
|
||||
PrintStackTrace(thr, rep->loop[i].stk);
|
||||
}
|
||||
Printf("==============================\n");
|
||||
}
|
||||
|
||||
void MutexLock(Thread *thr, uptr m, bool writelock, bool trylock) {
|
||||
if (thr->in_symbolizer)
|
||||
return;
|
||||
Mutex *mtx = FindMutex(thr, m);
|
||||
DDReport *rep = ctx->dd->MutexLock(thr->dd_pt, thr->dd_lt, &mtx->dd,
|
||||
writelock, trylock);
|
||||
if (rep)
|
||||
ReportDeadlock(thr, rep);
|
||||
}
|
||||
|
||||
void MutexUnlock(Thread *thr, uptr m, bool writelock) {
|
||||
if (thr->in_symbolizer)
|
||||
return;
|
||||
Mutex *mtx = FindMutex(thr, m);
|
||||
ctx->dd->MutexUnlock(thr->dd_pt, thr->dd_lt, &mtx->dd, writelock);
|
||||
}
|
||||
|
||||
void MutexDestroy(Thread *thr, uptr m) {
|
||||
if (thr->in_symbolizer)
|
||||
return;
|
||||
Mutex *mtx = FindMutexAndRemove(m);
|
||||
if (mtx == 0)
|
||||
return;
|
||||
ctx->dd->MutexDestroy(thr->dd_pt, thr->dd_lt, &mtx->dd);
|
||||
InternalFree(mtx);
|
||||
}
|
||||
|
||||
} // namespace __dsan
|
||||
|
||||
__attribute__((section(".preinit_array"), used))
|
||||
void (*__local_dsan_preinit)(void) = __dsan::Initialize;
|
|
@ -0,0 +1,50 @@
|
|||
//===-- dd_rtl.h ----------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef DD_RTL_H
|
||||
#define DD_RTL_H
|
||||
|
||||
#include "sanitizer_common/sanitizer_internal_defs.h"
|
||||
#include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
|
||||
#include "sanitizer_common/sanitizer_allocator_internal.h"
|
||||
#include "sanitizer_common/sanitizer_mutex.h"
|
||||
|
||||
namespace __dsan {
|
||||
|
||||
struct Mutex {
|
||||
Mutex *link;
|
||||
uptr addr;
|
||||
DDMutex dd;
|
||||
};
|
||||
|
||||
struct Thread {
|
||||
DDPhysicalThread *dd_pt;
|
||||
DDLogicalThread *dd_lt;
|
||||
|
||||
bool in_symbolizer;
|
||||
};
|
||||
|
||||
struct Context {
|
||||
DDetector *dd;
|
||||
|
||||
SpinMutex mutex_mtx;
|
||||
Mutex *mutex_list;
|
||||
u64 mutex_seq;
|
||||
};
|
||||
|
||||
void InitializeInterceptors();
|
||||
|
||||
void ThreadInit(Thread *thr);
|
||||
void ThreadDestroy(Thread *thr);
|
||||
|
||||
void MutexLock(Thread *thr, uptr m, bool writelock, bool trylock);
|
||||
void MutexUnlock(Thread *thr, uptr m, bool writelock);
|
||||
void MutexDestroy(Thread *thr, uptr m);
|
||||
|
||||
} // namespace __dsan
|
||||
#endif // DD_RTL_H
|
Loading…
Reference in New Issue