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