Hi tsan developers,
We are trying to modify tsan for Golang to print some traces for multi-threaded programs. To be more specific, we want to print the channel-related events, such as send, recv etc.
To do this, we have done the following modifications. For example, in order to print the channel send events,
1. we add a function racechansend(addr unsafe.Pointer, pc uintptr), which takes the channel address addr and program counter pc as inputs, in golang/src/runtime/race0.go and golang/src/runtime/race.go. In race0.go, this is an empty function that only throws race exceptions (because this file only contains functions when race detector is not enabled for Go). In race.go, it calls racecall(&__tsan_chan_send, getg().racectx, uintptr(addr), pc, 0).
2. we add a function void __tsan_chan_send(ThreadState *thr, uptr addr, uptr pc) in tsan_go.cpp under llvm/compiler-rt/lib/tsan/go/ which simply does some printing.
3. we call this racechansend function in golang/src/runtime/chan.go
This works fine, but we have encountered some segmentation faults when we try to print out the call stack of some memory read/write instructions using function void PrintCurrentStack(ThreadState *thr, uptr pc) from tsan_rtl_report.cpp.
After some debugging, we belive the problem is caused by the go_runtime_cb in tsan_go.cpp, which calls back into Golang code. That is, PrintCurrentStack will call go_runtime_cb and the problem is that somehow the current thread context g is set to be null, and when trying to access the field g.m, it causes segmentation faults (the assembly instruction MOVQ g_m(R14), R13 from function runtime·racecallbackthunk in golang/src/runtime/race_amd64.s).
We wonder if you have any ideas why this is happening, and how should we fix this problem? Thanks!