[asan] get rid of AsanPrintf in favor of Printf from sanitizer_common

llvm-svn: 162746
This commit is contained in:
Kostya Serebryany 2012-08-28 11:34:40 +00:00
parent 4bfe954d14
commit bb6f165952
12 changed files with 80 additions and 131 deletions

View File

@ -12,7 +12,6 @@ set(ASAN_SOURCES
asan_new_delete.cc
asan_poisoning.cc
asan_posix.cc
asan_printf.cc
asan_report.cc
asan_rtl.cc
asan_stack.cc

View File

@ -229,17 +229,17 @@ struct AsanChunk: public ChunkBase {
void DescribeAddress(uptr addr, uptr access_size) {
uptr offset;
AsanPrintf("%p is located ", (void*)addr);
Printf("%p is located ", (void*)addr);
if (AddrIsInside(addr, access_size, &offset)) {
AsanPrintf("%zu bytes inside of", offset);
Printf("%zu bytes inside of", offset);
} else if (AddrIsAtLeft(addr, access_size, &offset)) {
AsanPrintf("%zu bytes to the left of", offset);
Printf("%zu bytes to the left of", offset);
} else if (AddrIsAtRight(addr, access_size, &offset)) {
AsanPrintf("%zu bytes to the right of", offset);
Printf("%zu bytes to the right of", offset);
} else {
AsanPrintf(" somewhere around (this is AddressSanitizer bug!)");
Printf(" somewhere around (this is AddressSanitizer bug!)");
}
AsanPrintf(" %zu-byte region [%p,%p)\n",
Printf(" %zu-byte region [%p,%p)\n",
used_size, (void*)Beg(), (void*)(Beg() + used_size));
}
};
@ -601,12 +601,12 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
if (m->free_tid != kInvalidTid) {
AsanThreadSummary *free_thread =
asanThreadRegistry().FindByTid(m->free_tid);
AsanPrintf("freed by thread T%d here:\n", free_thread->tid());
Printf("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();
AsanPrintf("previously allocated by thread T%d here:\n",
Printf("previously allocated by thread T%d here:\n",
alloc_thread->tid());
alloc_stack.PrintStack();
@ -614,7 +614,7 @@ void DescribeHeapAddress(uptr addr, uptr access_size) {
free_thread->Announce();
alloc_thread->Announce();
} else {
AsanPrintf("allocated by thread T%d here:\n", alloc_thread->tid());
Printf("allocated by thread T%d here:\n", alloc_thread->tid());
alloc_stack.PrintStack();
t->summary()->Announce();
alloc_thread->Announce();

View File

@ -120,9 +120,6 @@ void *AsanTSDGet();
void AsanTSDSet(void *tsd);
void AppendToErrorMessageBuffer(const char *buffer);
// asan_printf.cc
void AsanPrintf(const char *format, ...);
void AsanReport(const char *format, ...);
// asan_poisoning.cc
// Poisons the shadow memory for "size" bytes starting from "addr".

View File

@ -231,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!
AsanPrintf("mz_destroy() called -- ignoring\n");
Printf("mz_destroy() called -- ignoring\n");
}
// from AvailabilityMacros.h
#if defined(MAC_OS_X_VERSION_10_6) && \

View File

@ -1,59 +0,0 @@
//===-- asan_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 a part of AddressSanitizer, an address sanity checker.
//
// Internal printf function, used inside ASan run-time library.
// We can't use libc printf because we intercept some of the functions used
// inside it.
//===----------------------------------------------------------------------===//
#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 {
void AsanPrintf(const char *format, ...) {
const int kLen = 1024 * 4;
char buffer[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);
AppendToErrorMessageBuffer(buffer);
}
// 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 = internal_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);
AppendToErrorMessageBuffer(buffer);
}
} // namespace __asan

View File

@ -47,22 +47,22 @@ static void (*on_error_callback)(void);
static void PrintBytes(const char *before, uptr *a) {
u8 *bytes = (u8*)a;
uptr byte_num = (__WORDSIZE) / 8;
AsanPrintf("%s%p:", before, (void*)a);
Printf("%s%p:", before, (void*)a);
for (uptr i = 0; i < byte_num; i++) {
AsanPrintf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15);
}
AsanPrintf("\n");
Printf("\n");
}
static void PrintShadowMemoryForAddress(uptr addr) {
if (!AddrIsInMem(addr))
return;
uptr shadow_addr = MemToShadow(addr);
AsanPrintf("Shadow byte and word:\n");
AsanPrintf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
Printf("Shadow byte and word:\n");
Printf(" %p: %x\n", (void*)shadow_addr, *(unsigned char*)shadow_addr);
uptr aligned_shadow = shadow_addr & ~(kWordSize - 1);
PrintBytes(" ", (uptr*)(aligned_shadow));
AsanPrintf("More shadow bytes:\n");
Printf("More shadow bytes:\n");
for (int i = -4; i <= 4; i++) {
const char *prefix = (i == 0) ? "=>" : " ";
PrintBytes(prefix, (uptr*)(aligned_shadow + i * kWordSize));
@ -73,14 +73,14 @@ static void PrintZoneForPointer(uptr ptr, uptr zone_ptr,
const char *zone_name) {
if (zone_ptr) {
if (zone_name) {
AsanPrintf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
Printf("malloc_zone_from_ptr(%p) = %p, which is %s\n",
ptr, zone_ptr, zone_name);
} else {
AsanPrintf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
Printf("malloc_zone_from_ptr(%p) = %p, which doesn't have a name\n",
ptr, zone_ptr);
}
} else {
AsanPrintf("malloc_zone_from_ptr(%p) = 0\n", ptr);
Printf("malloc_zone_from_ptr(%p) = 0\n", ptr);
}
}
@ -96,21 +96,21 @@ static void PrintGlobalNameIfASCII(const __asan_global &g) {
if (!IsASCII(*(unsigned char*)p)) return;
}
if (*(char*)(g.beg + g.size - 1) != 0) return;
AsanPrintf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
Printf(" '%s' is ascii string '%s'\n", g.name, (char*)g.beg);
}
bool DescribeAddressRelativeToGlobal(uptr addr, const __asan_global &g) {
if (addr < g.beg - kGlobalAndStackRedzone) return false;
if (addr >= g.beg + g.size_with_redzone) return false;
AsanPrintf("%p is located ", (void*)addr);
Printf("%p is located ", (void*)addr);
if (addr < g.beg) {
AsanPrintf("%zd bytes to the left", g.beg - addr);
Printf("%zd bytes to the left", g.beg - addr);
} else if (addr >= g.beg + g.size) {
AsanPrintf("%zd bytes to the right", addr - (g.beg + g.size));
Printf("%zd bytes to the right", addr - (g.beg + g.size));
} else {
AsanPrintf("%zd bytes inside", addr - g.beg); // Can it happen?
Printf("%zd bytes inside", addr - g.beg); // Can it happen?
}
AsanPrintf(" of global variable '%s' (0x%zx) of size %zu\n",
Printf(" of global variable '%s' (0x%zx) of size %zu\n",
g.name, g.beg, g.size);
PrintGlobalNameIfASCII(g);
return true;
@ -122,15 +122,15 @@ bool DescribeAddressIfShadow(uptr addr) {
static const char kAddrInShadowReport[] =
"Address %p is located in the %s.\n";
if (AddrIsInShadowGap(addr)) {
AsanPrintf(kAddrInShadowReport, addr, "shadow gap area");
Printf(kAddrInShadowReport, addr, "shadow gap area");
return true;
}
if (AddrIsInHighShadow(addr)) {
AsanPrintf(kAddrInShadowReport, addr, "high shadow area");
Printf(kAddrInShadowReport, addr, "high shadow area");
return true;
}
if (AddrIsInLowShadow(addr)) {
AsanPrintf(kAddrInShadowReport, addr, "low shadow area");
Printf(kAddrInShadowReport, addr, "low shadow area");
return true;
}
CHECK(0 && "Address is not in memory and not in shadow?");
@ -155,14 +155,14 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
internal_strncat(buf, frame_descr,
Min(kBufSize,
static_cast<sptr>(name_end - frame_descr)));
AsanPrintf("Address %p is located at offset %zu "
Printf("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);
AsanPrintf(" This frame has %zu object(s):\n", n_objects);
Printf(" 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;
@ -171,7 +171,7 @@ bool DescribeAddressIfStack(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 != ' ') {
AsanPrintf("AddressSanitizer can't parse the stack frame "
Printf("AddressSanitizer can't parse the stack frame "
"descriptor: |%s|\n", frame_descr);
break;
}
@ -179,9 +179,9 @@ bool DescribeAddressIfStack(uptr addr, uptr access_size) {
buf[0] = 0;
internal_strncat(buf, p, Min(kBufSize, len));
p += len;
AsanPrintf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf);
}
AsanPrintf("HINT: this may be a false positive if your program uses "
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");
t->summary()->Announce();
@ -213,7 +213,7 @@ class ScopedInErrorReport {
// Do not print more than one report, otherwise they will mix up.
// Error reporting functions shouldn't return at this situation, as
// they are defined as no-return.
AsanReport("AddressSanitizer: while reporting a bug found another one."
Report("AddressSanitizer: while reporting a bug found another one."
"Ignoring.\n");
// We can't use infinite busy loop here, as ASan may try to report an
// error while another error report is being printed (e.g. if the code
@ -224,7 +224,7 @@ class ScopedInErrorReport {
if (on_error_callback) {
on_error_callback();
}
AsanPrintf("===================================================="
Printf("===================================================="
"=============\n");
AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
if (curr_thread) {
@ -245,32 +245,32 @@ class ScopedInErrorReport {
if (error_report_callback) {
error_report_callback(error_message_buffer);
}
AsanReport("ABORTING\n");
Report("ABORTING\n");
Die();
}
};
void ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr) {
ScopedInErrorReport in_report;
AsanReport("ERROR: AddressSanitizer crashed on unknown address %p"
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().GetCurrentTidOrInvalid());
AsanPrintf("AddressSanitizer can not provide additional info.\n");
Printf("AddressSanitizer can not provide additional info.\n");
GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp);
stack.PrintStack();
}
void ReportDoubleFree(uptr addr, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanReport("ERROR: AddressSanitizer attempting double-free on %p:\n", addr);
Report("ERROR: AddressSanitizer attempting double-free on %p:\n", addr);
stack->PrintStack();
DescribeHeapAddress(addr, 1);
}
void ReportFreeNotMalloced(uptr addr, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanReport("ERROR: AddressSanitizer attempting free on address "
Report("ERROR: AddressSanitizer attempting free on address "
"which was not malloc()-ed: %p\n", addr);
stack->PrintStack();
DescribeHeapAddress(addr, 1);
@ -278,7 +278,7 @@ void ReportFreeNotMalloced(uptr addr, AsanStackTrace *stack) {
void ReportMallocUsableSizeNotOwned(uptr addr, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanReport("ERROR: AddressSanitizer attempting to call "
Report("ERROR: AddressSanitizer attempting to call "
"malloc_usable_size() for pointer which is "
"not owned: %p\n", addr);
stack->PrintStack();
@ -287,7 +287,7 @@ void ReportMallocUsableSizeNotOwned(uptr addr, AsanStackTrace *stack) {
void ReportAsanGetAllocatedSizeNotOwned(uptr addr, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanReport("ERROR: AddressSanitizer attempting to call "
Report("ERROR: AddressSanitizer attempting to call "
"__asan_get_allocated_size() for pointer which is "
"not owned: %p\n", addr);
stack->PrintStack();
@ -298,7 +298,7 @@ void ReportStringFunctionMemoryRangesOverlap(
const char *function, const char *offset1, uptr length1,
const char *offset2, uptr length2, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanReport("ERROR: AddressSanitizer %s-param-overlap: "
Report("ERROR: AddressSanitizer %s-param-overlap: "
"memory ranges [%p,%p) and [%p, %p) overlap\n", \
function, offset1, offset1 + length1, offset2, offset2 + length2);
stack->PrintStack();
@ -311,7 +311,7 @@ void ReportStringFunctionMemoryRangesOverlap(
void WarnMacFreeUnallocated(
uptr addr, uptr zone_ptr, const char *zone_name, AsanStackTrace *stack) {
// Just print a warning here.
AsanPrintf("free_common(%p) -- attempting to free unallocated memory.\n"
Printf("free_common(%p) -- attempting to free unallocated memory.\n"
"AddressSanitizer is ignoring this error on Mac OS now.\n",
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
@ -322,7 +322,7 @@ void WarnMacFreeUnallocated(
void ReportMacMzReallocUnknown(
uptr addr, uptr zone_ptr, const char *zone_name, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanPrintf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
Printf("mz_realloc(%p) -- attempting to realloc unallocated memory.\n"
"This is an unrecoverable problem, exiting now.\n",
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
@ -333,7 +333,7 @@ void ReportMacMzReallocUnknown(
void ReportMacCfReallocUnknown(
uptr addr, uptr zone_ptr, const char *zone_name, AsanStackTrace *stack) {
ScopedInErrorReport in_report;
AsanPrintf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
Printf("cf_realloc(%p) -- attempting to realloc unallocated memory.\n"
"This is an unrecoverable problem, exiting now.\n",
addr);
PrintZoneForPointer(addr, zone_ptr, zone_name);
@ -391,12 +391,12 @@ void __asan_report_error(uptr pc, uptr bp, uptr sp,
}
}
AsanReport("ERROR: AddressSanitizer %s on address "
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);
u32 curr_tid = asanThreadRegistry().GetCurrentTidOrInvalid();
AsanPrintf("%s of size %zu at %p thread T%d\n",
Printf("%s of size %zu at %p thread T%d\n",
access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
access_size, (void*)addr, curr_tid);

View File

@ -51,7 +51,7 @@ void Die() {
SANITIZER_INTERFACE_ATTRIBUTE
void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) {
AsanReport("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n",
file, line, cond, (uptr)v1, (uptr)v2);
PRINT_CURRENT_STACK();
ShowStatsAndAbort();
@ -248,7 +248,7 @@ static NOINLINE void force_interface_symbols() {
}
static void asan_atexit() {
AsanPrintf("AddressSanitizer exit stats:\n");
Printf("AddressSanitizer exit stats:\n");
__asan_print_accumulated_stats();
}
@ -284,6 +284,8 @@ void __asan_init() {
// Make sure we are not statically linked.
AsanDoesNotSupportStaticLinkage();
SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
// Initialize flags. This must be done early, because most of the
// initialization steps look at flags().
const char *options = GetEnv("ASAN_OPTIONS");

View File

@ -54,7 +54,7 @@ void AsanStackTrace::PrintStack(uptr *addr, uptr size) {
// We can't know anything about the string returned by external
// symbolizer, but if it starts with filename, try to strip path prefix
// from it.
AsanPrintf(" #%zu 0x%zx %s\n", frame_num, pc, StripPathPrefix(buff));
Printf(" #%zu 0x%zx %s\n", frame_num, pc, StripPathPrefix(buff));
frame_num++;
continue;
}
@ -67,18 +67,18 @@ void AsanStackTrace::PrintStack(uptr *addr, uptr size) {
if (addr_frames_num > 0) {
for (uptr j = 0; j < addr_frames_num; j++) {
AddressInfo &info = addr_frames[j];
AsanPrintf(" #%zu 0x%zx", frame_num, pc);
Printf(" #%zu 0x%zx", frame_num, pc);
if (info.function) {
AsanPrintf(" in %s", info.function);
Printf(" in %s", info.function);
}
if (info.file) {
AsanPrintf(" %s:%d:%d", StripPathPrefix(info.file), info.line,
Printf(" %s:%d:%d", StripPathPrefix(info.file), info.line,
info.column);
} else if (info.module) {
AsanPrintf(" (%s+0x%zx)", StripPathPrefix(info.module),
Printf(" (%s+0x%zx)", StripPathPrefix(info.module),
info.module_offset);
}
AsanPrintf("\n");
Printf("\n");
info.Clear();
frame_num++;
}
@ -87,10 +87,10 @@ void AsanStackTrace::PrintStack(uptr *addr, uptr size) {
char filename[4096];
if (proc_maps.GetObjectNameAndOffset(pc, &offset,
filename, sizeof(filename))) {
AsanPrintf(" #%zu 0x%zx (%s+0x%zx)\n",
Printf(" #%zu 0x%zx (%s+0x%zx)\n",
frame_num, pc, StripPathPrefix(filename), offset);
} else {
AsanPrintf(" #%zu 0x%zx\n", frame_num, pc);
Printf(" #%zu 0x%zx\n", frame_num, pc);
}
frame_num++;
}

View File

@ -27,29 +27,29 @@ AsanStats::AsanStats() {
static void PrintMallocStatsArray(const char *prefix,
uptr (&array)[kNumberOfSizeClasses]) {
AsanPrintf("%s", prefix);
Printf("%s", prefix);
for (uptr i = 0; i < kNumberOfSizeClasses; i++) {
if (!array[i]) continue;
AsanPrintf("%zu:%zu; ", i, array[i]);
Printf("%zu:%zu; ", i, array[i]);
}
AsanPrintf("\n");
Printf("\n");
}
void AsanStats::Print() {
AsanPrintf("Stats: %zuM malloced (%zuM for red zones) by %zu calls\n",
Printf("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",
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);
AsanPrintf("Stats: %zuM (%zu full pages) mmaped in %zu calls\n",
Printf("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);
AsanPrintf("Stats: malloc large: %zu small slow: %zu\n",
Printf("Stats: malloc large: %zu small slow: %zu\n",
malloc_large, malloc_small_slow);
}

View File

@ -44,7 +44,7 @@ class AsanThreadSummary {
if (tid_ == 0) return; // no need to announce the main thread.
if (!announced_) {
announced_ = true;
AsanPrintf("Thread T%d created by T%d here:\n", tid_, parent_tid_);
Printf("Thread T%d created by T%d here:\n", tid_, parent_tid_);
stack_.PrintStack();
}
}

View File

@ -98,6 +98,7 @@ void SetLowLevelAllocateCallback(LowLevelAllocateCallback callback);
void RawWrite(const char *buffer);
void Printf(const char *format, ...);
void Report(const char *format, ...);
void SetPrintfAndReportCallback(void (*callback)(const char *));
// Opens the file 'file_name" and reads up to 'max_len' bytes.
// The resulting buffer is mmaped and stored in '*buff'.

View File

@ -142,6 +142,11 @@ int VSNPrintf(char *buff, int buff_length,
return result;
}
static void (*PrintfAndReportCallback)(const char *);
void SetPrintfAndReportCallback(void (*callback)(const char *)) {
PrintfAndReportCallback = callback;
}
void Printf(const char *format, ...) {
const int kLen = 1024 * 4;
char *buffer = (char*)MmapOrDie(kLen, __FUNCTION__);
@ -151,6 +156,8 @@ void Printf(const char *format, ...) {
va_end(args);
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Printf is too short!\n");
RawWrite(buffer);
if (PrintfAndReportCallback)
PrintfAndReportCallback(buffer);
UnmapOrDie(buffer, kLen);
}
@ -179,6 +186,8 @@ void Report(const char *format, ...) {
va_end(args);
RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
RawWrite(buffer);
if (PrintfAndReportCallback)
PrintfAndReportCallback(buffer);
UnmapOrDie(buffer, kLen);
}