1 /* 2 * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2007-2009 Torch Mobile, Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 // The vprintf_stderr_common function triggers this error in the Mac build. 28 // Feel free to remove this pragma if this file builds on Mac. 29 // According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas 30 // we need to place this directive before any data or functions are defined. 31 #pragma GCC diagnostic ignored "-Wmissing-format-attribute" 32 33 #include "config.h" 34 #include "Assertions.h" 35 36 #include <stdio.h> 37 #include <stdarg.h> 38 #include <string.h> 39 40 #if PLATFORM(MAC) 41 #include <CoreFoundation/CFString.h> 42 #endif 43 44 #if COMPILER(MSVC) && !OS(WINCE) && !PLATFORM(BREWMP) 45 #ifndef WINVER 46 #define WINVER 0x0500 47 #endif 48 #ifndef _WIN32_WINNT 49 #define _WIN32_WINNT 0x0500 50 #endif 51 #include <crtdbg.h> 52 #endif 53 54 #if OS(WINDOWS) 55 #include <windows.h> 56 #endif 57 58 #if PLATFORM(BREWMP) 59 #include <AEEdbg.h> 60 #include <wtf/Vector.h> 61 #endif 62 63 #if PLATFORM(MAC) 64 #include <cxxabi.h> 65 #include <dlfcn.h> 66 #include <execinfo.h> 67 #endif 68 69 #if OS(ANDROID) 70 #include <utils/Log.h> 71 #endif 72 73 extern "C" { 74 75 #if PLATFORM(BREWMP) 76 77 static void printLog(const Vector<char>& buffer) 78 { 79 // Each call to DBGPRINTF generates at most 128 bytes of output on the Windows SDK. 80 // On Qualcomm chipset targets, DBGPRINTF() comes out the diag port (though this may change). 81 // The length of each output string is constrained even more than on the Windows SDK. 82 #if COMPILER(MSVC) 83 const int printBufferSize = 128; 84 #else 85 const int printBufferSize = 32; 86 #endif 87 88 char printBuffer[printBufferSize + 1]; 89 printBuffer[printBufferSize] = 0; // to guarantee null termination 90 91 const char* p = buffer.data(); 92 const char* end = buffer.data() + buffer.size(); 93 while (p < end) { 94 strncpy(printBuffer, p, printBufferSize); 95 dbg_Message(printBuffer, DBG_MSG_LEVEL_HIGH, __FILE__, __LINE__); 96 p += printBufferSize; 97 } 98 } 99 100 #endif 101 102 WTF_ATTRIBUTE_PRINTF(1, 0) 103 static void vprintf_stderr_common(const char* format, va_list args) 104 { 105 #if PLATFORM(MAC) 106 if (strstr(format, "%@")) { 107 CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); 108 CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args); 109 110 int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); 111 char* buffer = (char*)malloc(length + 1); 112 113 CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8); 114 115 fputs(buffer, stderr); 116 117 free(buffer); 118 CFRelease(str); 119 CFRelease(cfFormat); 120 return; 121 } 122 #elif PLATFORM(BREWMP) 123 // When str is 0, the return value is the number of bytes needed 124 // to accept the result including null termination. 125 int size = vsnprintf(0, 0, format, args); 126 if (size > 0) { 127 Vector<char> buffer(size); 128 vsnprintf(buffer.data(), size, format, args); 129 printLog(buffer); 130 } 131 #elif OS(ANDROID) 132 LOG_PRI_VA(ANDROID_LOG_DEBUG, "WebKit", format, args); 133 return; 134 #elif HAVE(ISDEBUGGERPRESENT) 135 if (IsDebuggerPresent()) { 136 size_t size = 1024; 137 138 do { 139 char* buffer = (char*)malloc(size); 140 141 if (buffer == NULL) 142 break; 143 144 if (_vsnprintf(buffer, size, format, args) != -1) { 145 #if OS(WINCE) 146 // WinCE only supports wide chars 147 wchar_t* wideBuffer = (wchar_t*)malloc(size * sizeof(wchar_t)); 148 if (wideBuffer == NULL) 149 break; 150 for (unsigned int i = 0; i < size; ++i) { 151 if (!(wideBuffer[i] = buffer[i])) 152 break; 153 } 154 OutputDebugStringW(wideBuffer); 155 free(wideBuffer); 156 #else 157 OutputDebugStringA(buffer); 158 #endif 159 free(buffer); 160 break; 161 } 162 163 free(buffer); 164 size *= 2; 165 } while (size > 1024); 166 } 167 #endif 168 #if OS(SYMBIAN) 169 vfprintf(stdout, format, args); 170 #else 171 vfprintf(stderr, format, args); 172 #endif 173 } 174 175 WTF_ATTRIBUTE_PRINTF(1, 2) 176 static void printf_stderr_common(const char* format, ...) 177 { 178 va_list args; 179 va_start(args, format); 180 vprintf_stderr_common(format, args); 181 va_end(args); 182 } 183 184 static void printCallSite(const char* file, int line, const char* function) 185 { 186 #if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG) 187 _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function); 188 #else 189 // By using this format, which matches the format used by MSVC for compiler errors, developers 190 // using Visual Studio can double-click the file/line number in the Output Window to have the 191 // editor navigate to that line of code. It seems fine for other developers, too. 192 printf_stderr_common("%s(%d) : %s\n", file, line, function); 193 #endif 194 } 195 196 void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion) 197 { 198 if (assertion) 199 printf_stderr_common("ASSERTION FAILED: %s\n", assertion); 200 else 201 printf_stderr_common("SHOULD NEVER BE REACHED\n"); 202 printCallSite(file, line, function); 203 } 204 205 void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) 206 { 207 printf_stderr_common("ASSERTION FAILED: "); 208 va_list args; 209 va_start(args, format); 210 vprintf_stderr_common(format, args); 211 va_end(args); 212 printf_stderr_common("\n%s\n", assertion); 213 printCallSite(file, line, function); 214 } 215 216 void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion) 217 { 218 printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion); 219 printCallSite(file, line, function); 220 } 221 222 void WTFReportBacktrace() 223 { 224 #if PLATFORM(MAC) 225 static const int maxFrames = 32; 226 void* samples[maxFrames]; 227 int frames = backtrace(samples, maxFrames); 228 229 for (int i = 1; i < frames; ++i) { 230 void* pointer = samples[i]; 231 232 // Try to get a symbol name from the dynamic linker. 233 Dl_info info; 234 if (dladdr(pointer, &info) && info.dli_sname) { 235 const char* mangledName = info.dli_sname; 236 237 // Assume c++ & try to demangle the name. 238 char* demangledName = abi::__cxa_demangle(mangledName, 0, 0, 0); 239 if (demangledName) { 240 fprintf(stderr, "%-3d %s\n", i, demangledName); 241 free(demangledName); 242 } else 243 fprintf(stderr, "%-3d %s\n", i, mangledName); 244 } else 245 fprintf(stderr, "%-3d %p\n", i, pointer); 246 } 247 #endif 248 } 249 250 void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) 251 { 252 printf_stderr_common("FATAL ERROR: "); 253 va_list args; 254 va_start(args, format); 255 vprintf_stderr_common(format, args); 256 va_end(args); 257 printf_stderr_common("\n"); 258 printCallSite(file, line, function); 259 } 260 261 void WTFReportError(const char* file, int line, const char* function, const char* format, ...) 262 { 263 printf_stderr_common("ERROR: "); 264 va_list args; 265 va_start(args, format); 266 vprintf_stderr_common(format, args); 267 va_end(args); 268 printf_stderr_common("\n"); 269 printCallSite(file, line, function); 270 } 271 272 void WTFLog(WTFLogChannel* channel, const char* format, ...) 273 { 274 if (channel->state != WTFLogChannelOn) 275 return; 276 277 va_list args; 278 va_start(args, format); 279 vprintf_stderr_common(format, args); 280 va_end(args); 281 if (format[strlen(format) - 1] != '\n') 282 printf_stderr_common("\n"); 283 } 284 285 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) 286 { 287 if (channel->state != WTFLogChannelOn) 288 return; 289 290 va_list args; 291 va_start(args, format); 292 vprintf_stderr_common(format, args); 293 va_end(args); 294 if (format[strlen(format) - 1] != '\n') 295 printf_stderr_common("\n"); 296 printCallSite(file, line, function); 297 } 298 299 } // extern "C" 300