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.
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
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.
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.
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.html#Diagnostic-Pragmas
31
// we need to place this directive before any data or functions are defined.
32
#pragma GCC diagnostic ignored "-Wmissing-format-attribute"
35
#include "Assertions.h"
38
#include "OwnArrayPtr.h"
49
#include <CoreFoundation/CFString.h>
53
#if COMPILER(MSVC) && !OS(WINCE)
61
#if (OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__))) && !OS(ANDROID)
68
#include "android/log.h"
71
#if PLATFORM(BLACKBERRY)
72
#include <BlackBerryPlatformLog.h>
77
WTF_ATTRIBUTE_PRINTF(1, 0)
78
static void vprintf_stderr_common(const char* format, va_list args)
81
if (strstr(format, "%@")) {
82
CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
85
#pragma clang diagnostic push
86
#pragma clang diagnostic ignored "-Wformat-nonliteral"
88
CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args);
90
#pragma clang diagnostic pop
92
int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
93
char* buffer = (char*)malloc(length + 1);
95
CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8);
97
#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
98
asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer);
100
fputs(buffer, stderr);
108
#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
110
va_copy(copyOfArgs, args);
111
asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs);
115
// Fall through to write to stderr in the same manner as other platforms.
117
#elif PLATFORM(BLACKBERRY)
118
BBLOGV(BlackBerry::Platform::LogLevelCritical, format, args);
120
__android_log_vprint(ANDROID_LOG_WARN, "WebKit", format, args);
121
#elif HAVE(ISDEBUGGERPRESENT)
122
if (IsDebuggerPresent()) {
126
char* buffer = (char*)malloc(size);
131
if (_vsnprintf(buffer, size, format, args) != -1) {
133
// WinCE only supports wide chars
134
wchar_t* wideBuffer = (wchar_t*)malloc(size * sizeof(wchar_t));
135
if (wideBuffer == NULL)
137
for (unsigned int i = 0; i < size; ++i) {
138
if (!(wideBuffer[i] = buffer[i]))
141
OutputDebugStringW(wideBuffer);
144
OutputDebugStringA(buffer);
152
} while (size > 1024);
155
#if !PLATFORM(BLACKBERRY)
156
vfprintf(stderr, format, args);
160
#if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0))
161
#pragma GCC diagnostic push
162
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
165
static void vprintf_stderr_with_prefix(const char* prefix, const char* format, va_list args)
167
size_t prefixLength = strlen(prefix);
168
size_t formatLength = strlen(format);
169
OwnArrayPtr<char> formatWithPrefix = adoptArrayPtr(new char[prefixLength + formatLength + 1]);
170
memcpy(formatWithPrefix.get(), prefix, prefixLength);
171
memcpy(formatWithPrefix.get() + prefixLength, format, formatLength);
172
formatWithPrefix[prefixLength + formatLength] = 0;
174
vprintf_stderr_common(formatWithPrefix.get(), args);
177
static void vprintf_stderr_with_trailing_newline(const char* format, va_list args)
179
size_t formatLength = strlen(format);
180
if (formatLength && format[formatLength - 1] == '\n') {
181
vprintf_stderr_common(format, args);
185
OwnArrayPtr<char> formatWithNewline = adoptArrayPtr(new char[formatLength + 2]);
186
memcpy(formatWithNewline.get(), format, formatLength);
187
formatWithNewline[formatLength] = '\n';
188
formatWithNewline[formatLength + 1] = 0;
190
vprintf_stderr_common(formatWithNewline.get(), args);
193
#if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0))
194
#pragma GCC diagnostic pop
197
WTF_ATTRIBUTE_PRINTF(1, 2)
198
static void printf_stderr_common(const char* format, ...)
201
va_start(args, format);
202
vprintf_stderr_common(format, args);
206
static void printCallSite(const char* file, int line, const char* function)
208
#if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG)
209
_CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
211
// By using this format, which matches the format used by MSVC for compiler errors, developers
212
// using Visual Studio can double-click the file/line number in the Output Window to have the
213
// editor navigate to that line of code. It seems fine for other developers, too.
214
printf_stderr_common("%s(%d) : %s\n", file, line, function);
218
void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion)
221
printf_stderr_common("ASSERTION FAILED: %s\n", assertion);
223
printf_stderr_common("SHOULD NEVER BE REACHED\n");
224
printCallSite(file, line, function);
227
void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...)
230
va_start(args, format);
231
vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args);
233
printf_stderr_common("\n%s\n", assertion);
234
printCallSite(file, line, function);
237
void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion)
239
printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion);
240
printCallSite(file, line, function);
243
void WTFGetBacktrace(void** stack, int* size)
245
#if (OS(DARWIN) || (OS(LINUX) && !defined(__UCLIBC__))) && !OS(ANDROID)
246
*size = backtrace(stack, *size);
247
#elif OS(WINDOWS) && !OS(WINCE)
248
// The CaptureStackBackTrace function is available in XP, but it is not defined
249
// in the Windows Server 2003 R2 Platform SDK. So, we'll grab the function
250
// through GetProcAddress.
251
typedef WORD (NTAPI* RtlCaptureStackBackTraceFunc)(DWORD, DWORD, PVOID*, PDWORD);
252
HMODULE kernel32 = ::GetModuleHandleW(L"Kernel32.dll");
257
RtlCaptureStackBackTraceFunc captureStackBackTraceFunc = reinterpret_cast<RtlCaptureStackBackTraceFunc>(
258
::GetProcAddress(kernel32, "RtlCaptureStackBackTrace"));
259
if (captureStackBackTraceFunc)
260
*size = captureStackBackTraceFunc(0, *size, stack, 0);
268
void WTFReportBacktrace()
270
static const int framesToShow = 31;
271
static const int framesToSkip = 2;
272
void* samples[framesToShow + framesToSkip];
273
int frames = framesToShow + framesToSkip;
275
WTFGetBacktrace(samples, &frames);
276
WTFPrintBacktrace(samples + framesToSkip, frames - framesToSkip);
279
#if OS(DARWIN) || OS(LINUX)
280
# if PLATFORM(QT) || PLATFORM(GTK)
281
# if defined(__GLIBC__) && !defined(__UCLIBC__)
282
# define WTF_USE_BACKTRACE_SYMBOLS 1
285
# define WTF_USE_DLADDR 1
289
void WTFPrintBacktrace(void** stack, int size)
291
#if USE(BACKTRACE_SYMBOLS)
292
char** symbols = backtrace_symbols(stack, size);
297
for (int i = 0; i < size; ++i) {
298
const char* mangledName = 0;
299
char* cxaDemangled = 0;
300
#if USE(BACKTRACE_SYMBOLS)
301
mangledName = symbols[i];
304
if (dladdr(stack[i], &info) && info.dli_sname)
305
mangledName = info.dli_sname;
307
cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0);
309
const int frameNumber = i + 1;
310
if (mangledName || cxaDemangled)
311
printf_stderr_common("%-3d %p %s\n", frameNumber, stack[i], cxaDemangled ? cxaDemangled : mangledName);
313
printf_stderr_common("%-3d %p\n", frameNumber, stack[i]);
317
#if USE(BACKTRACE_SYMBOLS)
322
#undef WTF_USE_BACKTRACE_SYMBOLS
323
#undef WTF_USE_DLADDR
325
static WTFCrashHookFunction globalHook = 0;
327
void WTFSetCrashHook(WTFCrashHookFunction function)
329
globalHook = function;
332
void WTFInvokeCrashHook()
339
static NO_RETURN void dumpBacktraceSignalHandler(int sig)
341
WTFReportBacktrace();
345
static void installSignalHandlersForFatalErrors(void (*handler)(int))
347
signal(SIGILL, handler); // 4: illegal instruction (not reset when caught).
348
signal(SIGTRAP, handler); // 5: trace trap (not reset when caught).
349
signal(SIGFPE, handler); // 8: floating point exception.
350
signal(SIGBUS, handler); // 10: bus error.
351
signal(SIGSEGV, handler); // 11: segmentation violation.
352
signal(SIGSYS, handler); // 12: bad argument to system call.
353
signal(SIGPIPE, handler); // 13: write on a pipe with no reader.
354
signal(SIGXCPU, handler); // 24: exceeded CPU time limit.
355
signal(SIGXFSZ, handler); // 25: exceeded file size limit.
358
static void resetSignalHandlersForFatalErrors()
360
installSignalHandlersForFatalErrors(SIG_DFL);
364
void WTFInstallReportBacktraceOnCrashHook()
367
// Needed otherwise we are going to dump the stack trace twice
368
// in case we hit an assertion.
369
WTFSetCrashHook(&resetSignalHandlersForFatalErrors);
370
installSignalHandlersForFatalErrors(&dumpBacktraceSignalHandler);
374
void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
377
va_start(args, format);
378
vprintf_stderr_with_prefix("FATAL ERROR: ", format, args);
380
printf_stderr_common("\n");
381
printCallSite(file, line, function);
384
void WTFReportError(const char* file, int line, const char* function, const char* format, ...)
387
va_start(args, format);
388
vprintf_stderr_with_prefix("ERROR: ", format, args);
390
printf_stderr_common("\n");
391
printCallSite(file, line, function);
394
void WTFLog(WTFLogChannel* channel, const char* format, ...)
396
if (channel->state != WTFLogChannelOn)
400
va_start(args, format);
401
vprintf_stderr_with_trailing_newline(format, args);
405
void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
407
if (channel->state != WTFLogChannelOn)
411
va_start(args, format);
412
vprintf_stderr_with_trailing_newline(format, args);
415
printCallSite(file, line, function);
418
void WTFLogAlways(const char* format, ...)
421
va_start(args, format);
422
vprintf_stderr_with_trailing_newline(format, args);