|
15 | 15 |
|
16 | 16 | namespace __tsan { |
17 | 17 |
|
| 18 | +// How many log accesses to flush at one time |
| 19 | +#define STATS_BUFFER_COUNT 10000000 |
| 20 | + |
| 21 | +struct AccessData { |
| 22 | + uptr Address; |
| 23 | + uptr Size; |
| 24 | + Tid ThreadId; |
| 25 | + u8 Type; |
| 26 | +}; |
| 27 | + |
| 28 | +static Mutex LogMutex; |
| 29 | +static u32 LogDataOffset = 0; |
| 30 | +static AccessData LogData[STATS_BUFFER_COUNT]; |
| 31 | +static char LogString[STATS_BUFFER_COUNT * 64]; |
| 32 | + |
| 33 | +void LogFlushData() { |
| 34 | + u32 Offset = 0; |
| 35 | + for (u32 I = 0; I < LogDataOffset; ++I) |
| 36 | + Offset += internal_snprintf(LogString + Offset, |
| 37 | + sizeof(LogString) - Offset, |
| 38 | + " > 0x%8lx %lu 0x%02x %u\n", |
| 39 | + LogData[I].Address, |
| 40 | + LogData[I].Size, |
| 41 | + LogData[I].Type, |
| 42 | + LogData[I].ThreadId); |
| 43 | + Printf("%s", LogString); |
| 44 | +} |
| 45 | + |
| 46 | +void LogMemoryAccess(uptr Address, uptr Size, |
| 47 | + AccessType Type, Tid ThreadId) { |
| 48 | + LogMutex.Lock(); |
| 49 | + LogData[LogDataOffset++] = {Address, Size, ThreadId, static_cast<u8>(Type)}; |
| 50 | + if (LogDataOffset == STATS_BUFFER_COUNT) { |
| 51 | + LogFlushData(); |
| 52 | + LogDataOffset = 0; |
| 53 | + } |
| 54 | + LogMutex.Unlock(); |
| 55 | +} |
| 56 | + |
18 | 57 | ALWAYS_INLINE USED bool TryTraceMemoryAccess(ThreadState* thr, uptr pc, |
19 | 58 | uptr addr, uptr size, |
20 | 59 | AccessType typ) { |
@@ -419,6 +458,7 @@ NOINLINE void TraceRestartMemoryAccess(ThreadState* thr, uptr pc, uptr addr, |
419 | 458 |
|
420 | 459 | ALWAYS_INLINE USED void MemoryAccess(ThreadState* thr, uptr pc, uptr addr, |
421 | 460 | uptr size, AccessType typ) { |
| 461 | + LogMemoryAccess(addr, size, typ, thr->tid); |
422 | 462 | RawShadow* shadow_mem = MemToShadow(addr); |
423 | 463 | UNUSED char memBuf[4][64]; |
424 | 464 | DPrintf2("#%d: Access: %d@%d %p/%zd typ=0x%x {%s, %s, %s, %s}\n", thr->tid, |
@@ -454,6 +494,7 @@ void RestartMemoryAccess16(ThreadState* thr, uptr pc, uptr addr, |
454 | 494 | ALWAYS_INLINE USED void MemoryAccess16(ThreadState* thr, uptr pc, uptr addr, |
455 | 495 | AccessType typ) { |
456 | 496 | const uptr size = 16; |
| 497 | + LogMemoryAccess(addr, size, typ, thr->tid); |
457 | 498 | FastState fast_state = thr->fast_state; |
458 | 499 | if (UNLIKELY(fast_state.GetIgnoreBit())) |
459 | 500 | return; |
@@ -666,6 +707,7 @@ template <bool is_read> |
666 | 707 | void MemoryAccessRangeT(ThreadState* thr, uptr pc, uptr addr, uptr size) { |
667 | 708 | const AccessType typ = |
668 | 709 | (is_read ? kAccessRead : kAccessWrite) | kAccessNoRodata; |
| 710 | + LogMemoryAccess(addr, size, typ, thr->tid); |
669 | 711 | RawShadow* shadow_mem = MemToShadow(addr); |
670 | 712 | DPrintf2("#%d: MemoryAccessRange: @%p %p size=%d is_read=%d\n", thr->tid, |
671 | 713 | (void*)pc, (void*)addr, (int)size, is_read); |
|
0 commit comments