1e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov//===-- sanitizer_printf.cc -----------------------------------------------===// 2e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// 3e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// The LLVM Compiler Infrastructure 4e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// 5e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// This file is distributed under the University of Illinois Open Source 6e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// License. See LICENSE.TXT for details. 7e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// 8e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov//===----------------------------------------------------------------------===// 9e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// 10e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer. 11e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// 12e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// Internal printf function, used inside run-time libraries. 13e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// We can't use libc printf because we intercept some of the functions used 14e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// inside it. 15e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov//===----------------------------------------------------------------------===// 16e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 17e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 18e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov#include "sanitizer_common.h" 19e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov#include "sanitizer_libc.h" 20e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 21e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov#include <stdio.h> 22e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov#include <stdarg.h> 23e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 24c5288679cc55c523188a40325d49d97b100cf03cDmitry Vyukov#if SANITIZER_WINDOWS && !defined(va_copy) 256a72c9d8509bb8e751cb92e71407c039a767caa1Dmitry Vyukov# define va_copy(dst, src) ((dst) = (src)) 266a72c9d8509bb8e751cb92e71407c039a767caa1Dmitry Vyukov#endif 276a72c9d8509bb8e751cb92e71407c039a767caa1Dmitry Vyukov 28e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonovnamespace __sanitizer { 29e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 307ed46ff7af911da0dd2067734d1408c6986c6657Alexey SamsonovStaticSpinMutex CommonSanitizerReportMutex; 317ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov 32e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonovstatic int AppendChar(char **buff, const char *buff_end, char c) { 33e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov if (*buff < buff_end) { 34e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov **buff = c; 35e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov (*buff)++; 36e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 37e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov return 1; 38e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 39e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 40e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov// Appends number in a given base to buffer. If its length is less than 41134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev// |minimal_num_length|, it is padded with leading zeroes or spaces, depending 42134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev// on the value of |pad_with_zero|. 43134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveevstatic int AppendNumber(char **buff, const char *buff_end, u64 absolute_value, 44134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev u8 base, u8 minimal_num_length, bool pad_with_zero, 45134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev bool negative) { 46e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov uptr const kMaxLen = 30; 47e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov RAW_CHECK(base == 10 || base == 16); 48134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev RAW_CHECK(base == 10 || !negative); 49134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev RAW_CHECK(absolute_value || !negative); 50e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov RAW_CHECK(minimal_num_length < kMaxLen); 51134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev int result = 0; 52134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev if (negative && minimal_num_length) 53134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev --minimal_num_length; 54134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev if (negative && pad_with_zero) 55134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev result += AppendChar(buff, buff_end, '-'); 56e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov uptr num_buffer[kMaxLen]; 57134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev int pos = 0; 58e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov do { 59134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow"); 60134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev num_buffer[pos++] = absolute_value % base; 61134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev absolute_value /= base; 62134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev } while (absolute_value > 0); 63e52e2806f5eef9aa6a46fc81119f592ea22b0cbfAlexey Samsonov if (pos < minimal_num_length) { 64e52e2806f5eef9aa6a46fc81119f592ea22b0cbfAlexey Samsonov // Make sure compiler doesn't insert call to memset here. 65e52e2806f5eef9aa6a46fc81119f592ea22b0cbfAlexey Samsonov internal_memset(&num_buffer[pos], 0, 66e52e2806f5eef9aa6a46fc81119f592ea22b0cbfAlexey Samsonov sizeof(num_buffer[0]) * (minimal_num_length - pos)); 67e52e2806f5eef9aa6a46fc81119f592ea22b0cbfAlexey Samsonov pos = minimal_num_length; 68e52e2806f5eef9aa6a46fc81119f592ea22b0cbfAlexey Samsonov } 69134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev RAW_CHECK(pos > 0); 70134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev pos--; 71134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev for (; pos >= 0 && num_buffer[pos] == 0; pos--) { 72134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev char c = (pad_with_zero || pos == 0) ? '0' : ' '; 73134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev result += AppendChar(buff, buff_end, c); 74134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev } 75134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-'); 76134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev for (; pos >= 0; pos--) { 775e97ba38b00eb843a55189bb913b445cbe620894Timur Iskhodzhanov char digit = static_cast<char>(num_buffer[pos]); 78e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit 79e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov : 'a' + digit - 10); 80e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 81e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov return result; 82e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 83e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 84134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveevstatic int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base, 85134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev u8 minimal_num_length, bool pad_with_zero) { 86134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev return AppendNumber(buff, buff_end, num, base, minimal_num_length, 87134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev pad_with_zero, false /* negative */); 88134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev} 89134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev 90f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smithstatic int AppendSignedDecimal(char **buff, const char *buff_end, s64 num, 91134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev u8 minimal_num_length, bool pad_with_zero) { 92134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev bool negative = (num < 0); 93134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10, 94134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev minimal_num_length, pad_with_zero, negative); 95e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 96e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 97e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonovstatic int AppendString(char **buff, const char *buff_end, const char *s) { 98e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov if (s == 0) 99e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov s = "<null>"; 100e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov int result = 0; 101e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov for (; *s; s++) { 102e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendChar(buff, buff_end, *s); 103e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 104e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov return result; 105e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 106e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 107e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonovstatic int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) { 108e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov int result = 0; 109e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendString(buff, buff_end, "0x"); 110e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendUnsigned(buff, buff_end, ptr_value, 16, 111134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev (SANITIZER_WORDSIZE == 64) ? 12 : 8, true); 112e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov return result; 113e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 114e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 115e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonovint VSNPrintf(char *buff, int buff_length, 116e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov const char *format, va_list args) { 117f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith static const char *kPrintfFormatsHelp = 118134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n"; 119e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov RAW_CHECK(format); 120e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov RAW_CHECK(buff_length > 0); 121e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov const char *buff_end = &buff[buff_length - 1]; 122e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov const char *cur = format; 123e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov int result = 0; 124e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov for (; *cur; cur++) { 125e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov if (*cur != '%') { 126e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendChar(&buff, buff_end, *cur); 127e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov continue; 128e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 129e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov cur++; 130134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev bool have_width = (*cur >= '0' && *cur <= '9'); 131134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev bool pad_with_zero = (*cur == '0'); 132f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith int width = 0; 133f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith if (have_width) { 134f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith while (*cur >= '0' && *cur <= '9') { 135f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith width = width * 10 + *cur++ - '0'; 136f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith } 137f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith } 138e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov bool have_z = (*cur == 'z'); 139e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov cur += have_z; 140f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l'); 141f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith cur += have_ll * 2; 142e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov s64 dval; 143e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov u64 uval; 144f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith bool have_flags = have_width | have_z | have_ll; 145e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov switch (*cur) { 146e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov case 'd': { 147f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith dval = have_ll ? va_arg(args, s64) 148f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith : have_z ? va_arg(args, sptr) 149f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith : va_arg(args, int); 150134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev result += AppendSignedDecimal(&buff, buff_end, dval, width, 151134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev pad_with_zero); 152e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov break; 153e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 154e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov case 'u': 155e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov case 'x': { 156f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith uval = have_ll ? va_arg(args, u64) 157f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith : have_z ? va_arg(args, uptr) 158f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith : va_arg(args, unsigned); 159e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendUnsigned(&buff, buff_end, uval, 160134da448d092f82bfd5ddcdfa203c5c652c51474Sergey Matveev (*cur == 'u') ? 10 : 16, width, pad_with_zero); 161e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov break; 162e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 163e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov case 'p': { 164f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); 165e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendPointer(&buff, buff_end, va_arg(args, uptr)); 166e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov break; 167e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 168e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov case 's': { 169f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); 170e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendString(&buff, buff_end, va_arg(args, char*)); 171e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov break; 172e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 17381dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany case 'c': { 174f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); 17501167e89d77530d5d8507e1f0f1f2979a1497573Kostya Serebryany result += AppendChar(&buff, buff_end, va_arg(args, int)); 17681dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany break; 17781dfbb76f858fbc4084771fce4967ede04ed5f44Kostya Serebryany } 178e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov case '%' : { 179f4932204d7cf89cc2402b1e30fb728cf84ff7b7fRichard Smith RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp); 180e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov result += AppendChar(&buff, buff_end, '%'); 181e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov break; 182e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 183e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov default: { 184e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov RAW_CHECK_MSG(false, kPrintfFormatsHelp); 185e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 186e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 187e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov } 188e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov RAW_CHECK(buff <= buff_end); 189e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov AppendChar(&buff, buff_end + 1, '\0'); 190e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov return result; 191e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 192e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 193283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryanystatic void (*PrintfAndReportCallback)(const char *); 194283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryanyvoid SetPrintfAndReportCallback(void (*callback)(const char *)) { 195283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany PrintfAndReportCallback = callback; 196283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany} 197283c296b64bc55deec9698260b3427a9b050a925Kostya Serebryany 19878b580f3d40132816f813c3dbf073d824137436aAlexey Samsonov#if SANITIZER_SUPPORTS_WEAK_HOOKS 19913f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov// Can be overriden in frontend. 20078b580f3d40132816f813c3dbf073d824137436aAlexey SamsonovSANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE 20178b580f3d40132816f813c3dbf073d824137436aAlexey Samsonovvoid OnPrint(const char *str); 20213f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov#endif 20313f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov 20413f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukovstatic void CallPrintfAndReportCallback(const char *str) { 20578b580f3d40132816f813c3dbf073d824137436aAlexey Samsonov#if SANITIZER_SUPPORTS_WEAK_HOOKS 20678b580f3d40132816f813c3dbf073d824137436aAlexey Samsonov if (&OnPrint != NULL) 20778b580f3d40132816f813c3dbf073d824137436aAlexey Samsonov OnPrint(str); 20813f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov#endif 20913f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov if (PrintfAndReportCallback) 21013f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov PrintfAndReportCallback(str); 21113f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov} 21213f62b2cdaa09376e917a1efd0b1dd3d23bbff8dDmitry Vyukov 21399f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonovstatic void SharedPrintfCode(bool append_pid, const char *format, 21499f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_list args) { 2154f5e4bbdf775354433430fea4598ff3991442915Dmitry Vyukov va_list args2; 2164f5e4bbdf775354433430fea4598ff3991442915Dmitry Vyukov va_copy(args2, args); 217b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov const int kLen = 16 * 1024; 218c1b73e84db2f9f62633ee52b13cd1f83ef2fbe99Alexander Potapenko // |local_buffer| is small enough not to overflow the stack and/or violate 219c1b73e84db2f9f62633ee52b13cd1f83ef2fbe99Alexander Potapenko // the stack limit enforced by TSan (-Wframe-larger-than=512). On the other 220c1b73e84db2f9f62633ee52b13cd1f83ef2fbe99Alexander Potapenko // hand, the bigger the buffer is, the more the chance the error report will 221c1b73e84db2f9f62633ee52b13cd1f83ef2fbe99Alexander Potapenko // fit into it. 222c1b73e84db2f9f62633ee52b13cd1f83ef2fbe99Alexander Potapenko char local_buffer[400]; 223e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko int needed_length; 224e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko char *buffer = local_buffer; 22599f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov int buffer_size = ARRAY_SIZE(local_buffer); 22699f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov // First try to print a message using a local buffer, and then fall back to 22799f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov // mmaped buffer. 228e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko for (int use_mmap = 0; use_mmap < 2; use_mmap++) { 22999f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (use_mmap) { 2304f5e4bbdf775354433430fea4598ff3991442915Dmitry Vyukov va_end(args); 2314f5e4bbdf775354433430fea4598ff3991442915Dmitry Vyukov va_copy(args, args2); 23299f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov buffer = (char*)MmapOrDie(kLen, "Report"); 23399f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov buffer_size = kLen; 23499f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov } 23599f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov needed_length = 0; 23699f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (append_pid) { 2370b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne int pid = internal_getpid(); 23899f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov needed_length += internal_snprintf(buffer, buffer_size, "==%d==", pid); 23999f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (needed_length >= buffer_size) { 24099f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov // The pid doesn't fit into the current buffer. 24199f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (!use_mmap) 24299f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov continue; 243e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n"); 244e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko } 245e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko } 246e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko needed_length += VSNPrintf(buffer + needed_length, 24799f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov buffer_size - needed_length, format, args); 24899f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (needed_length >= buffer_size) { 24999f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov // The message doesn't fit into the current buffer. 25099f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (!use_mmap) 251e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko continue; 25299f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n"); 253e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko } 25499f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov // If the message fit into the buffer, print it and exit. 25599f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov break; 256e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko } 25799f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov RawWrite(buffer); 25899f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov CallPrintfAndReportCallback(buffer); 259e282b1ac6f9d370f9b30dbbd2da43f6346947f7fAlexander Potapenko // If we had mapped any memory, clean up. 26099f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov if (buffer != local_buffer) 26199f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov UnmapOrDie((void *)buffer, buffer_size); 2624f5e4bbdf775354433430fea4598ff3991442915Dmitry Vyukov va_end(args2); 26399f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov} 26499f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov 26599f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonovvoid Printf(const char *format, ...) { 26699f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_list args; 26799f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_start(args, format); 26899f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov SharedPrintfCode(false, format, args); 26999f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_end(args); 27099f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov} 27199f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov 27299f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov// Like Printf, but prints the current PID before the output string. 27399f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonovvoid Report(const char *format, ...) { 27499f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_list args; 27599f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_start(args, format); 27699f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov SharedPrintfCode(true, format, args); 27799f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_end(args); 27899f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov} 27999f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov 28099f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov// Writes at most "length" symbols to "buffer" (including trailing '\0'). 28199f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov// Returns the number of symbols that should have been written to buffer 28299f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov// (not including trailing '\0'). Thus, the string is truncated 28399f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov// iff return value is not less than "length". 28499f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonovint internal_snprintf(char *buffer, uptr length, const char *format, ...) { 28599f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_list args; 28699f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_start(args, format); 28799f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov int needed_length = VSNPrintf(buffer, length, format, args); 28899f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov va_end(args); 28999f1e2011a855edd3b1036660ec5e7b70aa06520Alexey Samsonov return needed_length; 290e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} 291e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov 292e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov} // namespace __sanitizer 293