diff options
Diffstat (limited to 'lib/sanitizer_common/sanitizer_printf.cc')
-rw-r--r-- | lib/sanitizer_common/sanitizer_printf.cc | 88 |
1 files changed, 61 insertions, 27 deletions
diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 7b70c3aae23d..2393e8f2b87b 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -45,7 +45,12 @@ static int AppendUnsigned(char **buff, const char *buff_end, u64 num, num_buffer[pos++] = num % base; num /= base; } while (num > 0); - while (pos < minimal_num_length) num_buffer[pos++] = 0; + if (pos < minimal_num_length) { + // Make sure compiler doesn't insert call to memset here. + internal_memset(&num_buffer[pos], 0, + sizeof(num_buffer[0]) * (minimal_num_length - pos)); + pos = minimal_num_length; + } int result = 0; while (pos-- > 0) { uptr digit = num_buffer[pos]; @@ -55,13 +60,16 @@ static int AppendUnsigned(char **buff, const char *buff_end, u64 num, return result; } -static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num) { +static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num, + u8 minimal_num_length) { int result = 0; if (num < 0) { result += AppendChar(buff, buff_end, '-'); num = -num; + if (minimal_num_length) + --minimal_num_length; } - result += AppendUnsigned(buff, buff_end, (u64)num, 10, 0); + result += AppendUnsigned(buff, buff_end, (u64)num, 10, minimal_num_length); return result; } @@ -79,14 +87,14 @@ 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); + (SANITIZER_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"; + static const char *kPrintfFormatsHelp = + "Supported Printf formats: %(0[0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n"; RAW_CHECK(format); RAW_CHECK(buff_length > 0); const char *buff_end = &buff[buff_length - 1]; @@ -98,37 +106,55 @@ int VSNPrintf(char *buff, int buff_length, continue; } cur++; + bool have_width = (*cur == '0'); + int width = 0; + if (have_width) { + while (*cur >= '0' && *cur <= '9') { + have_width = true; + width = width * 10 + *cur++ - '0'; + } + } bool have_z = (*cur == 'z'); cur += have_z; + bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l'); + cur += have_ll * 2; s64 dval; u64 uval; + bool have_flags = have_width | have_z | have_ll; switch (*cur) { case 'd': { - dval = have_z ? va_arg(args, sptr) - : va_arg(args, int); - result += AppendSignedDecimal(&buff, buff_end, dval); + dval = have_ll ? va_arg(args, s64) + : have_z ? va_arg(args, sptr) + : va_arg(args, int); + result += AppendSignedDecimal(&buff, buff_end, dval, width); break; } case 'u': case 'x': { - uval = have_z ? va_arg(args, uptr) - : va_arg(args, unsigned); + uval = have_ll ? va_arg(args, u64) + : have_z ? va_arg(args, uptr) + : va_arg(args, unsigned); result += AppendUnsigned(&buff, buff_end, uval, - (*cur == 'u') ? 10 : 16, 0); + (*cur == 'u') ? 10 : 16, width); break; } case 'p': { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendPointer(&buff, buff_end, va_arg(args, uptr)); break; } case 's': { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendString(&buff, buff_end, va_arg(args, char*)); break; } + case 'c': { + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); + result += AppendChar(&buff, buff_end, va_arg(args, int)); + break; + } case '%' : { - RAW_CHECK_MSG(!have_z, kPrintfFormatsHelp); + RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); result += AppendChar(&buff, buff_end, '%'); break; } @@ -142,16 +168,22 @@ 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__); + const int kLen = 16 * 1024; + InternalScopedBuffer<char> buffer(kLen); va_list args; va_start(args, format); - int needed_length = VSNPrintf(buffer, kLen, format, args); + int needed_length = VSNPrintf(buffer.data(), kLen, format, args); va_end(args); RAW_CHECK_MSG(needed_length < kLen, "Buffer in Printf is too short!\n"); - RawWrite(buffer); - UnmapOrDie(buffer, kLen); + RawWrite(buffer.data()); + if (PrintfAndReportCallback) + PrintfAndReportCallback(buffer.data()); } // Writes at most "length" symbols to "buffer" (including trailing '\0'). @@ -168,18 +200,20 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) { // 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, __FUNCTION__); - int needed_length = internal_snprintf(buffer, kLen, "==%d== ", GetPid()); + const int kLen = 16 * 1024; + InternalScopedBuffer<char> buffer(kLen); + int needed_length = internal_snprintf(buffer.data(), + 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); + needed_length += VSNPrintf(buffer.data() + 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); + RawWrite(buffer.data()); + if (PrintfAndReportCallback) + PrintfAndReportCallback(buffer.data()); } } // namespace __sanitizer |