1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/* 2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * Copyright 2006 The WebRTC Project Authors. All rights reserved. 3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * 4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * Use of this source code is governed by a BSD-style license 5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * in the file PATENTS. All contributing project authors may 8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */ 10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 11a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// Most of this was borrowed (with minor modifications) from V8's and Chromium's 12a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// src/base/logging.cc. 13a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 14a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// Use the C++ version to provide __GLIBCXX__. 1534a6764981a656c62daed0d962f01374a08f9bacandrew@webrtc.org#include <cstdarg> 164ca66d691e1334231e57c069f4683d1a4d2d48f2andrew@webrtc.org#include <cstdio> 174ca66d691e1334231e57c069f4683d1a4d2d48f2andrew@webrtc.org#include <cstdlib> 18a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 19a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#if defined(__GLIBCXX__) && !defined(__UCLIBC__) 20a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#include <cxxabi.h> 21a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#include <execinfo.h> 22a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#endif 23a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 2434a6764981a656c62daed0d962f01374a08f9bacandrew@webrtc.org#if defined(WEBRTC_ANDROID) 25a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#define LOG_TAG "rtc" 26a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#include <android/log.h> // NOLINT 27a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#endif 28a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/checks.h" 30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 31a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#if defined(_MSC_VER) 32a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// Warning C4722: destructor never returns, potential memory leak. 33a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// FatalMessage's dtor very intentionally aborts. 34a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#pragma warning(disable:4722) 35a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#endif 36a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 37c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.orgnamespace rtc { 38c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org 39a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgvoid VPrintError(const char* format, va_list args) { 40a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#if defined(WEBRTC_ANDROID) 41a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args); 42a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#else 43a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org vfprintf(stderr, format, args); 44a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#endif 45a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org} 46a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 47a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgvoid PrintError(const char* format, ...) { 48a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org va_list args; 49a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org va_start(args, format); 50a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org VPrintError(format, args); 51a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org va_end(args); 52a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org} 53a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 54a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// TODO(ajm): This works on Mac (although the parsing fails) but I don't seem 55a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// to get usable symbols on Linux. This is copied from V8. Chromium has a more 56a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// advanced stace trace system; also more difficult to copy. 57a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgvoid DumpBacktrace() { 58a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#if defined(__GLIBCXX__) && !defined(__UCLIBC__) 59a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org void* trace[100]; 6034a6764981a656c62daed0d962f01374a08f9bacandrew@webrtc.org int size = backtrace(trace, sizeof(trace) / sizeof(*trace)); 61a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org char** symbols = backtrace_symbols(trace, size); 62a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError("\n==== C stack trace ===============================\n\n"); 63a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org if (size == 0) { 64a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError("(empty)\n"); 65a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org } else if (symbols == NULL) { 66a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError("(no symbols)\n"); 67a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org } else { 68a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org for (int i = 1; i < size; ++i) { 69a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org char mangled[201]; 70a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT 71a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError("%2d: ", i); 72a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org int status; 73a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org size_t length; 74a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status); 75a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError("%s\n", demangled != NULL ? demangled : mangled); 76a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org free(demangled); 77a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org } else { 78a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org // If parsing failed, at least print the unparsed symbol. 79a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError("%s\n", symbols[i]); 80a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org } 81a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org } 82a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org } 83a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org free(symbols); 84a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#endif 85a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org} 86a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 87a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgFatalMessage::FatalMessage(const char* file, int line) { 88a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org Init(file, line); 89a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org} 90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 91a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgFatalMessage::FatalMessage(const char* file, int line, std::string* result) { 92a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org Init(file, line); 93a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org stream_ << "Check failed: " << *result << std::endl << "# "; 94a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org delete result; 95a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org} 96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org 97a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgNO_RETURN FatalMessage::~FatalMessage() { 98a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org fflush(stdout); 99a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org fflush(stderr); 100a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org stream_ << std::endl << "#" << std::endl; 101a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org PrintError(stream_.str().c_str()); 102a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org DumpBacktrace(); 103a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org fflush(stderr); 104f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org abort(); 105f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} 106c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org 107a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgvoid FatalMessage::Init(const char* file, int line) { 108a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org stream_ << std::endl << std::endl << "#" << std::endl << "# Fatal error in " 109a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org << file << ", line " << line << std::endl << "# "; 110a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org} 111a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 112a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// MSVC doesn't like complex extern templates and DLLs. 113a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#if !defined(COMPILER_MSVC) 114a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org// Explicit instantiations for commonly used comparisons. 115a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgtemplate std::string* MakeCheckOpString<int, int>( 116a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org const int&, const int&, const char* names); 117a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgtemplate std::string* MakeCheckOpString<unsigned long, unsigned long>( 118a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org const unsigned long&, const unsigned long&, const char* names); 119a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgtemplate std::string* MakeCheckOpString<unsigned long, unsigned int>( 120a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org const unsigned long&, const unsigned int&, const char* names); 121a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgtemplate std::string* MakeCheckOpString<unsigned int, unsigned long>( 122a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org const unsigned int&, const unsigned long&, const char* names); 123a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.orgtemplate std::string* MakeCheckOpString<std::string, std::string>( 124a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org const std::string&, const std::string&, const char* name); 125a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org#endif 126a5b7869f3d9887d67a17f9607dcc0922c7d2b278andrew@webrtc.org 127c50bf7cbd0483806c50a848d24349a79939e1161henrike@webrtc.org} // namespace rtc 128