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