| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. | |
| 3 * Copyright (C) 2007-2009 Torch Mobile, Inc. | |
| 4 * Copyright (C) 2011 University of Szeged. All rights reserved. | |
| 5 * | |
| 6 * Redistribution and use in source and binary forms, with or without | |
| 7 * modification, are permitted provided that the following conditions | |
| 8 * are met: | |
| 9 * 1. Redistributions of source code must retain the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer. | |
| 11 * 2. Redistributions in binary form must reproduce the above copyright | |
| 12 * notice, this list of conditions and the following disclaimer in the | |
| 13 * documentation and/or other materials provided with the distribution. | |
| 14 * | |
| 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | |
| 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
| 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 */ | |
| 27 | |
| 28 // The vprintf_stderr_common function triggers this error in the Mac build. | |
| 29 // Feel free to remove this pragma if this file builds on Mac. | |
| 30 // According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.h
tml#Diagnostic-Pragmas | |
| 31 // we need to place this directive before any data or functions are defined. | |
| 32 #pragma GCC diagnostic ignored "-Wmissing-format-attribute" | |
| 33 | |
| 34 #include "config.h" | |
| 35 #include "Assertions.h" | |
| 36 | |
| 37 #include "Compiler.h" | |
| 38 #include "OwnArrayPtr.h" | |
| 39 | |
| 40 #include <stdio.h> | |
| 41 #include <stdarg.h> | |
| 42 #include <string.h> | |
| 43 | |
| 44 #if HAVE(SIGNAL_H) | |
| 45 #include <signal.h> | |
| 46 #endif | |
| 47 | |
| 48 #if USE(CF) | |
| 49 #include <CoreFoundation/CFString.h> | |
| 50 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 | |
| 51 #define WTF_USE_APPLE_SYSTEM_LOG 1 | |
| 52 #include <asl.h> | |
| 53 #endif | |
| 54 #endif // USE(CF) | |
| 55 | |
| 56 #if COMPILER(MSVC) && !OS(WINCE) | |
| 57 #include <crtdbg.h> | |
| 58 #endif | |
| 59 | |
| 60 #if OS(WINDOWS) | |
| 61 #include <windows.h> | |
| 62 #endif | |
| 63 | |
| 64 #if (OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__))) && !OS(ANDROID) | |
| 65 #include <cxxabi.h> | |
| 66 #include <dlfcn.h> | |
| 67 #include <execinfo.h> | |
| 68 #endif | |
| 69 | |
| 70 #if OS(ANDROID) | |
| 71 #include "android/log.h" | |
| 72 #endif | |
| 73 | |
| 74 extern "C" { | |
| 75 | |
| 76 WTF_ATTRIBUTE_PRINTF(1, 0) | |
| 77 static void vprintf_stderr_common(const char* format, va_list args) | |
| 78 { | |
| 79 #if USE(CF) && !OS(WINDOWS) | |
| 80 if (strstr(format, "%@")) { | |
| 81 CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFString
EncodingUTF8); | |
| 82 | |
| 83 #if COMPILER(CLANG) | |
| 84 #pragma clang diagnostic push | |
| 85 #pragma clang diagnostic ignored "-Wformat-nonliteral" | |
| 86 #endif | |
| 87 CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFor
mat, args); | |
| 88 #if COMPILER(CLANG) | |
| 89 #pragma clang diagnostic pop | |
| 90 #endif | |
| 91 CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str
), kCFStringEncodingUTF8); | |
| 92 char* buffer = (char*)malloc(length + 1); | |
| 93 | |
| 94 CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8); | |
| 95 | |
| 96 #if USE(APPLE_SYSTEM_LOG) | |
| 97 asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer); | |
| 98 #endif | |
| 99 fputs(buffer, stderr); | |
| 100 | |
| 101 free(buffer); | |
| 102 CFRelease(str); | |
| 103 CFRelease(cfFormat); | |
| 104 return; | |
| 105 } | |
| 106 | |
| 107 #if USE(APPLE_SYSTEM_LOG) | |
| 108 va_list copyOfArgs; | |
| 109 va_copy(copyOfArgs, args); | |
| 110 asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs); | |
| 111 va_end(copyOfArgs); | |
| 112 #endif | |
| 113 | |
| 114 // Fall through to write to stderr in the same manner as other platforms. | |
| 115 | |
| 116 #elif OS(ANDROID) | |
| 117 __android_log_vprint(ANDROID_LOG_WARN, "WebKit", format, args); | |
| 118 #elif HAVE(ISDEBUGGERPRESENT) | |
| 119 if (IsDebuggerPresent()) { | |
| 120 size_t size = 1024; | |
| 121 | |
| 122 do { | |
| 123 char* buffer = (char*)malloc(size); | |
| 124 | |
| 125 if (buffer == NULL) | |
| 126 break; | |
| 127 | |
| 128 if (_vsnprintf(buffer, size, format, args) != -1) { | |
| 129 #if OS(WINCE) | |
| 130 // WinCE only supports wide chars | |
| 131 wchar_t* wideBuffer = (wchar_t*)malloc(size * sizeof(wchar_t)); | |
| 132 if (wideBuffer == NULL) | |
| 133 break; | |
| 134 for (unsigned int i = 0; i < size; ++i) { | |
| 135 if (!(wideBuffer[i] = buffer[i])) | |
| 136 break; | |
| 137 } | |
| 138 OutputDebugStringW(wideBuffer); | |
| 139 free(wideBuffer); | |
| 140 #else | |
| 141 OutputDebugStringA(buffer); | |
| 142 #endif | |
| 143 free(buffer); | |
| 144 break; | |
| 145 } | |
| 146 | |
| 147 free(buffer); | |
| 148 size *= 2; | |
| 149 } while (size > 1024); | |
| 150 } | |
| 151 #endif | |
| 152 vfprintf(stderr, format, args); | |
| 153 } | |
| 154 | |
| 155 #if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) | |
| 156 #pragma GCC diagnostic push | |
| 157 #pragma GCC diagnostic ignored "-Wformat-nonliteral" | |
| 158 #endif | |
| 159 | |
| 160 static void vprintf_stderr_with_prefix(const char* prefix, const char* format, v
a_list args) | |
| 161 { | |
| 162 size_t prefixLength = strlen(prefix); | |
| 163 size_t formatLength = strlen(format); | |
| 164 OwnArrayPtr<char> formatWithPrefix = adoptArrayPtr(new char[prefixLength + f
ormatLength + 1]); | |
| 165 memcpy(formatWithPrefix.get(), prefix, prefixLength); | |
| 166 memcpy(formatWithPrefix.get() + prefixLength, format, formatLength); | |
| 167 formatWithPrefix[prefixLength + formatLength] = 0; | |
| 168 | |
| 169 vprintf_stderr_common(formatWithPrefix.get(), args); | |
| 170 } | |
| 171 | |
| 172 static void vprintf_stderr_with_trailing_newline(const char* format, va_list arg
s) | |
| 173 { | |
| 174 size_t formatLength = strlen(format); | |
| 175 if (formatLength && format[formatLength - 1] == '\n') { | |
| 176 vprintf_stderr_common(format, args); | |
| 177 return; | |
| 178 } | |
| 179 | |
| 180 OwnArrayPtr<char> formatWithNewline = adoptArrayPtr(new char[formatLength +
2]); | |
| 181 memcpy(formatWithNewline.get(), format, formatLength); | |
| 182 formatWithNewline[formatLength] = '\n'; | |
| 183 formatWithNewline[formatLength + 1] = 0; | |
| 184 | |
| 185 vprintf_stderr_common(formatWithNewline.get(), args); | |
| 186 } | |
| 187 | |
| 188 #if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) | |
| 189 #pragma GCC diagnostic pop | |
| 190 #endif | |
| 191 | |
| 192 WTF_ATTRIBUTE_PRINTF(1, 2) | |
| 193 static void printf_stderr_common(const char* format, ...) | |
| 194 { | |
| 195 va_list args; | |
| 196 va_start(args, format); | |
| 197 vprintf_stderr_common(format, args); | |
| 198 va_end(args); | |
| 199 } | |
| 200 | |
| 201 static void printCallSite(const char* file, int line, const char* function) | |
| 202 { | |
| 203 #if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG) | |
| 204 _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function); | |
| 205 #else | |
| 206 // By using this format, which matches the format used by MSVC for compiler
errors, developers | |
| 207 // using Visual Studio can double-click the file/line number in the Output W
indow to have the | |
| 208 // editor navigate to that line of code. It seems fine for other developers,
too. | |
| 209 printf_stderr_common("%s(%d) : %s\n", file, line, function); | |
| 210 #endif | |
| 211 } | |
| 212 | |
| 213 void WTFReportAssertionFailure(const char* file, int line, const char* function,
const char* assertion) | |
| 214 { | |
| 215 if (assertion) | |
| 216 printf_stderr_common("ASSERTION FAILED: %s\n", assertion); | |
| 217 else | |
| 218 printf_stderr_common("SHOULD NEVER BE REACHED\n"); | |
| 219 printCallSite(file, line, function); | |
| 220 } | |
| 221 | |
| 222 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char
* function, const char* assertion, const char* format, ...) | |
| 223 { | |
| 224 va_list args; | |
| 225 va_start(args, format); | |
| 226 vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args); | |
| 227 va_end(args); | |
| 228 printf_stderr_common("\n%s\n", assertion); | |
| 229 printCallSite(file, line, function); | |
| 230 } | |
| 231 | |
| 232 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* f
unction, const char* argName, const char* assertion) | |
| 233 { | |
| 234 printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion); | |
| 235 printCallSite(file, line, function); | |
| 236 } | |
| 237 | |
| 238 void WTFGetBacktrace(void** stack, int* size) | |
| 239 { | |
| 240 #if (OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__))) && !OS(ANDROID) | |
| 241 *size = backtrace(stack, *size); | |
| 242 #elif OS(WINDOWS) && !OS(WINCE) | |
| 243 // The CaptureStackBackTrace function is available in XP, but it is not defi
ned | |
| 244 // in the Windows Server 2003 R2 Platform SDK. So, we'll grab the function | |
| 245 // through GetProcAddress. | |
| 246 typedef WORD (NTAPI* RtlCaptureStackBackTraceFunc)(DWORD, DWORD, PVOID*, PDW
ORD); | |
| 247 HMODULE kernel32 = ::GetModuleHandleW(L"Kernel32.dll"); | |
| 248 if (!kernel32) { | |
| 249 *size = 0; | |
| 250 return; | |
| 251 } | |
| 252 RtlCaptureStackBackTraceFunc captureStackBackTraceFunc = reinterpret_cast<Rt
lCaptureStackBackTraceFunc>( | |
| 253 ::GetProcAddress(kernel32, "RtlCaptureStackBackTrace")); | |
| 254 if (captureStackBackTraceFunc) | |
| 255 *size = captureStackBackTraceFunc(0, *size, stack, 0); | |
| 256 else | |
| 257 *size = 0; | |
| 258 #else | |
| 259 *size = 0; | |
| 260 #endif | |
| 261 } | |
| 262 | |
| 263 void WTFReportBacktrace() | |
| 264 { | |
| 265 static const int framesToShow = 31; | |
| 266 static const int framesToSkip = 2; | |
| 267 void* samples[framesToShow + framesToSkip]; | |
| 268 int frames = framesToShow + framesToSkip; | |
| 269 | |
| 270 WTFGetBacktrace(samples, &frames); | |
| 271 WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip); | |
| 272 } | |
| 273 | |
| 274 #if OS(DARWIN) || (OS(LINUX) && !OS(ANDROID)) | |
| 275 #define WTF_USE_DLADDR 1 | |
| 276 #endif | |
| 277 | |
| 278 void WTFPrintBacktrace(void** stack, int size) | |
| 279 { | |
| 280 #if USE(BACKTRACE_SYMBOLS) | |
| 281 char** symbols = backtrace_symbols(stack, size); | |
| 282 if (!symbols) | |
| 283 return; | |
| 284 #endif | |
| 285 | |
| 286 for (int i = 0; i < size; ++i) { | |
| 287 const char* mangledName = 0; | |
| 288 char* cxaDemangled = 0; | |
| 289 #if USE(BACKTRACE_SYMBOLS) | |
| 290 mangledName = symbols[i]; | |
| 291 #elif USE(DLADDR) | |
| 292 Dl_info info; | |
| 293 if (dladdr(stack[i], &info) && info.dli_sname) | |
| 294 mangledName = info.dli_sname; | |
| 295 if (mangledName) | |
| 296 cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0); | |
| 297 #endif | |
| 298 const int frameNumber = i + 1; | |
| 299 if (mangledName || cxaDemangled) | |
| 300 printf_stderr_common("%-3d %p %s\n", frameNumber, stack[i], cxaDeman
gled ? cxaDemangled : mangledName); | |
| 301 else | |
| 302 printf_stderr_common("%-3d %p\n", frameNumber, stack[i]); | |
| 303 free(cxaDemangled); | |
| 304 } | |
| 305 | |
| 306 #if USE(BACKTRACE_SYMBOLS) | |
| 307 free(symbols); | |
| 308 #endif | |
| 309 } | |
| 310 | |
| 311 #undef WTF_USE_BACKTRACE_SYMBOLS | |
| 312 #undef WTF_USE_DLADDR | |
| 313 | |
| 314 static WTFCrashHookFunction globalHook = 0; | |
| 315 | |
| 316 void WTFSetCrashHook(WTFCrashHookFunction function) | |
| 317 { | |
| 318 globalHook = function; | |
| 319 } | |
| 320 | |
| 321 void WTFInvokeCrashHook() | |
| 322 { | |
| 323 if (globalHook) | |
| 324 globalHook(); | |
| 325 } | |
| 326 | |
| 327 #if HAVE(SIGNAL_H) | |
| 328 static NO_RETURN void dumpBacktraceSignalHandler(int sig) | |
| 329 { | |
| 330 WTFReportBacktrace(); | |
| 331 exit(128 + sig); | |
| 332 } | |
| 333 | |
| 334 static void installSignalHandlersForFatalErrors(void (*handler)(int)) | |
| 335 { | |
| 336 signal(SIGILL, handler); // 4: illegal instruction (not reset when caught
). | |
| 337 signal(SIGTRAP, handler); // 5: trace trap (not reset when caught). | |
| 338 signal(SIGFPE, handler); // 8: floating point exception. | |
| 339 signal(SIGBUS, handler); // 10: bus error. | |
| 340 signal(SIGSEGV, handler); // 11: segmentation violation. | |
| 341 signal(SIGSYS, handler); // 12: bad argument to system call. | |
| 342 signal(SIGPIPE, handler); // 13: write on a pipe with no reader. | |
| 343 signal(SIGXCPU, handler); // 24: exceeded CPU time limit. | |
| 344 signal(SIGXFSZ, handler); // 25: exceeded file size limit. | |
| 345 } | |
| 346 | |
| 347 static void resetSignalHandlersForFatalErrors() | |
| 348 { | |
| 349 installSignalHandlersForFatalErrors(SIG_DFL); | |
| 350 } | |
| 351 #endif | |
| 352 | |
| 353 void WTFInstallReportBacktraceOnCrashHook() | |
| 354 { | |
| 355 #if HAVE(SIGNAL_H) | |
| 356 // Needed otherwise we are going to dump the stack trace twice | |
| 357 // in case we hit an assertion. | |
| 358 WTFSetCrashHook(&resetSignalHandlersForFatalErrors); | |
| 359 installSignalHandlersForFatalErrors(&dumpBacktraceSignalHandler); | |
| 360 #endif | |
| 361 } | |
| 362 | |
| 363 void WTFReportFatalError(const char* file, int line, const char* function, const
char* format, ...) | |
| 364 { | |
| 365 va_list args; | |
| 366 va_start(args, format); | |
| 367 vprintf_stderr_with_prefix("FATAL ERROR: ", format, args); | |
| 368 va_end(args); | |
| 369 printf_stderr_common("\n"); | |
| 370 printCallSite(file, line, function); | |
| 371 } | |
| 372 | |
| 373 void WTFReportError(const char* file, int line, const char* function, const char
* format, ...) | |
| 374 { | |
| 375 va_list args; | |
| 376 va_start(args, format); | |
| 377 vprintf_stderr_with_prefix("ERROR: ", format, args); | |
| 378 va_end(args); | |
| 379 printf_stderr_common("\n"); | |
| 380 printCallSite(file, line, function); | |
| 381 } | |
| 382 | |
| 383 void WTFLog(WTFLogChannel* channel, const char* format, ...) | |
| 384 { | |
| 385 if (channel->state != WTFLogChannelOn) | |
| 386 return; | |
| 387 | |
| 388 va_list args; | |
| 389 va_start(args, format); | |
| 390 vprintf_stderr_with_trailing_newline(format, args); | |
| 391 va_end(args); | |
| 392 } | |
| 393 | |
| 394 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
el* channel, const char* format, ...) | |
| 395 { | |
| 396 if (channel->state != WTFLogChannelOn) | |
| 397 return; | |
| 398 | |
| 399 va_list args; | |
| 400 va_start(args, format); | |
| 401 vprintf_stderr_with_trailing_newline(format, args); | |
| 402 va_end(args); | |
| 403 | |
| 404 printCallSite(file, line, function); | |
| 405 } | |
| 406 | |
| 407 void WTFLogAlways(const char* format, ...) | |
| 408 { | |
| 409 va_list args; | |
| 410 va_start(args, format); | |
| 411 vprintf_stderr_with_trailing_newline(format, args); | |
| 412 va_end(args); | |
| 413 } | |
| 414 | |
| 415 } // extern "C" | |
| OLD | NEW |