forked from OSchip/llvm-project
[Sanitizer]: Introduce a common internal printf function. For now, also use tool-specific wrappers TsanPrintf (its output is controlled by TSan flags) and AsanPrintf (which copies its results to the ASan-private buffer). Supported formats: %[z]{d,u,x}, %s, %p. Re-write all format strings in TSan according to this format (this should have no effect on 64-bit platforms).
llvm-svn: 158065
This commit is contained in:
parent
88aeaf6ac4
commit
51ae983718
|
@ -217,18 +217,18 @@ struct AsanChunk: public ChunkBase {
|
|||
|
||||
void DescribeAddress(uptr addr, uptr access_size) {
|
||||
uptr offset;
|
||||
Printf("%p is located ", (void*)addr);
|
||||
AsanPrintf("%p is located ", (void*)addr);
|
||||
if (AddrIsInside(addr, access_size, &offset)) {
|
||||
Printf("%zu bytes inside of", offset);
|
||||
AsanPrintf("%zu bytes inside of", offset);
|
||||
} else if (AddrIsAtLeft(addr, access_size, &offset)) {
|
||||
Printf("%zu bytes to the left of", offset);
|
||||
AsanPrintf("%zu bytes to the left of", offset);
|
||||
} else if (AddrIsAtRight(addr, access_size, &offset)) {
|
||||
Printf("%zu bytes to the right of", offset);
|
||||
AsanPrintf("%zu bytes to the right of", offset);
|
||||
} else {
|
||||
Printf(" somewhere around (this is AddressSanitizer bug!)");
|
||||
AsanPrintf(" somewhere around (this is AddressSanitizer bug!)");
|
||||
}
|
||||
Printf(" %zu-byte region [%p,%p)\n",
|
||||
used_size, (void*)beg(), (void*)(beg() + used_size));
|
||||
AsanPrintf(" %zu-byte region [%p,%p)\n",
|
||||
used_size, (void*)beg(), (void*)(beg() + used_size));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -588,20 +588,20 @@ static void Describe(uptr addr, uptr access_size) {
|
|||
if (m->free_tid >= 0) {
|
||||
AsanThreadSummary *free_thread =
|
||||
asanThreadRegistry().FindByTid(m->free_tid);
|
||||
Printf("freed by thread T%d here:\n", free_thread->tid());
|
||||
AsanPrintf("freed by thread T%d here:\n", free_thread->tid());
|
||||
AsanStackTrace free_stack;
|
||||
AsanStackTrace::UncompressStack(&free_stack, m->compressed_free_stack(),
|
||||
m->compressed_free_stack_size());
|
||||
free_stack.PrintStack();
|
||||
Printf("previously allocated by thread T%d here:\n",
|
||||
alloc_thread->tid());
|
||||
AsanPrintf("previously allocated by thread T%d here:\n",
|
||||
alloc_thread->tid());
|
||||
|
||||
alloc_stack.PrintStack();
|
||||
t->summary()->Announce();
|
||||
free_thread->Announce();
|
||||
alloc_thread->Announce();
|
||||
} else {
|
||||
Printf("allocated by thread T%d here:\n", alloc_thread->tid());
|
||||
AsanPrintf("allocated by thread T%d here:\n", alloc_thread->tid());
|
||||
alloc_stack.PrintStack();
|
||||
t->summary()->Announce();
|
||||
alloc_thread->Announce();
|
||||
|
@ -711,13 +711,13 @@ static void Deallocate(u8 *ptr, AsanStackTrace *stack) {
|
|||
u16 old_chunk_state = AtomicExchange(&m->chunk_state, CHUNK_QUARANTINE);
|
||||
|
||||
if (old_chunk_state == CHUNK_QUARANTINE) {
|
||||
Report("ERROR: AddressSanitizer attempting double-free on %p:\n", ptr);
|
||||
AsanReport("ERROR: AddressSanitizer attempting double-free on %p:\n", ptr);
|
||||
stack->PrintStack();
|
||||
Describe((uptr)ptr, 1);
|
||||
ShowStatsAndAbort();
|
||||
} else if (old_chunk_state != CHUNK_ALLOCATED) {
|
||||
Report("ERROR: AddressSanitizer attempting free on address which was not"
|
||||
" malloc()-ed: %p\n", ptr);
|
||||
AsanReport("ERROR: AddressSanitizer attempting free on address "
|
||||
"which was not malloc()-ed: %p\n", ptr);
|
||||
stack->PrintStack();
|
||||
ShowStatsAndAbort();
|
||||
}
|
||||
|
@ -867,8 +867,9 @@ uptr asan_malloc_usable_size(void *ptr, AsanStackTrace *stack) {
|
|||
if (ptr == 0) return 0;
|
||||
uptr usable_size = malloc_info.AllocationSize((uptr)ptr);
|
||||
if (FLAG_check_malloc_usable_size && (usable_size == 0)) {
|
||||
Report("ERROR: AddressSanitizer attempting to call malloc_usable_size() "
|
||||
"for pointer which is not owned: %p\n", ptr);
|
||||
AsanReport("ERROR: AddressSanitizer attempting to call "
|
||||
"malloc_usable_size() for pointer which is "
|
||||
"not owned: %p\n", ptr);
|
||||
stack->PrintStack();
|
||||
Describe((uptr)ptr, 1);
|
||||
ShowStatsAndAbort();
|
||||
|
@ -1072,9 +1073,9 @@ uptr __asan_get_allocated_size(const void *p) {
|
|||
uptr allocated_size = malloc_info.AllocationSize((uptr)p);
|
||||
// Die if p is not malloced or if it is already freed.
|
||||
if (allocated_size == 0) {
|
||||
Report("ERROR: AddressSanitizer attempting to call "
|
||||
"__asan_get_allocated_size() for pointer which is "
|
||||
"not owned: %p\n", p);
|
||||
AsanReport("ERROR: AddressSanitizer attempting to call "
|
||||
"__asan_get_allocated_size() for pointer which is "
|
||||
"not owned: %p\n", p);
|
||||
PRINT_CURRENT_STACK();
|
||||
Describe((uptr)p, 1);
|
||||
ShowStatsAndAbort();
|
||||
|
|
|
@ -66,22 +66,22 @@ void PrintIfASCII(const Global &g) {
|
|||
if (!isascii(*(char*)p)) return;
|
||||
}
|
||||
if (*(char*)(g.beg + g.size - 1) != 0) return;
|
||||
Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
|
||||
AsanPrintf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
|
||||
}
|
||||
|
||||
bool DescribeAddrIfMyRedZone(const Global &g, uptr addr) {
|
||||
if (addr < g.beg - kGlobalAndStackRedzone) return false;
|
||||
if (addr >= g.beg + g.size_with_redzone) return false;
|
||||
Printf("%p is located ", (void*)addr);
|
||||
AsanPrintf("%p is located ", (void*)addr);
|
||||
if (addr < g.beg) {
|
||||
Printf("%zd bytes to the left", g.beg - addr);
|
||||
AsanPrintf("%zd bytes to the left", g.beg - addr);
|
||||
} else if (addr >= g.beg + g.size) {
|
||||
Printf("%zd bytes to the right", addr - (g.beg + g.size));
|
||||
AsanPrintf("%zd bytes to the right", addr - (g.beg + g.size));
|
||||
} else {
|
||||
Printf("%zd bytes inside", addr - g.beg); // Can it happen?
|
||||
AsanPrintf("%zd bytes inside", addr - g.beg); // Can it happen?
|
||||
}
|
||||
Printf(" of global variable '%s' (0x%zx) of size %zu\n",
|
||||
g.name, g.beg, g.size);
|
||||
AsanPrintf(" of global variable '%s' (0x%zx) of size %zu\n",
|
||||
g.name, g.beg, g.size);
|
||||
PrintIfASCII(g);
|
||||
return true;
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ bool DescribeAddrIfGlobal(uptr addr) {
|
|||
for (ListOfGlobals *l = list_of_globals; l; l = l->next) {
|
||||
const Global &g = *l->g;
|
||||
if (FLAG_report_globals >= 2)
|
||||
Printf("Search Global: beg=%p size=%zu name=%s\n",
|
||||
(void*)g.beg, g.size, (char*)g.name);
|
||||
AsanPrintf("Search Global: beg=%p size=%zu name=%s\n",
|
||||
(void*)g.beg, g.size, (char*)g.name);
|
||||
res |= DescribeAddrIfMyRedZone(g, addr);
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -155,9 +155,9 @@ static inline bool RangesOverlap(const char *offset1, uptr length1,
|
|||
const char *offset1 = (const char*)_offset1; \
|
||||
const char *offset2 = (const char*)_offset2; \
|
||||
if (RangesOverlap(offset1, length1, offset2, length2)) { \
|
||||
Report("ERROR: AddressSanitizer %s-param-overlap: " \
|
||||
"memory ranges [%p,%p) and [%p, %p) overlap\n", \
|
||||
name, offset1, offset1 + length1, offset2, offset2 + length2); \
|
||||
AsanReport("ERROR: AddressSanitizer %s-param-overlap: " \
|
||||
"memory ranges [%p,%p) and [%p, %p) overlap\n", \
|
||||
name, offset1, offset1 + length1, offset2, offset2 + length2); \
|
||||
PRINT_CURRENT_STACK(); \
|
||||
ShowStatsAndAbort(); \
|
||||
} \
|
||||
|
|
|
@ -157,11 +157,10 @@ void AsanTSDSet(void *tsd);
|
|||
uptr ReadFileToBuffer(const char *file_name, char **buff,
|
||||
uptr *buff_size, uptr max_len);
|
||||
|
||||
void AppendToErrorMessageBuffer(const char *buffer);
|
||||
// asan_printf.cc
|
||||
void RawWrite(const char *buffer);
|
||||
int SNPrintf(char *buffer, uptr length, const char *format, ...);
|
||||
void Printf(const char *format, ...);
|
||||
void Report(const char *format, ...);
|
||||
void AsanPrintf(const char *format, ...) FORMAT(1, 2);
|
||||
void AsanReport(const char *format, ...) FORMAT(1, 2);
|
||||
|
||||
// Don't use std::min and std::max, to minimize dependency on libstdc++.
|
||||
template<class T> T Min(T a, T b) { return a < b ? a : b; }
|
||||
|
|
|
@ -119,14 +119,14 @@ void print_zone_for_ptr(void *ptr) {
|
|||
malloc_zone_t *orig_zone = malloc_zone_from_ptr(ptr);
|
||||
if (orig_zone) {
|
||||
if (orig_zone->zone_name) {
|
||||
Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
|
||||
ptr, orig_zone, orig_zone->zone_name);
|
||||
AsanPrintf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
|
||||
ptr, orig_zone, orig_zone->zone_name);
|
||||
} else {
|
||||
Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
|
||||
ptr, orig_zone);
|
||||
AsanPrintf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
|
||||
ptr, orig_zone);
|
||||
}
|
||||
} else {
|
||||
Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
|
||||
AsanPrintf("malloc_zone_from_ptr(%p) = 0\n", ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,8 +146,9 @@ void mz_free(malloc_zone_t *zone, void *ptr) {
|
|||
asan_free(ptr, &stack);
|
||||
} else {
|
||||
// Let us just leak this memory for now.
|
||||
Printf("mz_free(%p) -- attempting to free unallocated memory.\n"
|
||||
"AddressSanitizer is ignoring this error on Mac OS now.\n", ptr);
|
||||
AsanPrintf("mz_free(%p) -- attempting to free unallocated memory.\n"
|
||||
"AddressSanitizer is ignoring this error on Mac OS now.\n",
|
||||
ptr);
|
||||
print_zone_for_ptr(ptr);
|
||||
GET_STACK_TRACE_HERE_FOR_FREE(ptr);
|
||||
stack.PrintStack();
|
||||
|
@ -170,8 +171,9 @@ void cf_free(void *ptr, void *info) {
|
|||
asan_free(ptr, &stack);
|
||||
} else {
|
||||
// Let us just leak this memory for now.
|
||||
Printf("cf_free(%p) -- attempting to free unallocated memory.\n"
|
||||
"AddressSanitizer is ignoring this error on Mac OS now.\n", ptr);
|
||||
AsanPrintf("cf_free(%p) -- attempting to free unallocated memory.\n"
|
||||
"AddressSanitizer is ignoring this error on Mac OS now.\n",
|
||||
ptr);
|
||||
print_zone_for_ptr(ptr);
|
||||
GET_STACK_TRACE_HERE_FOR_FREE(ptr);
|
||||
stack.PrintStack();
|
||||
|
@ -191,8 +193,9 @@ void *mz_realloc(malloc_zone_t *zone, void *ptr, size_t size) {
|
|||
// We can't recover from reallocating an unknown address, because
|
||||
// this would require reading at most |size| bytes from
|
||||
// potentially unaccessible memory.
|
||||
Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n", ptr);
|
||||
AsanPrintf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n",
|
||||
ptr);
|
||||
print_zone_for_ptr(ptr);
|
||||
GET_STACK_TRACE_HERE_FOR_FREE(ptr);
|
||||
stack.PrintStack();
|
||||
|
@ -214,8 +217,9 @@ void *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) {
|
|||
// We can't recover from reallocating an unknown address, because
|
||||
// this would require reading at most |size| bytes from
|
||||
// potentially unaccessible memory.
|
||||
Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n", ptr);
|
||||
AsanPrintf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
|
||||
"This is an unrecoverable problem, exiting now.\n",
|
||||
ptr);
|
||||
print_zone_for_ptr(ptr);
|
||||
GET_STACK_TRACE_HERE_FOR_FREE(ptr);
|
||||
stack.PrintStack();
|
||||
|
@ -227,7 +231,7 @@ void *cf_realloc(void *ptr, CFIndex size, CFOptionFlags hint, void *info) {
|
|||
|
||||
void mz_destroy(malloc_zone_t* zone) {
|
||||
// A no-op -- we will not be destroyed!
|
||||
Printf("mz_destroy() called -- ignoring\n");
|
||||
AsanPrintf("mz_destroy() called -- ignoring\n");
|
||||
}
|
||||
// from AvailabilityMacros.h
|
||||
#if defined(MAC_OS_X_VERSION_10_6) && \
|
||||
|
|
|
@ -86,11 +86,11 @@ static void ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {
|
|||
if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
|
||||
uptr pc, sp, bp;
|
||||
GetPcSpBp(context, &pc, &sp, &bp);
|
||||
Report("ERROR: AddressSanitizer crashed on unknown address %p"
|
||||
" (pc %p sp %p bp %p T%d)\n",
|
||||
(void*)addr, (void*)pc, (void*)sp, (void*)bp,
|
||||
asanThreadRegistry().GetCurrentTidOrMinusOne());
|
||||
Printf("AddressSanitizer can not provide additional info. ABORTING\n");
|
||||
AsanReport("ERROR: AddressSanitizer crashed on unknown address %p"
|
||||
" (pc %p sp %p bp %p T%d)\n",
|
||||
(void*)addr, (void*)pc, (void*)sp, (void*)bp,
|
||||
asanThreadRegistry().GetCurrentTidOrMinusOne());
|
||||
AsanPrintf("AddressSanitizer can not provide additional info. ABORTING\n");
|
||||
GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
|
||||
stack.PrintStack();
|
||||
ShowStatsAndAbort();
|
||||
|
|
|
@ -17,143 +17,18 @@
|
|||
#include "asan_internal.h"
|
||||
#include "asan_interceptors.h"
|
||||
#include "sanitizer_common/sanitizer_libc.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __sanitizer {
|
||||
int VSNPrintf(char *buff, int buff_length, const char *format, va_list args);
|
||||
} // namespace __sanitizer
|
||||
|
||||
namespace __asan {
|
||||
|
||||
extern char *error_message_buffer;
|
||||
extern uptr error_message_buffer_pos, error_message_buffer_size;
|
||||
|
||||
void RawWrite(const char *buffer) {
|
||||
static const char *kRawWriteError = "RawWrite can't output requested buffer!";
|
||||
uptr length = (uptr)internal_strlen(buffer);
|
||||
if (length != internal_write(2, buffer, length)) {
|
||||
internal_write(2, kRawWriteError, internal_strlen(kRawWriteError));
|
||||
Die();
|
||||
}
|
||||
if (error_message_buffer) {
|
||||
int remaining = error_message_buffer_size - error_message_buffer_pos;
|
||||
internal_strncpy(error_message_buffer + error_message_buffer_pos,
|
||||
buffer, remaining);
|
||||
error_message_buffer[error_message_buffer_size - 1] = '\0';
|
||||
// FIXME: reallocate the buffer instead of truncating the message.
|
||||
error_message_buffer_pos += remaining > length ? length : remaining;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int AppendChar(char **buff, const char *buff_end, char c) {
|
||||
if (*buff < buff_end) {
|
||||
**buff = c;
|
||||
(*buff)++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Appends number in a given base to buffer. If its length is less than
|
||||
// "minimal_num_length", it is padded with leading zeroes.
|
||||
static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
|
||||
u8 base, u8 minimal_num_length) {
|
||||
uptr const kMaxLen = 30;
|
||||
RAW_CHECK(base == 10 || base == 16);
|
||||
RAW_CHECK(minimal_num_length < kMaxLen);
|
||||
uptr num_buffer[kMaxLen];
|
||||
uptr pos = 0;
|
||||
do {
|
||||
RAW_CHECK_MSG(pos < kMaxLen, "appendNumber buffer overflow");
|
||||
num_buffer[pos++] = num % base;
|
||||
num /= base;
|
||||
} while (num > 0);
|
||||
while (pos < minimal_num_length) num_buffer[pos++] = 0;
|
||||
int result = 0;
|
||||
while (pos-- > 0) {
|
||||
uptr digit = num_buffer[pos];
|
||||
result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
|
||||
: 'a' + digit - 10);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int AppendSignedDecimal(char **buff, const char *buff_end,
|
||||
s64 num) {
|
||||
int result = 0;
|
||||
if (num < 0) {
|
||||
result += AppendChar(buff, buff_end, '-');
|
||||
num = -num;
|
||||
}
|
||||
result += AppendUnsigned(buff, buff_end, (u64)num, 10, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int AppendString(char **buff, const char *buff_end,
|
||||
const char *s) {
|
||||
// Avoid library functions like stpcpy here.
|
||||
RAW_CHECK_MSG(s, "Error: passing a 0 pointer to AppendString\n");
|
||||
int result = 0;
|
||||
for (; *s; s++) {
|
||||
result += AppendChar(buff, buff_end, *s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int AppendPointer(char **buff, const char *buff_end,
|
||||
u64 ptr_value) {
|
||||
int result = 0;
|
||||
result += AppendString(buff, buff_end, "0x");
|
||||
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
|
||||
(__WORDSIZE == 64) ? 12 : 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int VSNPrintf(char *buff, int buff_length,
|
||||
const char *format, va_list args) {
|
||||
static const char *kPrintfFormatsHelp = "Supported Printf formats: "
|
||||
"%%[z]{d,u,x}; %%p; %%s";
|
||||
RAW_CHECK(format);
|
||||
RAW_CHECK(buff_length > 0);
|
||||
const char *buff_end = &buff[buff_length - 1];
|
||||
const char *cur = format;
|
||||
int result = 0;
|
||||
for (; *cur; cur++) {
|
||||
if (*cur == '%') {
|
||||
cur++;
|
||||
bool have_z = (*cur == 'z');
|
||||
cur += have_z;
|
||||
s64 dval;
|
||||
u64 uval;
|
||||
switch (*cur) {
|
||||
case 'd': dval = have_z ? va_arg(args, sptr)
|
||||
: va_arg(args, int);
|
||||
result += AppendSignedDecimal(&buff, buff_end, dval);
|
||||
break;
|
||||
case 'u': uval = have_z ? va_arg(args, uptr)
|
||||
: va_arg(args, unsigned);
|
||||
result += AppendUnsigned(&buff, buff_end, uval, 10, 0);
|
||||
break;
|
||||
case 'x': uval = have_z ? va_arg(args, uptr)
|
||||
: va_arg(args, unsigned);
|
||||
result += AppendUnsigned(&buff, buff_end, uval, 16, 0);
|
||||
break;
|
||||
case 'p': RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
|
||||
result += AppendPointer(&buff, buff_end,
|
||||
va_arg(args, uptr));
|
||||
break;
|
||||
case 's': RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
|
||||
result += AppendString(&buff, buff_end, va_arg(args, char*));
|
||||
break;
|
||||
default: RAW_CHECK_MSG(false, kPrintfFormatsHelp);
|
||||
}
|
||||
} else {
|
||||
result += AppendChar(&buff, buff_end, *cur);
|
||||
}
|
||||
}
|
||||
RAW_CHECK(buff <= buff_end);
|
||||
AppendChar(&buff, buff_end + 1, '\0');
|
||||
return result;
|
||||
}
|
||||
|
||||
void Printf(const char *format, ...) {
|
||||
void AsanPrintf(const char *format, ...) {
|
||||
const int kLen = 1024 * 4;
|
||||
char buffer[kLen];
|
||||
va_list args;
|
||||
|
@ -162,22 +37,11 @@ void Printf(const char *format, ...) {
|
|||
va_end(args);
|
||||
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Printf is too short!\n");
|
||||
RawWrite(buffer);
|
||||
AppendToErrorMessageBuffer(buffer);
|
||||
}
|
||||
|
||||
// Writes at most "length" symbols to "buffer" (including trailing '\0').
|
||||
// Returns the number of symbols that should have been written to buffer
|
||||
// (not including trailing '\0'). Thus, the string is truncated
|
||||
// iff return value is not less than "length".
|
||||
int SNPrintf(char *buffer, uptr length, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int needed_length = VSNPrintf(buffer, length, format, args);
|
||||
va_end(args);
|
||||
return needed_length;
|
||||
}
|
||||
|
||||
// Like Printf, but prints the current PID before the output string.
|
||||
void Report(const char *format, ...) {
|
||||
// Like AsanPrintf, but prints the current PID before the output string.
|
||||
void AsanReport(const char *format, ...) {
|
||||
const int kLen = 1024 * 4;
|
||||
char buffer[kLen];
|
||||
int needed_length = SNPrintf(buffer, kLen, "==%d== ", GetPid());
|
||||
|
@ -189,6 +53,7 @@ void Report(const char *format, ...) {
|
|||
va_end(args);
|
||||
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
|
||||
RawWrite(buffer);
|
||||
AppendToErrorMessageBuffer(buffer);
|
||||
}
|
||||
|
||||
} // namespace __asan
|
||||
|
|
|
@ -95,11 +95,11 @@ void ShowStatsAndAbort() {
|
|||
static void PrintBytes(const char *before, uptr *a) {
|
||||
u8 *bytes = (u8*)a;
|
||||
uptr byte_num = (__WORDSIZE) / 8;
|
||||
Printf("%s%p:", before, (void*)a);
|
||||
AsanPrintf("%s%p:", before, (void*)a);
|
||||
for (uptr i = 0; i < byte_num; i++) {
|
||||
Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
|
||||
AsanPrintf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
|
||||
}
|
||||
Printf("\n");
|
||||
AsanPrintf("\n");
|
||||
}
|
||||
|
||||
uptr ReadFileToBuffer(const char *file_name, char **buff,
|
||||
|
@ -133,11 +133,23 @@ uptr ReadFileToBuffer(const char *file_name, char **buff,
|
|||
return read_len;
|
||||
}
|
||||
|
||||
void AppendToErrorMessageBuffer(const char *buffer) {
|
||||
if (error_message_buffer) {
|
||||
uptr length = (uptr)internal_strlen(buffer);
|
||||
int remaining = error_message_buffer_size - error_message_buffer_pos;
|
||||
internal_strncpy(error_message_buffer + error_message_buffer_pos,
|
||||
buffer, remaining);
|
||||
error_message_buffer[error_message_buffer_size - 1] = '\0';
|
||||
// FIXME: reallocate the buffer instead of truncating the message.
|
||||
error_message_buffer_pos += remaining > length ? length : remaining;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- mmap -------------------- {{{1
|
||||
void OutOfMemoryMessageAndDie(const char *mem_type, uptr size) {
|
||||
Report("ERROR: AddressSanitizer failed to allocate "
|
||||
"0x%zx (%zd) bytes of %s\n",
|
||||
size, size, mem_type);
|
||||
AsanReport("ERROR: AddressSanitizer failed to allocate "
|
||||
"0x%zx (%zd) bytes of %s\n",
|
||||
size, size, mem_type);
|
||||
PRINT_CURRENT_STACK();
|
||||
ShowStatsAndAbort();
|
||||
}
|
||||
|
@ -187,14 +199,14 @@ static bool DescribeStackAddress(uptr addr, uptr access_size) {
|
|||
internal_strncat(buf, frame_descr,
|
||||
Min(kBufSize,
|
||||
static_cast<sptr>(name_end - frame_descr)));
|
||||
Printf("Address %p is located at offset %zu "
|
||||
"in frame <%s> of T%d's stack:\n",
|
||||
(void*)addr, offset, buf, t->tid());
|
||||
AsanPrintf("Address %p is located at offset %zu "
|
||||
"in frame <%s> of T%d's stack:\n",
|
||||
(void*)addr, offset, buf, t->tid());
|
||||
// Report the number of stack objects.
|
||||
char *p;
|
||||
uptr n_objects = internal_simple_strtoll(name_end, &p, 10);
|
||||
CHECK(n_objects > 0);
|
||||
Printf(" This frame has %zu object(s):\n", n_objects);
|
||||
AsanPrintf(" This frame has %zu object(s):\n", n_objects);
|
||||
// Report all objects in this frame.
|
||||
for (uptr i = 0; i < n_objects; i++) {
|
||||
uptr beg, size;
|
||||
|
@ -203,19 +215,19 @@ static bool DescribeStackAddress(uptr addr, uptr access_size) {
|
|||
size = internal_simple_strtoll(p, &p, 10);
|
||||
len = internal_simple_strtoll(p, &p, 10);
|
||||
if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
|
||||
Printf("AddressSanitizer can't parse the stack frame descriptor: |%s|\n",
|
||||
frame_descr);
|
||||
AsanPrintf("AddressSanitizer can't parse the stack frame "
|
||||
"descriptor: |%s|\n", frame_descr);
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
buf[0] = 0;
|
||||
internal_strncat(buf, p, Min(kBufSize, len));
|
||||
p += len;
|
||||
Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
|
||||
AsanPrintf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
|
||||
}
|
||||
Printf("HINT: this may be a false positive if your program uses "
|
||||
"some custom stack unwind mechanism\n"
|
||||
" (longjmp and C++ exceptions *are* supported)\n");
|
||||
AsanPrintf("HINT: this may be a false positive if your program uses "
|
||||
"some custom stack unwind mechanism\n"
|
||||
" (longjmp and C++ exceptions *are* supported)\n");
|
||||
t->summary()->Announce();
|
||||
return true;
|
||||
}
|
||||
|
@ -320,7 +332,7 @@ static void BoolFlagValue(const char *flags, const char *flag,
|
|||
}
|
||||
|
||||
static void asan_atexit() {
|
||||
Printf("AddressSanitizer exit stats:\n");
|
||||
AsanPrintf("AddressSanitizer exit stats:\n");
|
||||
__asan_print_accumulated_stats();
|
||||
}
|
||||
|
||||
|
@ -370,7 +382,8 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
|
|||
static int num_calls = 0;
|
||||
if (AtomicInc(&num_calls) > 1) return;
|
||||
|
||||
Printf("=================================================================\n");
|
||||
AsanPrintf("===================================================="
|
||||
"=============\n");
|
||||
const char *bug_descr = "unknown-crash";
|
||||
if (AddrIsInMem(addr)) {
|
||||
u8 *shadow_addr = (u8*)MemToShadow(addr);
|
||||
|
@ -417,13 +430,13 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
|
|||
curr_thread->fake_stack().StopUsingFakeStack();
|
||||
}
|
||||
|
||||
Report("ERROR: AddressSanitizer %s on address "
|
||||
"%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
|
||||
bug_descr, (void*)addr, pc, bp, sp);
|
||||
AsanReport("ERROR: AddressSanitizer %s on address "
|
||||
"%p at pc 0x%zx bp 0x%zx sp 0x%zx\n",
|
||||
bug_descr, (void*)addr, pc, bp, sp);
|
||||
|
||||
Printf("%s of size %zu at %p thread T%d\n",
|
||||
access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
|
||||
access_size, (void*)addr, curr_tid);
|
||||
AsanPrintf("%s of size %zu at %p thread T%d\n",
|
||||
access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
|
||||
access_size, (void*)addr, curr_tid);
|
||||
|
||||
if (FLAG_debug) {
|
||||
PrintBytes("PC: ", (uptr*)pc);
|
||||
|
@ -437,13 +450,13 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
|
|||
DescribeAddress(addr, access_size);
|
||||
|
||||
uptr shadow_addr = MemToShadow(addr);
|
||||
Report("ABORTING\n");
|
||||
AsanReport("ABORTING\n");
|
||||
__asan_print_accumulated_stats();
|
||||
Printf("Shadow byte and word:\n");
|
||||
Printf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
|
||||
AsanPrintf("Shadow byte and word:\n");
|
||||
AsanPrintf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
|
||||
uptr aligned_shadow = shadow_addr & ~(kWordSize - 1);
|
||||
PrintBytes(" ", (uptr*)(aligned_shadow));
|
||||
Printf("More shadow bytes:\n");
|
||||
AsanPrintf("More shadow bytes:\n");
|
||||
PrintBytes(" ", (uptr*)(aligned_shadow-4*kWordSize));
|
||||
PrintBytes(" ", (uptr*)(aligned_shadow-3*kWordSize));
|
||||
PrintBytes(" ", (uptr*)(aligned_shadow-2*kWordSize));
|
||||
|
|
|
@ -33,7 +33,7 @@ void AsanStackTrace::PrintStack(uptr *addr, uptr size) {
|
|||
uptr pc = addr[i];
|
||||
char buff[4096];
|
||||
ASAN_USE_EXTERNAL_SYMBOLIZER((void*)pc, buff, sizeof(buff));
|
||||
Printf(" #%zu 0x%zx %s\n", i, pc, buff);
|
||||
AsanPrintf(" #%zu 0x%zx %s\n", i, pc, buff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,19 +51,19 @@ void AsanStackTrace::PrintStack(uptr *addr, uptr size) {
|
|||
for (AddressInfoList *entry = address_info_list; entry;
|
||||
entry = entry->next) {
|
||||
AddressInfo info = entry->info;
|
||||
Printf(" #%zu 0x%zx %s:%d:%d\n", frame_num, pc,
|
||||
(info.file) ? info.file : "",
|
||||
info.line, info.column);
|
||||
AsanPrintf(" #%zu 0x%zx %s:%d:%d\n", frame_num, pc,
|
||||
(info.file) ? info.file : "",
|
||||
info.line, info.column);
|
||||
frame_num++;
|
||||
}
|
||||
address_info_list->Clear();
|
||||
} else {
|
||||
if (proc_maps.GetObjectNameAndOffset(pc, &offset,
|
||||
filename, sizeof(filename))) {
|
||||
Printf(" #%zu 0x%zx (%s+0x%zx)\n", frame_num, pc, filename,
|
||||
offset);
|
||||
AsanPrintf(" #%zu 0x%zx (%s+0x%zx)\n", frame_num, pc, filename,
|
||||
offset);
|
||||
} else {
|
||||
Printf(" #%zu 0x%zx\n", frame_num, pc);
|
||||
AsanPrintf(" #%zu 0x%zx\n", frame_num, pc);
|
||||
}
|
||||
frame_num++;
|
||||
}
|
||||
|
|
|
@ -27,30 +27,30 @@ AsanStats::AsanStats() {
|
|||
|
||||
static void PrintMallocStatsArray(const char *prefix,
|
||||
uptr (&array)[kNumberOfSizeClasses]) {
|
||||
Printf("%s", prefix);
|
||||
AsanPrintf("%s", prefix);
|
||||
for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
|
||||
if (!array[i]) continue;
|
||||
Printf("%zu:%zu; ", i, array[i]);
|
||||
AsanPrintf("%zu:%zu; ", i, array[i]);
|
||||
}
|
||||
Printf("\n");
|
||||
AsanPrintf("\n");
|
||||
}
|
||||
|
||||
void AsanStats::Print() {
|
||||
Printf("Stats: %zuM malloced (%zuM for red zones) by %zu calls\n",
|
||||
malloced>>20, malloced_redzones>>20, mallocs);
|
||||
Printf("Stats: %zuM realloced by %zu calls\n", realloced>>20, reallocs);
|
||||
Printf("Stats: %zuM freed by %zu calls\n", freed>>20, frees);
|
||||
Printf("Stats: %zuM really freed by %zu calls\n",
|
||||
really_freed>>20, real_frees);
|
||||
Printf("Stats: %zuM (%zu full pages) mmaped in %zu calls\n",
|
||||
mmaped>>20, mmaped / kPageSize, mmaps);
|
||||
AsanPrintf("Stats: %zuM malloced (%zuM for red zones) by %zu calls\n",
|
||||
malloced>>20, malloced_redzones>>20, mallocs);
|
||||
AsanPrintf("Stats: %zuM realloced by %zu calls\n", realloced>>20, reallocs);
|
||||
AsanPrintf("Stats: %zuM freed by %zu calls\n", freed>>20, frees);
|
||||
AsanPrintf("Stats: %zuM really freed by %zu calls\n",
|
||||
really_freed>>20, real_frees);
|
||||
AsanPrintf("Stats: %zuM (%zu full pages) mmaped in %zu calls\n",
|
||||
mmaped>>20, mmaped / kPageSize, mmaps);
|
||||
|
||||
PrintMallocStatsArray(" mmaps by size class: ", mmaped_by_size);
|
||||
PrintMallocStatsArray(" mallocs by size class: ", malloced_by_size);
|
||||
PrintMallocStatsArray(" frees by size class: ", freed_by_size);
|
||||
PrintMallocStatsArray(" rfrees by size class: ", really_freed_by_size);
|
||||
Printf("Stats: malloc large: %zu small slow: %zu\n",
|
||||
malloc_large, malloc_small_slow);
|
||||
AsanPrintf("Stats: malloc large: %zu small slow: %zu\n",
|
||||
malloc_large, malloc_small_slow);
|
||||
}
|
||||
|
||||
static AsanLock print_lock(LINKER_INITIALIZED);
|
||||
|
|
|
@ -41,7 +41,7 @@ class AsanThreadSummary {
|
|||
if (tid_ == 0) return; // no need to announce the main thread.
|
||||
if (!announced_) {
|
||||
announced_ = true;
|
||||
Printf("Thread T%d created by T%d here:\n", tid_, parent_tid_);
|
||||
AsanPrintf("Thread T%d created by T%d here:\n", tid_, parent_tid_);
|
||||
stack_.PrintStack();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,10 @@ void RawWrite(const char *buffer);
|
|||
void *MmapOrDie(uptr size);
|
||||
void UnmapOrDie(void *addr, uptr size);
|
||||
|
||||
void Printf(const char *format, ...) FORMAT(1, 2);
|
||||
int SNPrintf(char *buffer, uptr length, const char *format, ...) FORMAT(3, 4);
|
||||
void Report(const char *format, ...) FORMAT(1, 2);
|
||||
|
||||
// Bit twiddling.
|
||||
inline bool IsPowerOfTwo(uptr x) {
|
||||
return (x & (x - 1)) == 0;
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
//===-- sanitizer_printf.cc -----------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is shared between AddressSanitizer and ThreadSanitizer.
|
||||
//
|
||||
// Internal printf function, used inside run-time libraries.
|
||||
// We can't use libc printf because we intercept some of the functions used
|
||||
// inside it.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "sanitizer_common.h"
|
||||
#include "sanitizer_libc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
namespace __sanitizer {
|
||||
|
||||
static int AppendChar(char **buff, const char *buff_end, char c) {
|
||||
if (*buff < buff_end) {
|
||||
**buff = c;
|
||||
(*buff)++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Appends number in a given base to buffer. If its length is less than
|
||||
// "minimal_num_length", it is padded with leading zeroes.
|
||||
static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
|
||||
u8 base, u8 minimal_num_length) {
|
||||
uptr const kMaxLen = 30;
|
||||
RAW_CHECK(base == 10 || base == 16);
|
||||
RAW_CHECK(minimal_num_length < kMaxLen);
|
||||
uptr num_buffer[kMaxLen];
|
||||
uptr pos = 0;
|
||||
do {
|
||||
RAW_CHECK_MSG(pos < kMaxLen, "appendNumber buffer overflow");
|
||||
num_buffer[pos++] = num % base;
|
||||
num /= base;
|
||||
} while (num > 0);
|
||||
while (pos < minimal_num_length) num_buffer[pos++] = 0;
|
||||
int result = 0;
|
||||
while (pos-- > 0) {
|
||||
uptr digit = num_buffer[pos];
|
||||
result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
|
||||
: 'a' + digit - 10);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num) {
|
||||
int result = 0;
|
||||
if (num < 0) {
|
||||
result += AppendChar(buff, buff_end, '-');
|
||||
num = -num;
|
||||
}
|
||||
result += AppendUnsigned(buff, buff_end, (u64)num, 10, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendString(char **buff, const char *buff_end, const char *s) {
|
||||
if (s == 0)
|
||||
s = "<null>";
|
||||
int result = 0;
|
||||
for (; *s; s++) {
|
||||
result += AppendChar(buff, buff_end, *s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
|
||||
int result = 0;
|
||||
result += AppendString(buff, buff_end, "0x");
|
||||
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
|
||||
(__WORDSIZE == 64) ? 12 : 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
int VSNPrintf(char *buff, int buff_length,
|
||||
const char *format, va_list args) {
|
||||
static const char *kPrintfFormatsHelp = "Supported Printf formats: "
|
||||
"%%[z]{d,u,x}; %%p; %%s\n";
|
||||
RAW_CHECK(format);
|
||||
RAW_CHECK(buff_length > 0);
|
||||
const char *buff_end = &buff[buff_length - 1];
|
||||
const char *cur = format;
|
||||
int result = 0;
|
||||
for (; *cur; cur++) {
|
||||
if (*cur != '%') {
|
||||
result += AppendChar(&buff, buff_end, *cur);
|
||||
continue;
|
||||
}
|
||||
cur++;
|
||||
bool have_z = (*cur == 'z');
|
||||
cur += have_z;
|
||||
s64 dval;
|
||||
u64 uval;
|
||||
switch (*cur) {
|
||||
case 'd': {
|
||||
dval = have_z ? va_arg(args, sptr)
|
||||
: va_arg(args, int);
|
||||
result += AppendSignedDecimal(&buff, buff_end, dval);
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
case 'x': {
|
||||
uval = have_z ? va_arg(args, uptr)
|
||||
: va_arg(args, unsigned);
|
||||
result += AppendUnsigned(&buff, buff_end, uval,
|
||||
(*cur == 'u') ? 10 : 16, 0);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
|
||||
result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
|
||||
result += AppendString(&buff, buff_end, va_arg(args, char*));
|
||||
break;
|
||||
}
|
||||
case '%' : {
|
||||
RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp);
|
||||
result += AppendChar(&buff, buff_end, '%');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
RAW_CHECK_MSG(false, kPrintfFormatsHelp);
|
||||
}
|
||||
}
|
||||
}
|
||||
RAW_CHECK(buff <= buff_end);
|
||||
AppendChar(&buff, buff_end + 1, '\0');
|
||||
return result;
|
||||
}
|
||||
|
||||
void Printf(const char *format, ...) {
|
||||
const int kLen = 1024 * 4;
|
||||
char *buffer = (char*)MmapOrDie(kLen);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int needed_length = VSNPrintf(buffer, kLen, format, args);
|
||||
va_end(args);
|
||||
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Printf is too short!\n");
|
||||
RawWrite(buffer);
|
||||
UnmapOrDie(buffer, kLen);
|
||||
}
|
||||
|
||||
// Writes at most "length" symbols to "buffer" (including trailing '\0').
|
||||
// Returns the number of symbols that should have been written to buffer
|
||||
// (not including trailing '\0'). Thus, the string is truncated
|
||||
// iff return value is not less than "length".
|
||||
int SNPrintf(char *buffer, uptr length, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int needed_length = VSNPrintf(buffer, length, format, args);
|
||||
va_end(args);
|
||||
return needed_length;
|
||||
}
|
||||
|
||||
// Like Printf, but prints the current PID before the output string.
|
||||
void Report(const char *format, ...) {
|
||||
const int kLen = 1024 * 4;
|
||||
char *buffer = (char*)MmapOrDie(kLen);
|
||||
int needed_length = SNPrintf(buffer, kLen, "==%d== ", GetPid());
|
||||
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
needed_length += VSNPrintf(buffer + needed_length, kLen - needed_length,
|
||||
format, args);
|
||||
va_end(args);
|
||||
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
|
||||
RawWrite(buffer);
|
||||
UnmapOrDie(buffer, kLen);
|
||||
}
|
||||
|
||||
} // namespace __sanitizer
|
|
@ -679,7 +679,7 @@ TSAN_INTERCEPTOR(int, pthread_create,
|
|||
// We place the huge ThreadState object into TLS, account for that.
|
||||
const uptr minstacksize = GetTlsSize() + 128*1024;
|
||||
if (stacksize < minstacksize) {
|
||||
DPrintf("ThreadSanitizer: stacksize %lu->%lu\n", stacksize, minstacksize);
|
||||
DPrintf("ThreadSanitizer: stacksize %zu->%zu\n", stacksize, minstacksize);
|
||||
pthread_attr_setstacksize(attr, minstacksize);
|
||||
}
|
||||
ThreadParam p;
|
||||
|
|
|
@ -125,7 +125,7 @@ static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
|
|||
ExpectRace *race = FindRace(list, addr, size);
|
||||
if (race == 0)
|
||||
return false;
|
||||
DPrintf("Hit expected/benign race: %s addr=%lx:%d %s:%d\n",
|
||||
DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
|
||||
race->desc, race->addr, (int)race->size, race->file, race->line);
|
||||
race->hitcount++;
|
||||
return true;
|
||||
|
@ -217,7 +217,7 @@ void AnnotateNoOp(char *f, int l, uptr mem) {
|
|||
static void ReportMissedExpectedRace(ExpectRace *race) {
|
||||
TsanPrintf("==================\n");
|
||||
TsanPrintf("WARNING: ThreadSanitizer: missed expected data race\n");
|
||||
TsanPrintf(" %s addr=%lx %s:%d\n",
|
||||
TsanPrintf(" %s addr=%zx %s:%d\n",
|
||||
race->desc, race->addr, race->file, race->line);
|
||||
TsanPrintf("==================\n");
|
||||
}
|
||||
|
@ -267,14 +267,14 @@ void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
|
|||
Lock lock(&dyn_ann_ctx->mtx);
|
||||
AddExpectRace(&dyn_ann_ctx->expect,
|
||||
f, l, mem, 1, desc);
|
||||
DPrintf("Add expected race: %s addr=%lx %s:%d\n", desc, mem, f, l);
|
||||
DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
|
||||
}
|
||||
|
||||
static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
|
||||
Lock lock(&dyn_ann_ctx->mtx);
|
||||
AddExpectRace(&dyn_ann_ctx->benign,
|
||||
f, l, mem, size, desc);
|
||||
DPrintf("Add benign race: %s addr=%lx %s:%d\n", desc, mem, f, l);
|
||||
DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
|
||||
}
|
||||
|
||||
// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
|
||||
|
|
|
@ -40,7 +40,7 @@ void *user_alloc(ThreadState *thr, uptr pc, uptr sz) {
|
|||
if (CTX() && CTX()->initialized) {
|
||||
MemoryResetRange(thr, pc, (uptr)p, sz);
|
||||
}
|
||||
DPrintf("#%d: alloc(%lu) = %p\n", thr->tid, sz, p);
|
||||
DPrintf("#%d: alloc(%zu) = %p\n", thr->tid, sz, p);
|
||||
SignalUnsafeCall(thr, pc);
|
||||
return p;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ MBlock *user_mblock(ThreadState *thr, void *p) {
|
|||
MBlock *b = (MBlock*)AllocBlock(p);
|
||||
// FIXME: Output a warning, it's a user error.
|
||||
if (p < (char*)(b + 1) || p > (char*)(b + 1) + b->size) {
|
||||
TsanPrintf("user_mblock p=%p b=%p size=%lu beg=%p end=%p\n",
|
||||
TsanPrintf("user_mblock p=%p b=%p size=%zu beg=%p end=%p\n",
|
||||
p, b, b->size, (char*)(b + 1), (char*)(b + 1) + b->size);
|
||||
CHECK_GE(p, (char*)(b + 1));
|
||||
CHECK_LE(p, (char*)(b + 1) + b->size);
|
||||
|
|
|
@ -120,7 +120,7 @@ DeadlockDetector::DeadlockDetector() {
|
|||
}
|
||||
|
||||
void DeadlockDetector::Lock(MutexType t) {
|
||||
// TsanPrintf("LOCK %d @%llu\n", t, seq_ + 1);
|
||||
// TsanPrintf("LOCK %d @%zu\n", t, seq_ + 1);
|
||||
u64 max_seq = 0;
|
||||
u64 max_idx = MutexTypeInvalid;
|
||||
for (int i = 0; i != MutexTypeCount; i++) {
|
||||
|
@ -135,16 +135,17 @@ void DeadlockDetector::Lock(MutexType t) {
|
|||
locked_[t] = ++seq_;
|
||||
if (max_idx == MutexTypeInvalid)
|
||||
return;
|
||||
// TsanPrintf(" last %d @%llu\n", max_idx, max_seq);
|
||||
// TsanPrintf(" last %d @%zu\n", max_idx, max_seq);
|
||||
if (!CanLockAdj[max_idx][t]) {
|
||||
TsanPrintf("ThreadSanitizer: internal deadlock detected\n");
|
||||
TsanPrintf("ThreadSanitizer: can't lock %d while under %llu\n", t, max_idx);
|
||||
TsanPrintf("ThreadSanitizer: can't lock %d while under %zu\n",
|
||||
t, (uptr)max_idx);
|
||||
Die();
|
||||
}
|
||||
}
|
||||
|
||||
void DeadlockDetector::Unlock(MutexType t) {
|
||||
// TsanPrintf("UNLO %d @%llu #%llu\n", t, seq_, locked_[t]);
|
||||
// TsanPrintf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]);
|
||||
CHECK(locked_[t]);
|
||||
locked_[t] = 0;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ static void ProtectRange(uptr beg, uptr end) {
|
|||
PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE,
|
||||
-1, 0)) {
|
||||
TsanPrintf("FATAL: ThreadSanitizer can not protect [%lx,%lx]\n", beg, end);
|
||||
TsanPrintf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
|
||||
TsanPrintf("FATAL: Make sure you are not using unlimited stack\n");
|
||||
Die();
|
||||
}
|
||||
|
@ -120,17 +120,17 @@ void InitializeShadowMemory() {
|
|||
}
|
||||
ProtectRange(kClosedLowBeg, kClosedLowEnd);
|
||||
ProtectRange(kClosedMidBeg, kClosedMidEnd);
|
||||
DPrintf("kClosedLow %lx-%lx (%luGB)\n",
|
||||
DPrintf("kClosedLow %zx-%zx (%zuGB)\n",
|
||||
kClosedLowBeg, kClosedLowEnd, (kClosedLowEnd - kClosedLowBeg) >> 30);
|
||||
DPrintf("kLinuxShadow %lx-%lx (%luGB)\n",
|
||||
DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n",
|
||||
kLinuxShadowBeg, kLinuxShadowEnd,
|
||||
(kLinuxShadowEnd - kLinuxShadowBeg) >> 30);
|
||||
DPrintf("kClosedMid %lx-%lx (%luGB)\n",
|
||||
DPrintf("kClosedMid %zx-%zx (%zuGB)\n",
|
||||
kClosedMidBeg, kClosedMidEnd, (kClosedMidEnd - kClosedMidBeg) >> 30);
|
||||
DPrintf("kLinuxAppMem %lx-%lx (%luGB)\n",
|
||||
DPrintf("kLinuxAppMem %zx-%zx (%zuGB)\n",
|
||||
kLinuxAppMemBeg, kLinuxAppMemEnd,
|
||||
(kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
|
||||
DPrintf("stack %lx\n", (uptr)&shadow);
|
||||
DPrintf("stack %zx\n", (uptr)&shadow);
|
||||
}
|
||||
|
||||
static void CheckPIE() {
|
||||
|
@ -144,8 +144,8 @@ static void CheckPIE() {
|
|||
u64 addr = strtoll(buf, 0, 16);
|
||||
if ((u64)addr < kLinuxAppMemBeg) {
|
||||
TsanPrintf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
|
||||
"something is mapped at 0x%llx < 0x%lx)\n",
|
||||
addr, kLinuxAppMemBeg);
|
||||
"something is mapped at 0x%zx < 0x%zx)\n",
|
||||
(uptr)addr, kLinuxAppMemBeg);
|
||||
TsanPrintf("FATAL: Make sure to compile with -fPIE"
|
||||
" and to link with -pie.\n");
|
||||
Die();
|
||||
|
|
|
@ -18,114 +18,12 @@
|
|||
|
||||
#include <stdarg.h> // va_list
|
||||
|
||||
typedef long long i64; // NOLINT
|
||||
typedef long iptr; // NOLINT
|
||||
namespace __sanitizer {
|
||||
int VSNPrintf(char *buff, int buff_length, const char *format, va_list args);
|
||||
} // namespace __sanitizer
|
||||
|
||||
namespace __tsan {
|
||||
|
||||
static int AppendChar(char **buff, const char *buff_end, char c) {
|
||||
if (*buff < buff_end) {
|
||||
**buff = c;
|
||||
(*buff)++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
|
||||
int base, uptr minimal_num_length) {
|
||||
uptr const kMaxLen = 30;
|
||||
uptr num_buffer[kMaxLen];
|
||||
uptr pos = 0;
|
||||
do {
|
||||
num_buffer[pos++] = num % base;
|
||||
num /= base;
|
||||
} while (num > 0);
|
||||
while (pos < minimal_num_length) num_buffer[pos++] = 0;
|
||||
int result = 0;
|
||||
while (pos-- > 0) {
|
||||
uptr digit = num_buffer[pos];
|
||||
result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
|
||||
: 'a' + digit - 10);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendSignedDecimal(char **buff, const char *buff_end, i64 num) {
|
||||
int result = 0;
|
||||
if (num < 0) {
|
||||
result += AppendChar(buff, buff_end, '-');
|
||||
num = -num;
|
||||
}
|
||||
result += AppendUnsigned(buff, buff_end, (u64)num, 10, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendString(char **buff, const char *buff_end, const char *s) {
|
||||
if (s == 0)
|
||||
s = "<null>";
|
||||
int result = 0;
|
||||
for (; *s; s++) {
|
||||
result += AppendChar(buff, buff_end, *s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
|
||||
int result = 0;
|
||||
result += AppendString(buff, buff_end, "0x");
|
||||
result += AppendUnsigned(buff, buff_end, ptr_value, 16,
|
||||
(sizeof(void*) == 8) ? 12 : 8); // NOLINT
|
||||
return result;
|
||||
}
|
||||
|
||||
uptr VSNPrintf(char *buff, int buff_length,
|
||||
const char *format, va_list args) {
|
||||
const char *buff_end = &buff[buff_length - 1];
|
||||
const char *cur = format;
|
||||
int result = 0;
|
||||
for (; *cur; cur++) {
|
||||
if (*cur != '%') {
|
||||
result += AppendChar(&buff, buff_end, *cur);
|
||||
continue;
|
||||
}
|
||||
cur++;
|
||||
bool is_long = (*cur == 'l');
|
||||
cur += is_long;
|
||||
bool is_llong = (*cur == 'l');
|
||||
cur += is_llong;
|
||||
switch (*cur) {
|
||||
case 'd': {
|
||||
i64 v = is_llong ? va_arg(args, i64)
|
||||
: is_long ? va_arg(args, iptr)
|
||||
: va_arg(args, int);
|
||||
result += AppendSignedDecimal(&buff, buff_end, v);
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
case 'x': {
|
||||
u64 v = is_llong ? va_arg(args, u64)
|
||||
: is_long ? va_arg(args, uptr)
|
||||
: va_arg(args, unsigned);
|
||||
result += AppendUnsigned(&buff, buff_end, v, *cur == 'u' ? 10: 16, 0);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
result += AppendString(&buff, buff_end, va_arg(args, char*));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Die();
|
||||
}
|
||||
}
|
||||
}
|
||||
AppendChar(&buff, buff_end + 1, '\0');
|
||||
return result;
|
||||
}
|
||||
|
||||
void TsanPrintf(const char *format, ...) {
|
||||
ScopedInRtl in_rtl;
|
||||
const uptr kMaxLen = 16 * 1024;
|
||||
|
@ -138,12 +36,4 @@ void TsanPrintf(const char *format, ...) {
|
|||
buffer, len < buffer.Size() ? len : buffer.Size() - 1);
|
||||
}
|
||||
|
||||
uptr SNPrintf(char *buffer, uptr length, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
uptr len = VSNPrintf(buffer, length, format, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
} // namespace __tsan
|
||||
|
|
|
@ -70,10 +70,10 @@ static void PrintMop(const ReportMop *mop, bool first) {
|
|||
|
||||
static void PrintLocation(const ReportLocation *loc) {
|
||||
if (loc->type == ReportLocationGlobal) {
|
||||
TsanPrintf(" Location is global '%s' of size %lu at %lx %s:%d\n",
|
||||
TsanPrintf(" Location is global '%s' of size %zu at %zx %s:%d\n",
|
||||
loc->name, loc->size, loc->addr, loc->file, loc->line);
|
||||
} else if (loc->type == ReportLocationHeap) {
|
||||
TsanPrintf(" Location is heap of size %lu at %lx allocated "
|
||||
TsanPrintf(" Location is heap of size %zu at %zx allocated "
|
||||
"by thread %d:\n", loc->size, loc->addr, loc->tid);
|
||||
PrintStack(loc->stack);
|
||||
} else if (loc->type == ReportLocationStack) {
|
||||
|
|
|
@ -104,9 +104,9 @@ static void WriteMemoryProfile(char *buf, uptr buf_size, int num) {
|
|||
uptr nsync = 0;
|
||||
uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync);
|
||||
|
||||
SNPrintf(buf, buf_size, "%d: shadow=%luMB"
|
||||
" thread=%luMB(total=%d/live=%d)"
|
||||
" sync=%luMB(cnt=%lu)\n",
|
||||
SNPrintf(buf, buf_size, "%d: shadow=%zuMB"
|
||||
" thread=%zuMB(total=%d/live=%d)"
|
||||
" sync=%zuMB(cnt=%zu)\n",
|
||||
num,
|
||||
shadow >> 20,
|
||||
threadmem >> 20, nthread, nlivethread,
|
||||
|
@ -359,17 +359,18 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
|
|||
int kAccessSizeLog, bool kAccessIsWrite) {
|
||||
u64 *shadow_mem = (u64*)MemToShadow(addr);
|
||||
DPrintf2("#%d: tsan::OnMemoryAccess: @%p %p size=%d"
|
||||
" is_write=%d shadow_mem=%p {%llx, %llx, %llx, %llx}\n",
|
||||
" is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
|
||||
(int)thr->fast_state.tid(), (void*)pc, (void*)addr,
|
||||
(int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
|
||||
shadow_mem[0], shadow_mem[1], shadow_mem[2], shadow_mem[3]);
|
||||
(uptr)shadow_mem[0], (uptr)shadow_mem[1],
|
||||
(uptr)shadow_mem[2], (uptr)shadow_mem[3]);
|
||||
#if TSAN_DEBUG
|
||||
if (!IsAppMem(addr)) {
|
||||
TsanPrintf("Access to non app mem %lx\n", addr);
|
||||
TsanPrintf("Access to non app mem %zx\n", addr);
|
||||
DCHECK(IsAppMem(addr));
|
||||
}
|
||||
if (!IsShadowMem((uptr)shadow_mem)) {
|
||||
TsanPrintf("Bad shadow addr %p (%lx)\n", shadow_mem, addr);
|
||||
TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
|
||||
DCHECK(IsShadowMem((uptr)shadow_mem));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
namespace __tsan {
|
||||
|
||||
void TsanPrintf(const char *format, ...) FORMAT(1, 2);
|
||||
uptr SNPrintf(char *buffer, uptr length, const char *format, ...) FORMAT(3, 4);
|
||||
|
||||
// FastState (from most significant bit):
|
||||
// unused : 1
|
||||
|
|
|
@ -22,7 +22,7 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
|
|||
bool rw, bool recursive) {
|
||||
Context *ctx = CTX();
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexCreate %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexCreate %zx\n", thr->tid, addr);
|
||||
StatInc(thr, StatMutexCreate);
|
||||
MemoryWrite1Byte(thr, pc, addr);
|
||||
SyncVar *s = ctx->synctab.GetAndLock(thr, pc, addr, true);
|
||||
|
@ -34,7 +34,7 @@ void MutexCreate(ThreadState *thr, uptr pc, uptr addr,
|
|||
void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
|
||||
Context *ctx = CTX();
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexDestroy %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexDestroy %zx\n", thr->tid, addr);
|
||||
StatInc(thr, StatMutexDestroy);
|
||||
MemoryWrite1Byte(thr, pc, addr);
|
||||
SyncVar *s = ctx->synctab.GetAndRemove(thr, pc, addr);
|
||||
|
@ -52,7 +52,7 @@ void MutexDestroy(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexLock %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexLock %zx\n", thr->tid, addr);
|
||||
MemoryRead1Byte(thr, pc, addr);
|
||||
thr->fast_state.IncrementEpoch();
|
||||
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeLock, addr);
|
||||
|
@ -81,7 +81,7 @@ void MutexLock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void MutexUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexUnlock %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexUnlock %zx\n", thr->tid, addr);
|
||||
MemoryRead1Byte(thr, pc, addr);
|
||||
thr->fast_state.IncrementEpoch();
|
||||
TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeUnlock, addr);
|
||||
|
@ -114,7 +114,7 @@ void MutexUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexReadLock %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexReadLock %zx\n", thr->tid, addr);
|
||||
StatInc(thr, StatMutexReadLock);
|
||||
MemoryRead1Byte(thr, pc, addr);
|
||||
thr->fast_state.IncrementEpoch();
|
||||
|
@ -130,7 +130,7 @@ void MutexReadLock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexReadUnlock %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexReadUnlock %zx\n", thr->tid, addr);
|
||||
StatInc(thr, StatMutexReadUnlock);
|
||||
MemoryRead1Byte(thr, pc, addr);
|
||||
thr->fast_state.IncrementEpoch();
|
||||
|
@ -148,7 +148,7 @@ void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: MutexReadOrWriteUnlock %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: MutexReadOrWriteUnlock %zx\n", thr->tid, addr);
|
||||
MemoryRead1Byte(thr, pc, addr);
|
||||
SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
|
||||
if (s->owner_tid == SyncVar::kInvalidTid) {
|
||||
|
@ -189,7 +189,7 @@ void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void Acquire(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: Acquire %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
|
||||
SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, false);
|
||||
thr->clock.set(thr->tid, thr->fast_state.epoch());
|
||||
thr->clock.acquire(&s->clock);
|
||||
|
@ -199,7 +199,7 @@ void Acquire(ThreadState *thr, uptr pc, uptr addr) {
|
|||
|
||||
void Release(ThreadState *thr, uptr pc, uptr addr) {
|
||||
CHECK_GT(thr->in_rtl, 0);
|
||||
DPrintf("#%d: Release %lx\n", thr->tid, addr);
|
||||
DPrintf("#%d: Release %zx\n", thr->tid, addr);
|
||||
SyncVar *s = CTX()->synctab.GetAndLock(thr, pc, addr, true);
|
||||
thr->clock.set(thr->tid, thr->fast_state.epoch());
|
||||
thr->clock.release(&s->clock);
|
||||
|
|
|
@ -68,7 +68,7 @@ static void StackStripMain(ReportStack *stack) {
|
|||
// can actually happen if we do not instrument some code,
|
||||
// so it's only a DCHECK. However we must try hard to not miss it
|
||||
// due to our fault.
|
||||
TsanPrintf("Bottom stack frame of stack %lx is missed\n", stack->pc);
|
||||
TsanPrintf("Bottom stack frame of stack %zx is missed\n", stack->pc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,19 +189,19 @@ static void RestoreStack(int tid, const u64 epoch, StackTrace *stk) {
|
|||
return;
|
||||
const u64 eend = epoch % kTraceSize;
|
||||
const u64 ebegin = eend / kTracePartSize * kTracePartSize;
|
||||
DPrintf("#%d: RestoreStack epoch=%llu ebegin=%llu eend=%llu partidx=%d\n",
|
||||
tid, epoch, ebegin, eend, partidx);
|
||||
DPrintf("#%d: RestoreStack epoch=%zu ebegin=%zu eend=%zu partidx=%d\n",
|
||||
tid, (uptr)epoch, (uptr)ebegin, (uptr)eend, partidx);
|
||||
InternalScopedBuf<uptr> stack(1024); // FIXME: de-hardcode 1024
|
||||
for (uptr i = 0; i < hdr->stack0.Size(); i++) {
|
||||
stack[i] = hdr->stack0.Get(i);
|
||||
DPrintf2(" #%02lu: pc=%lx\n", i, stack[i]);
|
||||
DPrintf2(" #%02lu: pc=%zx\n", i, stack[i]);
|
||||
}
|
||||
uptr pos = hdr->stack0.Size();
|
||||
for (uptr i = ebegin; i <= eend; i++) {
|
||||
Event ev = trace->events[i];
|
||||
EventType typ = (EventType)(ev >> 61);
|
||||
uptr pc = (uptr)(ev & 0xffffffffffffull);
|
||||
DPrintf2(" %lu typ=%d pc=%lx\n", i, typ, pc);
|
||||
DPrintf2(" %zu typ=%d pc=%zx\n", i, typ, pc);
|
||||
if (typ == EventTypeMop) {
|
||||
stack[pos] = pc;
|
||||
} else if (typ == EventTypeFuncEnter) {
|
||||
|
@ -213,7 +213,7 @@ static void RestoreStack(int tid, const u64 epoch, StackTrace *stk) {
|
|||
pos--;
|
||||
}
|
||||
for (uptr j = 0; j <= pos; j++)
|
||||
DPrintf2(" #%lu: %lx\n", j, stack[j]);
|
||||
DPrintf2(" #%zu: %zx\n", j, stack[j]);
|
||||
}
|
||||
if (pos == 0 && stack[0] == 0)
|
||||
return;
|
||||
|
@ -349,8 +349,8 @@ void ReportRace(ThreadState *thr) {
|
|||
|
||||
void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) {
|
||||
ScopedInRtl in_rtl;
|
||||
TsanPrintf("FATAL: ThreadSanitizer CHECK failed: %s:%d \"%s\" (%llx, %llx)\n",
|
||||
file, line, cond, v1, v2);
|
||||
TsanPrintf("FATAL: ThreadSanitizer CHECK failed: %s:%d \"%s\" (%zx, %zx)\n",
|
||||
file, line, cond, (uptr)v1, (uptr)v2);
|
||||
Die();
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ static void ThreadDead(ThreadState *thr, ThreadContext *tctx) {
|
|||
CHECK_GT(thr->in_rtl, 0);
|
||||
CHECK(tctx->status == ThreadStatusRunning
|
||||
|| tctx->status == ThreadStatusFinished);
|
||||
DPrintf("#%d: ThreadDead uid=%lu\n", thr->tid, tctx->user_id);
|
||||
DPrintf("#%d: ThreadDead uid=%zu\n", thr->tid, tctx->user_id);
|
||||
tctx->status = ThreadStatusDead;
|
||||
tctx->user_id = 0;
|
||||
tctx->sync.Reset();
|
||||
|
@ -106,7 +106,7 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {
|
|||
CHECK_NE(tctx, 0);
|
||||
CHECK_GE(tid, 0);
|
||||
CHECK_LT(tid, kMaxTid);
|
||||
DPrintf("#%d: ThreadCreate tid=%d uid=%lu\n", thr->tid, tid, uid);
|
||||
DPrintf("#%d: ThreadCreate tid=%d uid=%zu\n", thr->tid, tid, uid);
|
||||
CHECK_EQ(tctx->status, ThreadStatusInvalid);
|
||||
ctx->alive_threads++;
|
||||
if (ctx->max_alive_threads < ctx->alive_threads) {
|
||||
|
@ -170,9 +170,9 @@ void ThreadStart(ThreadState *thr, int tid) {
|
|||
thr->clock.set(tid, tctx->epoch0);
|
||||
thr->clock.acquire(&tctx->sync);
|
||||
StatInc(thr, StatSyncAcquire);
|
||||
DPrintf("#%d: ThreadStart epoch=%llu stk_addr=%lx stk_size=%lx "
|
||||
"tls_addr=%lx tls_size=%lx\n",
|
||||
tid, tctx->epoch0, stk_addr, stk_size, tls_addr, tls_size);
|
||||
DPrintf("#%d: ThreadStart epoch=%zu stk_addr=%zx stk_size=%zx "
|
||||
"tls_addr=%zx tls_size=%zx\n",
|
||||
tid, (uptr)tctx->epoch0, stk_addr, stk_size, tls_addr, tls_size);
|
||||
}
|
||||
|
||||
void ThreadFinish(ThreadState *thr) {
|
||||
|
@ -239,7 +239,7 @@ int ThreadTid(ThreadState *thr, uptr pc, uptr uid) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
DPrintf("#%d: ThreadTid uid=%lu tid=%d\n", thr->tid, uid, res);
|
||||
DPrintf("#%d: ThreadTid uid=%zu tid=%d\n", thr->tid, uid, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -292,20 +292,20 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
|
|||
|
||||
#if TSAN_DEBUG
|
||||
if (!IsAppMem(addr)) {
|
||||
TsanPrintf("Access to non app mem %lx\n", addr);
|
||||
TsanPrintf("Access to non app mem %zx\n", addr);
|
||||
DCHECK(IsAppMem(addr));
|
||||
}
|
||||
if (!IsAppMem(addr + size - 1)) {
|
||||
TsanPrintf("Access to non app mem %lx\n", addr + size - 1);
|
||||
TsanPrintf("Access to non app mem %zx\n", addr + size - 1);
|
||||
DCHECK(IsAppMem(addr + size - 1));
|
||||
}
|
||||
if (!IsShadowMem((uptr)shadow_mem)) {
|
||||
TsanPrintf("Bad shadow addr %p (%lx)\n", shadow_mem, addr);
|
||||
TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
|
||||
DCHECK(IsShadowMem((uptr)shadow_mem));
|
||||
}
|
||||
if (!IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1))) {
|
||||
TsanPrintf("Bad shadow addr %p (%lx)\n",
|
||||
shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
|
||||
TsanPrintf("Bad shadow addr %p (%zx)\n",
|
||||
shadow_mem + size * kShadowCnt / 8 - 1, addr + size - 1);
|
||||
DCHECK(IsShadowMem((uptr)(shadow_mem + size * kShadowCnt / 8 - 1)));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -243,7 +243,7 @@ void StatOutput(u64 *stat) {
|
|||
|
||||
TsanPrintf("Statistics:\n");
|
||||
for (int i = 0; i < StatCnt; i++)
|
||||
TsanPrintf("%s: %llu\n", name[i], stat[i]);
|
||||
TsanPrintf("%s: %zu\n", name[i], (uptr)stat[i]);
|
||||
}
|
||||
|
||||
} // namespace __tsan
|
||||
|
|
|
@ -102,13 +102,14 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
|
|||
m->base = (uptr)info->dlpi_addr;
|
||||
m->inp_fd = -1;
|
||||
m->out_fd = -1;
|
||||
DPrintf("Module %s %lx\n", m->name, m->base);
|
||||
DPrintf("Module %s %zx\n", m->name, m->base);
|
||||
for (int i = 0; i < info->dlpi_phnum; i++) {
|
||||
const Elf64_Phdr *s = &info->dlpi_phdr[i];
|
||||
DPrintf(" Section p_type=%llx p_offset=%llx p_vaddr=%llx p_paddr=%llx"
|
||||
" p_filesz=%llx p_memsz=%llx p_flags=%llx p_align=%llx\n",
|
||||
(u64)s->p_type, (u64)s->p_offset, (u64)s->p_vaddr, (u64)s->p_paddr,
|
||||
(u64)s->p_filesz, (u64)s->p_memsz, (u64)s->p_flags, (u64)s->p_align);
|
||||
DPrintf(" Section p_type=%zx p_offset=%zx p_vaddr=%zx p_paddr=%zx"
|
||||
" p_filesz=%zx p_memsz=%zx p_flags=%zx p_align=%zx\n",
|
||||
(uptr)s->p_type, (uptr)s->p_offset, (uptr)s->p_vaddr,
|
||||
(uptr)s->p_paddr, (uptr)s->p_filesz, (uptr)s->p_memsz,
|
||||
(uptr)s->p_flags, (uptr)s->p_align);
|
||||
if (s->p_type != PT_LOAD)
|
||||
continue;
|
||||
SectionDesc *sec = (SectionDesc*)internal_alloc(MBlockReportStack,
|
||||
|
@ -118,7 +119,7 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) {
|
|||
sec->end = sec->base + s->p_memsz;
|
||||
sec->next = ctx->sections;
|
||||
ctx->sections = sec;
|
||||
DPrintf(" Section %lx-%lx\n", sec->base, sec->end);
|
||||
DPrintf(" Section %zx-%zx\n", sec->base, sec->end);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -199,7 +200,7 @@ ReportStack *SymbolizeData(uptr addr) {
|
|||
int res = 0;
|
||||
InternalScopedBuf<char> cmd(1024);
|
||||
SNPrintf(cmd, cmd.Size(),
|
||||
"nm -alC %s|grep \"%lx\"|awk '{printf(\"%%s\\n%%s\", $3, $4)}' > tsan.tmp2",
|
||||
"nm -alC %s|grep \"%zx\"|awk '{printf(\"%%s\\n%%s\", $3, $4)}' > tsan.tmp2",
|
||||
exe, (addr - base));
|
||||
if (system(cmd))
|
||||
return 0;
|
||||
|
|
|
@ -23,8 +23,8 @@ static void TestThreadInfo(bool main) {
|
|||
uptr tls_addr = 0;
|
||||
uptr tls_size = 0;
|
||||
GetThreadStackAndTls(main, &stk_addr, &stk_size, &tls_addr, &tls_size);
|
||||
// Printf("stk=%lx-%lx(%lu)\n", stk_addr, stk_addr + stk_size, stk_size);
|
||||
// Printf("tls=%lx-%lx(%lu)\n", tls_addr, tls_addr + tls_size, tls_size);
|
||||
// Printf("stk=%zx-%zx(%zu)\n", stk_addr, stk_addr + stk_size, stk_size);
|
||||
// Printf("tls=%zx-%zx(%zu)\n", tls_addr, tls_addr + tls_size, tls_size);
|
||||
|
||||
int stack_var;
|
||||
EXPECT_NE(stk_addr, (uptr)0);
|
||||
|
|
|
@ -21,13 +21,13 @@ namespace __tsan {
|
|||
TEST(Printf, Basic) {
|
||||
char buf[1024];
|
||||
uptr len = SNPrintf(buf, sizeof(buf),
|
||||
"a%db%ldc%lldd%ue%luf%llug%xh%lxq%llxw%pe%sr",
|
||||
(int)-1, (long)-2, (long long)-3, // NOLINT
|
||||
(unsigned)-4, (unsigned long)5, (unsigned long long)6, // NOLINT
|
||||
(unsigned)10, (unsigned long)11, (unsigned long long)12, // NOLINT
|
||||
"a%db%zdc%ue%zuf%xh%zxq%pe%sr",
|
||||
(int)-1, (long)-2, // NOLINT
|
||||
(unsigned)-4, (unsigned long)5, // NOLINT
|
||||
(unsigned)10, (unsigned long)11, // NOLINT
|
||||
(void*)0x123, "_string_");
|
||||
EXPECT_EQ(len, strlen(buf));
|
||||
EXPECT_EQ(0, strcmp(buf, "a-1b-2c-3d4294967292e5f6gahbqcw"
|
||||
EXPECT_EQ(0, strcmp(buf, "a-1b-2c4294967292e5fahbq"
|
||||
"0x000000000123e_string_r"));
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ TEST(Printf, OverflowInt) {
|
|||
|
||||
TEST(Printf, OverflowUint) {
|
||||
char buf[] = "123456789";
|
||||
SNPrintf(buf, 4, "a%llx", (long long)0x123456789); // NOLINT
|
||||
SNPrintf(buf, 4, "a%zx", (unsigned long)0x123456789); // NOLINT
|
||||
EXPECT_EQ(0, strcmp(buf, "a12"));
|
||||
EXPECT_EQ(buf[3], 0);
|
||||
EXPECT_EQ(buf[4], '5');
|
||||
|
@ -96,14 +96,11 @@ static void TestMinMax(const char *fmt, T min, T max) {
|
|||
|
||||
TEST(Printf, MinMax) {
|
||||
TestMinMax<int>("%d-%d", INT_MIN, INT_MAX); // NOLINT
|
||||
TestMinMax<long>("%ld-%ld", LONG_MIN, LONG_MAX); // NOLINT
|
||||
TestMinMax<long long>("%lld-%lld", LLONG_MIN, LLONG_MAX); // NOLINT
|
||||
TestMinMax<long>("%zd-%zd", LONG_MIN, LONG_MAX); // NOLINT
|
||||
TestMinMax<unsigned>("%u-%u", 0, UINT_MAX); // NOLINT
|
||||
TestMinMax<unsigned long>("%lu-%lu", 0, ULONG_MAX); // NOLINT
|
||||
TestMinMax<unsigned long long>("%llu-%llu", 0, ULLONG_MAX); // NOLINT
|
||||
TestMinMax<unsigned long>("%zu-%zu", 0, ULONG_MAX); // NOLINT
|
||||
TestMinMax<unsigned>("%x-%x", 0, UINT_MAX); // NOLINT
|
||||
TestMinMax<unsigned long>("%lx-%lx", 0, ULONG_MAX); // NOLINT
|
||||
TestMinMax<unsigned long long>("%llx-%llx", 0, ULLONG_MAX); // NOLINT
|
||||
TestMinMax<unsigned long>("%zx-%zx", 0, ULONG_MAX); // NOLINT
|
||||
}
|
||||
|
||||
} // namespace __tsan
|
||||
|
|
Loading…
Reference in New Issue