tsan: consistently use return pc as top frame pc

always substract 1 from the top pc
this allows to get correct stacks with -O2

llvm-svn: 184112
This commit is contained in:
Dmitry Vyukov 2013-06-17 19:57:03 +00:00
parent 7648aa3558
commit 5cf581a8d4
5 changed files with 19 additions and 10 deletions

View File

@ -181,8 +181,7 @@ ScopedInterceptor::~ScopedInterceptor() {
StatInc(thr, StatInt_##func); \
const uptr caller_pc = GET_CALLER_PC(); \
ScopedInterceptor si(thr, #func, caller_pc); \
const uptr pc = __sanitizer::StackTrace::GetPreviousInstructionPc( \
__sanitizer::StackTrace::GetCurrentPc()); \
const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
(void)pc; \
/**/
@ -1882,6 +1881,7 @@ void ProcessPendingSignals(ThreadState *thr) {
uptr pc = signal->sigaction ?
(uptr)sigactions[sig].sa_sigaction :
(uptr)sigactions[sig].sa_handler;
pc += 1; // return address is expected, OutputReport() will undo this
stack.Init(&pc, 1);
ThreadRegistryLock l(ctx->thread_registry);
ScopedReport rep(ReportTypeErrnoInSignal);

View File

@ -13,6 +13,7 @@
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
#include "tsan_interface_ann.h"
#include "tsan_mutex.h"
#include "tsan_report.h"
@ -229,12 +230,12 @@ using namespace __tsan; // NOLINT
extern "C" {
void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensBefore);
Release(cur_thread(), CALLERPC, addr);
Release(cur_thread(), pc, addr);
}
void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
SCOPED_ANNOTATION(AnnotateHappensAfter);
Acquire(cur_thread(), CALLERPC, addr);
Acquire(cur_thread(), pc, addr);
}
void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {

View File

@ -30,7 +30,6 @@ using namespace __tsan; // NOLINT
#define SCOPED_ATOMIC(func, ...) \
const uptr callpc = (uptr)__builtin_return_address(0); \
uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
pc = __sanitizer::StackTrace::GetPreviousInstructionPc(pc); \
mo = ConvertOrder(mo); \
mo = flags()->force_seq_cst_atomics ? (morder)mo_seq_cst : mo; \
ThreadState *const thr = cur_thread(); \

View File

@ -17,6 +17,7 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stacktrace.h"
using namespace __tsan; // NOLINT
@ -157,7 +158,7 @@ SyncVar* GetAndRemoveJavaSync(ThreadState *thr, uptr pc, uptr addr) {
#define SCOPED_JAVA_FUNC(func) \
ThreadState *thr = cur_thread(); \
const uptr caller_pc = GET_CALLER_PC(); \
const uptr pc = (uptr)&func; \
const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
(void)pc; \
ScopedJavaFunc scoped(thr, caller_pc); \
/**/

View File

@ -106,17 +106,25 @@ static ReportStack *SymbolizeStack(const StackTrace& trace) {
return 0;
ReportStack *stack = 0;
for (uptr si = 0; si < trace.Size(); si++) {
const uptr pc = trace.Get(si);
#ifndef TSAN_GO
// We obtain the return address, that is, address of the next instruction,
// so offset it by 1 byte.
bool is_last = (si == trace.Size() - 1);
ReportStack *ent = SymbolizeCode(trace.Get(si) - !is_last);
const uptr pc1 = __sanitizer::StackTrace::GetPreviousInstructionPc(pc);
#else
// FIXME(dvyukov): Go sometimes uses address of a function as top pc.
uptr pc1 = pc;
if (si != trace.Size() - 1)
pc1 -= 1;
#endif
ReportStack *ent = SymbolizeCode(pc1);
CHECK_NE(ent, 0);
ReportStack *last = ent;
while (last->next) {
last->pc += !is_last;
last->pc = pc; // restore original pc for report
last = last->next;
}
last->pc += !is_last;
last->pc = pc; // restore original pc for report
last->next = stack;
stack = ent;
}