| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2007-2009 Torch Mobile, Inc. | 3 * Copyright (C) 2007-2009 Torch Mobile, Inc. |
| 4 * Copyright (C) 2011 University of Szeged. All rights reserved. | 4 * Copyright (C) 2011 University of Szeged. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 #include <stdlib.h> | 44 #include <stdlib.h> |
| 45 #include <string.h> | 45 #include <string.h> |
| 46 | 46 |
| 47 #if OS(MACOSX) | 47 #if OS(MACOSX) |
| 48 #include <AvailabilityMacros.h> | 48 #include <AvailabilityMacros.h> |
| 49 #include <CoreFoundation/CFString.h> | 49 #include <CoreFoundation/CFString.h> |
| 50 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 | 50 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 |
| 51 #define WTF_USE_APPLE_SYSTEM_LOG 1 | 51 #define WTF_USE_APPLE_SYSTEM_LOG 1 |
| 52 #include <asl.h> | 52 #include <asl.h> |
| 53 #endif | 53 #endif |
| 54 #endif // OS(MACOSX) | 54 #endif // OS(MACOSX) |
| 55 | 55 |
| 56 #if COMPILER(MSVC) | 56 #if COMPILER(MSVC) |
| 57 #include <crtdbg.h> | 57 #include <crtdbg.h> |
| 58 #endif | 58 #endif |
| 59 | 59 |
| 60 #if OS(WIN) | 60 #if OS(WIN) |
| 61 #include <windows.h> | 61 #include <windows.h> |
| 62 #endif | 62 #endif |
| 63 | 63 |
| 64 #if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) | 64 #if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) |
| 65 #include <cxxabi.h> | 65 #include <cxxabi.h> |
| 66 #include <dlfcn.h> | 66 #include <dlfcn.h> |
| 67 #include <execinfo.h> | 67 #include <execinfo.h> |
| 68 #endif | 68 #endif |
| 69 | 69 |
| 70 #if OS(ANDROID) | 70 #if OS(ANDROID) |
| 71 #include <android/log.h> | 71 #include <android/log.h> |
| 72 #endif | 72 #endif |
| 73 | 73 |
| 74 WTF_ATTRIBUTE_PRINTF(1, 0) | 74 WTF_ATTRIBUTE_PRINTF(1, 0) |
| 75 static void vprintf_stderr_common(const char* format, va_list args) | 75 static void vprintf_stderr_common(const char* format, va_list args) { |
| 76 { | |
| 77 #if OS(MACOSX) | 76 #if OS(MACOSX) |
| 78 if (strstr(format, "%@")) { | 77 if (strstr(format, "%@")) { |
| 79 CFStringRef cfFormat = CFStringCreateWithCString(nullptr, format, kCFStr
ingEncodingUTF8); | 78 CFStringRef cfFormat = CFStringCreateWithCString(nullptr, format, kCFStringE
ncodingUTF8); |
| 80 | 79 |
| 81 #if COMPILER(CLANG) | 80 #if COMPILER(CLANG) |
| 82 #pragma clang diagnostic push | 81 #pragma clang diagnostic push |
| 83 #pragma clang diagnostic ignored "-Wformat-nonliteral" | 82 #pragma clang diagnostic ignored "-Wformat-nonliteral" |
| 84 #endif | 83 #endif |
| 85 CFStringRef str = CFStringCreateWithFormatAndArguments(nullptr, nullptr,
cfFormat, args); | 84 CFStringRef str = CFStringCreateWithFormatAndArguments(nullptr, nullptr, cfF
ormat, args); |
| 86 #if COMPILER(CLANG) | 85 #if COMPILER(CLANG) |
| 87 #pragma clang diagnostic pop | 86 #pragma clang diagnostic pop |
| 88 #endif | 87 #endif |
| 89 CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str
), kCFStringEncodingUTF8); | 88 CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), k
CFStringEncodingUTF8); |
| 90 char* buffer = (char*)malloc(length + 1); | 89 char* buffer = (char*)malloc(length + 1); |
| 91 | 90 |
| 92 CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8); | 91 CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8); |
| 93 | 92 |
| 94 #if USE(APPLE_SYSTEM_LOG) | 93 #if USE(APPLE_SYSTEM_LOG) |
| 95 asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer); | 94 asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer); |
| 96 #endif | 95 #endif |
| 97 fputs(buffer, stderr); | 96 fputs(buffer, stderr); |
| 98 | 97 |
| 99 free(buffer); | 98 free(buffer); |
| 100 CFRelease(str); | 99 CFRelease(str); |
| 101 CFRelease(cfFormat); | 100 CFRelease(cfFormat); |
| 102 return; | 101 return; |
| 103 } | 102 } |
| 104 | 103 |
| 105 #if USE(APPLE_SYSTEM_LOG) | 104 #if USE(APPLE_SYSTEM_LOG) |
| 106 va_list copyOfArgs; | 105 va_list copyOfArgs; |
| 107 va_copy(copyOfArgs, args); | 106 va_copy(copyOfArgs, args); |
| 108 asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs); | 107 asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs); |
| 109 va_end(copyOfArgs); | 108 va_end(copyOfArgs); |
| 110 #endif | 109 #endif |
| 111 | 110 |
| 112 // Fall through to write to stderr in the same manner as other platforms. | 111 // Fall through to write to stderr in the same manner as other platforms. |
| 113 | 112 |
| 114 #elif OS(ANDROID) | 113 #elif OS(ANDROID) |
| 115 __android_log_vprint(ANDROID_LOG_WARN, "WebKit", format, args); | 114 __android_log_vprint(ANDROID_LOG_WARN, "WebKit", format, args); |
| 116 #elif OS(WIN) | 115 #elif OS(WIN) |
| 117 if (IsDebuggerPresent()) { | 116 if (IsDebuggerPresent()) { |
| 118 size_t size = 1024; | 117 size_t size = 1024; |
| 119 | 118 |
| 120 do { | 119 do { |
| 121 char* buffer = (char*)malloc(size); | 120 char* buffer = (char*)malloc(size); |
| 122 if (!buffer) | 121 if (!buffer) |
| 123 break; | 122 break; |
| 124 | 123 |
| 125 if (_vsnprintf(buffer, size, format, args) != -1) { | 124 if (_vsnprintf(buffer, size, format, args) != -1) { |
| 126 OutputDebugStringA(buffer); | 125 OutputDebugStringA(buffer); |
| 127 free(buffer); | 126 free(buffer); |
| 128 break; | 127 break; |
| 129 } | 128 } |
| 130 | 129 |
| 131 free(buffer); | 130 free(buffer); |
| 132 size *= 2; | 131 size *= 2; |
| 133 } while (size > 1024); | 132 } while (size > 1024); |
| 134 } | 133 } |
| 135 #endif | 134 #endif |
| 136 vfprintf(stderr, format, args); | 135 vfprintf(stderr, format, args); |
| 137 } | 136 } |
| 138 | 137 |
| 139 #if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) | 138 #if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) |
| 140 #pragma GCC diagnostic push | 139 #pragma GCC diagnostic push |
| 141 #pragma GCC diagnostic ignored "-Wformat-nonliteral" | 140 #pragma GCC diagnostic ignored "-Wformat-nonliteral" |
| 142 #endif | 141 #endif |
| 143 | 142 |
| 144 static void vprintf_stderr_with_prefix(const char* prefix, const char* format, v
a_list args) | 143 static void vprintf_stderr_with_prefix(const char* prefix, const char* format, v
a_list args) { |
| 145 { | 144 size_t prefixLength = strlen(prefix); |
| 146 size_t prefixLength = strlen(prefix); | 145 size_t formatLength = strlen(format); |
| 147 size_t formatLength = strlen(format); | 146 OwnPtr<char[]> formatWithPrefix = adoptArrayPtr(new char[prefixLength + format
Length + 1]); |
| 148 OwnPtr<char[]> formatWithPrefix = adoptArrayPtr(new char[prefixLength + form
atLength + 1]); | 147 memcpy(formatWithPrefix.get(), prefix, prefixLength); |
| 149 memcpy(formatWithPrefix.get(), prefix, prefixLength); | 148 memcpy(formatWithPrefix.get() + prefixLength, format, formatLength); |
| 150 memcpy(formatWithPrefix.get() + prefixLength, format, formatLength); | 149 formatWithPrefix[prefixLength + formatLength] = 0; |
| 151 formatWithPrefix[prefixLength + formatLength] = 0; | |
| 152 | 150 |
| 153 vprintf_stderr_common(formatWithPrefix.get(), args); | 151 vprintf_stderr_common(formatWithPrefix.get(), args); |
| 154 } | 152 } |
| 155 | 153 |
| 156 static void vprintf_stderr_with_trailing_newline(const char* format, va_list arg
s) | 154 static void vprintf_stderr_with_trailing_newline(const char* format, va_list arg
s) { |
| 157 { | 155 size_t formatLength = strlen(format); |
| 158 size_t formatLength = strlen(format); | 156 if (formatLength && format[formatLength - 1] == '\n') { |
| 159 if (formatLength && format[formatLength - 1] == '\n') { | 157 vprintf_stderr_common(format, args); |
| 160 vprintf_stderr_common(format, args); | 158 return; |
| 161 return; | 159 } |
| 162 } | |
| 163 | 160 |
| 164 OwnPtr<char[]> formatWithNewline = adoptArrayPtr(new char[formatLength + 2])
; | 161 OwnPtr<char[]> formatWithNewline = adoptArrayPtr(new char[formatLength + 2]); |
| 165 memcpy(formatWithNewline.get(), format, formatLength); | 162 memcpy(formatWithNewline.get(), format, formatLength); |
| 166 formatWithNewline[formatLength] = '\n'; | 163 formatWithNewline[formatLength] = '\n'; |
| 167 formatWithNewline[formatLength + 1] = 0; | 164 formatWithNewline[formatLength + 1] = 0; |
| 168 | 165 |
| 169 vprintf_stderr_common(formatWithNewline.get(), args); | 166 vprintf_stderr_common(formatWithNewline.get(), args); |
| 170 } | 167 } |
| 171 | 168 |
| 172 #if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) | 169 #if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) |
| 173 #pragma GCC diagnostic pop | 170 #pragma GCC diagnostic pop |
| 174 #endif | 171 #endif |
| 175 | 172 |
| 176 WTF_ATTRIBUTE_PRINTF(1, 2) | 173 WTF_ATTRIBUTE_PRINTF(1, 2) |
| 177 static void printf_stderr_common(const char* format, ...) | 174 static void printf_stderr_common(const char* format, ...) { |
| 178 { | 175 va_list args; |
| 179 va_list args; | 176 va_start(args, format); |
| 180 va_start(args, format); | 177 vprintf_stderr_common(format, args); |
| 181 vprintf_stderr_common(format, args); | 178 va_end(args); |
| 182 va_end(args); | 179 } |
| 183 } | 180 |
| 184 | 181 static void printCallSite(const char* file, int line, const char* function) { |
| 185 static void printCallSite(const char* file, int line, const char* function) | |
| 186 { | |
| 187 #if OS(WIN) && defined(_DEBUG) | 182 #if OS(WIN) && defined(_DEBUG) |
| 188 _CrtDbgReport(_CRT_WARN, file, line, nullptr, "%s\n", function); | 183 _CrtDbgReport(_CRT_WARN, file, line, nullptr, "%s\n", function); |
| 189 #else | 184 #else |
| 190 // By using this format, which matches the format used by MSVC for compiler
errors, developers | 185 // By using this format, which matches the format used by MSVC for compiler er
rors, developers |
| 191 // using Visual Studio can double-click the file/line number in the Output W
indow to have the | 186 // using Visual Studio can double-click the file/line number in the Output Win
dow to have the |
| 192 // editor navigate to that line of code. It seems fine for other developers,
too. | 187 // editor navigate to that line of code. It seems fine for other developers, t
oo. |
| 193 printf_stderr_common("%s(%d) : %s\n", file, line, function); | 188 printf_stderr_common("%s(%d) : %s\n", file, line, function); |
| 194 #endif | 189 #endif |
| 195 } | 190 } |
| 196 | 191 |
| 197 void WTFReportAssertionFailure(const char* file, int line, const char* function,
const char* assertion) | 192 void WTFReportAssertionFailure(const char* file, int line, const char* function,
const char* assertion) { |
| 198 { | 193 if (assertion) |
| 199 if (assertion) | 194 printf_stderr_common("ASSERTION FAILED: %s\n", assertion); |
| 200 printf_stderr_common("ASSERTION FAILED: %s\n", assertion); | 195 else |
| 196 printf_stderr_common("SHOULD NEVER BE REACHED\n"); |
| 197 printCallSite(file, line, function); |
| 198 } |
| 199 |
| 200 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char
* function, const char* assertion, const char* format, ...) { |
| 201 va_list args; |
| 202 va_start(args, format); |
| 203 vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args); |
| 204 va_end(args); |
| 205 printf_stderr_common("\n%s\n", assertion); |
| 206 printCallSite(file, line, function); |
| 207 } |
| 208 |
| 209 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* f
unction, const char* argName, const char* assertion) { |
| 210 printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion); |
| 211 printCallSite(file, line, function); |
| 212 } |
| 213 |
| 214 void WTFGetBacktrace(void** stack, int* size) { |
| 215 #if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) |
| 216 *size = backtrace(stack, *size); |
| 217 #elif OS(WIN) |
| 218 // The CaptureStackBackTrace function is available in XP, but it is not define
d |
| 219 // in the Windows Server 2003 R2 Platform SDK. So, we'll grab the function |
| 220 // through GetProcAddress. |
| 221 typedef WORD(NTAPI * RtlCaptureStackBackTraceFunc)(DWORD, DWORD, PVOID*, PDWOR
D); |
| 222 HMODULE kernel32 = ::GetModuleHandleW(L"Kernel32.dll"); |
| 223 if (!kernel32) { |
| 224 *size = 0; |
| 225 return; |
| 226 } |
| 227 RtlCaptureStackBackTraceFunc captureStackBackTraceFunc = reinterpret_cast<RtlC
aptureStackBackTraceFunc>( |
| 228 ::GetProcAddress(kernel32, "RtlCaptureStackBackTrace")); |
| 229 if (captureStackBackTraceFunc) |
| 230 *size = captureStackBackTraceFunc(0, *size, stack, 0); |
| 231 else |
| 232 *size = 0; |
| 233 #else |
| 234 *size = 0; |
| 235 #endif |
| 236 } |
| 237 |
| 238 void WTFReportBacktrace(int framesToShow) { |
| 239 static const int framesToSkip = 2; |
| 240 // Use alloca to allocate on the stack since this function is used in OOM situ
ations. |
| 241 void** samples = static_cast<void**>(alloca((framesToShow + framesToSkip) * si
zeof(void*))); |
| 242 int frames = framesToShow + framesToSkip; |
| 243 |
| 244 WTFGetBacktrace(samples, &frames); |
| 245 WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip); |
| 246 } |
| 247 |
| 248 FrameToNameScope::FrameToNameScope(void* addr) |
| 249 : m_name(0), m_cxaDemangled(0) { |
| 250 #if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) |
| 251 Dl_info info; |
| 252 if (!dladdr(addr, &info) || !info.dli_sname) |
| 253 return; |
| 254 const char* mangledName = info.dli_sname; |
| 255 if ((m_cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0))) |
| 256 m_name = m_cxaDemangled; |
| 257 else |
| 258 m_name = mangledName; |
| 259 #else |
| 260 (void)addr; |
| 261 #endif |
| 262 } |
| 263 |
| 264 FrameToNameScope::~FrameToNameScope() { |
| 265 free(m_cxaDemangled); |
| 266 } |
| 267 |
| 268 static const char kScopedLoggerIndent[] = " "; |
| 269 |
| 270 ScopedLogger::ScopedLogger(bool condition, const char* format, ...) |
| 271 : m_parent(condition ? current() : 0), m_multiline(false) { |
| 272 if (!condition) |
| 273 return; |
| 274 |
| 275 va_list args; |
| 276 va_start(args, format); |
| 277 init(format, args); |
| 278 va_end(args); |
| 279 } |
| 280 |
| 281 ScopedLogger::~ScopedLogger() { |
| 282 if (current() == this) { |
| 283 if (m_multiline) |
| 284 indent(); |
| 201 else | 285 else |
| 202 printf_stderr_common("SHOULD NEVER BE REACHED\n"); | 286 print(" "); |
| 203 printCallSite(file, line, function); | 287 print(")\n"); |
| 204 } | 288 current() = m_parent; |
| 205 | 289 } |
| 206 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char
* function, const char* assertion, const char* format, ...) | 290 } |
| 207 { | 291 |
| 208 va_list args; | 292 void ScopedLogger::init(const char* format, va_list args) { |
| 209 va_start(args, format); | 293 current() = this; |
| 210 vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args); | 294 if (m_parent) |
| 211 va_end(args); | 295 m_parent->writeNewlineIfNeeded(); |
| 212 printf_stderr_common("\n%s\n", assertion); | 296 indent(); |
| 213 printCallSite(file, line, function); | 297 print("( "); |
| 214 } | 298 m_printFunc(format, args); |
| 215 | 299 } |
| 216 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* f
unction, const char* argName, const char* assertion) | 300 |
| 217 { | 301 void ScopedLogger::writeNewlineIfNeeded() { |
| 218 printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion); | 302 if (!m_multiline) { |
| 219 printCallSite(file, line, function); | 303 print("\n"); |
| 220 } | 304 m_multiline = true; |
| 221 | 305 } |
| 222 void WTFGetBacktrace(void** stack, int* size) | 306 } |
| 223 { | 307 |
| 224 #if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) | 308 void ScopedLogger::indent() { |
| 225 *size = backtrace(stack, *size); | 309 if (m_parent) { |
| 226 #elif OS(WIN) | 310 m_parent->indent(); |
| 227 // The CaptureStackBackTrace function is available in XP, but it is not defi
ned | 311 print(kScopedLoggerIndent); |
| 228 // in the Windows Server 2003 R2 Platform SDK. So, we'll grab the function | 312 } |
| 229 // through GetProcAddress. | 313 } |
| 230 typedef WORD (NTAPI* RtlCaptureStackBackTraceFunc)(DWORD, DWORD, PVOID*, PDW
ORD); | 314 |
| 231 HMODULE kernel32 = ::GetModuleHandleW(L"Kernel32.dll"); | 315 void ScopedLogger::log(const char* format, ...) { |
| 232 if (!kernel32) { | 316 if (current() != this) |
| 233 *size = 0; | 317 return; |
| 234 return; | 318 |
| 235 } | 319 va_list args; |
| 236 RtlCaptureStackBackTraceFunc captureStackBackTraceFunc = reinterpret_cast<Rt
lCaptureStackBackTraceFunc>( | 320 va_start(args, format); |
| 237 ::GetProcAddress(kernel32, "RtlCaptureStackBackTrace")); | 321 |
| 238 if (captureStackBackTraceFunc) | 322 writeNewlineIfNeeded(); |
| 239 *size = captureStackBackTraceFunc(0, *size, stack, 0); | 323 indent(); |
| 324 print(kScopedLoggerIndent); |
| 325 m_printFunc(format, args); |
| 326 print("\n"); |
| 327 |
| 328 va_end(args); |
| 329 } |
| 330 |
| 331 void ScopedLogger::print(const char* format, ...) { |
| 332 va_list args; |
| 333 va_start(args, format); |
| 334 m_printFunc(format, args); |
| 335 va_end(args); |
| 336 } |
| 337 |
| 338 ScopedLogger*& ScopedLogger::current() { |
| 339 AtomicallyInitializedStaticReference(ThreadSpecific<ScopedLogger*>, ref, new T
hreadSpecific<ScopedLogger*>); |
| 340 return *ref; |
| 341 } |
| 342 |
| 343 ScopedLogger::PrintFunctionPtr ScopedLogger::m_printFunc = vprintf_stderr_common
; |
| 344 |
| 345 void WTFPrintBacktrace(void** stack, int size) { |
| 346 for (int i = 0; i < size; ++i) { |
| 347 FrameToNameScope frameToName(stack[i]); |
| 348 const int frameNumber = i + 1; |
| 349 if (frameToName.nullableName()) |
| 350 printf_stderr_common("%-3d %p %s\n", frameNumber, stack[i], frameToName.nu
llableName()); |
| 240 else | 351 else |
| 241 *size = 0; | 352 printf_stderr_common("%-3d %p\n", frameNumber, stack[i]); |
| 242 #else | 353 } |
| 243 *size = 0; | 354 } |
| 244 #endif | 355 |
| 245 } | 356 void WTFReportFatalError(const char* file, int line, const char* function, const
char* format, ...) { |
| 246 | 357 va_list args; |
| 247 void WTFReportBacktrace(int framesToShow) | 358 va_start(args, format); |
| 248 { | 359 vprintf_stderr_with_prefix("FATAL ERROR: ", format, args); |
| 249 static const int framesToSkip = 2; | 360 va_end(args); |
| 250 // Use alloca to allocate on the stack since this function is used in OOM si
tuations. | 361 printf_stderr_common("\n"); |
| 251 void** samples = static_cast<void**>(alloca((framesToShow + framesToSkip) *
sizeof(void *))); | 362 printCallSite(file, line, function); |
| 252 int frames = framesToShow + framesToSkip; | 363 } |
| 253 | 364 |
| 254 WTFGetBacktrace(samples, &frames); | 365 void WTFReportError(const char* file, int line, const char* function, const char
* format, ...) { |
| 255 WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip); | 366 va_list args; |
| 256 } | 367 va_start(args, format); |
| 257 | 368 vprintf_stderr_with_prefix("ERROR: ", format, args); |
| 258 FrameToNameScope::FrameToNameScope(void* addr) | 369 va_end(args); |
| 259 : m_name(0) | 370 printf_stderr_common("\n"); |
| 260 , m_cxaDemangled(0) | 371 printCallSite(file, line, function); |
| 261 { | 372 } |
| 262 #if OS(MACOSX) || (OS(LINUX) && !defined(__UCLIBC__)) | 373 |
| 263 Dl_info info; | 374 void WTFLog(WTFLogChannel* channel, const char* format, ...) { |
| 264 if (!dladdr(addr, &info) || !info.dli_sname) | 375 if (channel->state != WTFLogChannelOn) |
| 265 return; | 376 return; |
| 266 const char* mangledName = info.dli_sname; | 377 |
| 267 if ((m_cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0))) | 378 va_list args; |
| 268 m_name = m_cxaDemangled; | 379 va_start(args, format); |
| 269 else | 380 vprintf_stderr_with_trailing_newline(format, args); |
| 270 m_name = mangledName; | 381 va_end(args); |
| 271 #else | 382 } |
| 272 (void)addr; | 383 |
| 273 #endif | 384 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
el* channel, const char* format, ...) { |
| 274 } | 385 if (channel->state != WTFLogChannelOn) |
| 275 | 386 return; |
| 276 FrameToNameScope::~FrameToNameScope() | 387 |
| 277 { | 388 va_list args; |
| 278 free(m_cxaDemangled); | 389 va_start(args, format); |
| 279 } | 390 vprintf_stderr_with_trailing_newline(format, args); |
| 280 | 391 va_end(args); |
| 281 static const char kScopedLoggerIndent[] = " "; | 392 |
| 282 | 393 printCallSite(file, line, function); |
| 283 ScopedLogger::ScopedLogger(bool condition, const char* format, ...) | 394 } |
| 284 : m_parent(condition ? current() : 0) | 395 |
| 285 , m_multiline(false) | 396 void WTFLogAlways(const char* format, ...) { |
| 286 { | 397 va_list args; |
| 287 if (!condition) | 398 va_start(args, format); |
| 288 return; | 399 vprintf_stderr_with_trailing_newline(format, args); |
| 289 | 400 va_end(args); |
| 290 va_list args; | 401 } |
| 291 va_start(args, format); | |
| 292 init(format, args); | |
| 293 va_end(args); | |
| 294 } | |
| 295 | |
| 296 ScopedLogger::~ScopedLogger() | |
| 297 { | |
| 298 if (current() == this) { | |
| 299 if (m_multiline) | |
| 300 indent(); | |
| 301 else | |
| 302 print(" "); | |
| 303 print(")\n"); | |
| 304 current() = m_parent; | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 void ScopedLogger::init(const char* format, va_list args) | |
| 309 { | |
| 310 current() = this; | |
| 311 if (m_parent) | |
| 312 m_parent->writeNewlineIfNeeded(); | |
| 313 indent(); | |
| 314 print("( "); | |
| 315 m_printFunc(format, args); | |
| 316 } | |
| 317 | |
| 318 void ScopedLogger::writeNewlineIfNeeded() | |
| 319 { | |
| 320 if (!m_multiline) { | |
| 321 print("\n"); | |
| 322 m_multiline = true; | |
| 323 } | |
| 324 } | |
| 325 | |
| 326 void ScopedLogger::indent() | |
| 327 { | |
| 328 if (m_parent) { | |
| 329 m_parent->indent(); | |
| 330 print(kScopedLoggerIndent); | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 void ScopedLogger::log(const char* format, ...) | |
| 335 { | |
| 336 if (current() != this) | |
| 337 return; | |
| 338 | |
| 339 va_list args; | |
| 340 va_start(args, format); | |
| 341 | |
| 342 writeNewlineIfNeeded(); | |
| 343 indent(); | |
| 344 print(kScopedLoggerIndent); | |
| 345 m_printFunc(format, args); | |
| 346 print("\n"); | |
| 347 | |
| 348 va_end(args); | |
| 349 } | |
| 350 | |
| 351 void ScopedLogger::print(const char* format, ...) | |
| 352 { | |
| 353 va_list args; | |
| 354 va_start(args, format); | |
| 355 m_printFunc(format, args); | |
| 356 va_end(args); | |
| 357 } | |
| 358 | |
| 359 ScopedLogger*& ScopedLogger::current() | |
| 360 { | |
| 361 AtomicallyInitializedStaticReference(ThreadSpecific<ScopedLogger*>, ref, new
ThreadSpecific<ScopedLogger*>); | |
| 362 return *ref; | |
| 363 } | |
| 364 | |
| 365 ScopedLogger::PrintFunctionPtr ScopedLogger::m_printFunc = vprintf_stderr_common
; | |
| 366 | |
| 367 void WTFPrintBacktrace(void** stack, int size) | |
| 368 { | |
| 369 for (int i = 0; i < size; ++i) { | |
| 370 FrameToNameScope frameToName(stack[i]); | |
| 371 const int frameNumber = i + 1; | |
| 372 if (frameToName.nullableName()) | |
| 373 printf_stderr_common("%-3d %p %s\n", frameNumber, stack[i], frameToN
ame.nullableName()); | |
| 374 else | |
| 375 printf_stderr_common("%-3d %p\n", frameNumber, stack[i]); | |
| 376 } | |
| 377 } | |
| 378 | |
| 379 void WTFReportFatalError(const char* file, int line, const char* function, const
char* format, ...) | |
| 380 { | |
| 381 va_list args; | |
| 382 va_start(args, format); | |
| 383 vprintf_stderr_with_prefix("FATAL ERROR: ", format, args); | |
| 384 va_end(args); | |
| 385 printf_stderr_common("\n"); | |
| 386 printCallSite(file, line, function); | |
| 387 } | |
| 388 | |
| 389 void WTFReportError(const char* file, int line, const char* function, const char
* format, ...) | |
| 390 { | |
| 391 va_list args; | |
| 392 va_start(args, format); | |
| 393 vprintf_stderr_with_prefix("ERROR: ", format, args); | |
| 394 va_end(args); | |
| 395 printf_stderr_common("\n"); | |
| 396 printCallSite(file, line, function); | |
| 397 } | |
| 398 | |
| 399 void WTFLog(WTFLogChannel* channel, const char* format, ...) | |
| 400 { | |
| 401 if (channel->state != WTFLogChannelOn) | |
| 402 return; | |
| 403 | |
| 404 va_list args; | |
| 405 va_start(args, format); | |
| 406 vprintf_stderr_with_trailing_newline(format, args); | |
| 407 va_end(args); | |
| 408 } | |
| 409 | |
| 410 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
el* channel, const char* format, ...) | |
| 411 { | |
| 412 if (channel->state != WTFLogChannelOn) | |
| 413 return; | |
| 414 | |
| 415 va_list args; | |
| 416 va_start(args, format); | |
| 417 vprintf_stderr_with_trailing_newline(format, args); | |
| 418 va_end(args); | |
| 419 | |
| 420 printCallSite(file, line, function); | |
| 421 } | |
| 422 | |
| 423 void WTFLogAlways(const char* format, ...) | |
| 424 { | |
| 425 va_list args; | |
| 426 va_start(args, format); | |
| 427 vprintf_stderr_with_trailing_newline(format, args); | |
| 428 va_end(args); | |
| 429 } | |
| 430 | |
| OLD | NEW |