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 
37 namespace rtc {
38 
VPrintError(const char * format,va_list args)39 void 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 
PrintError(const char * format,...)47 void 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.
DumpBacktrace()57 void 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 
FatalMessage(const char * file,int line)87 FatalMessage::FatalMessage(const char* file, int line) {
88   Init(file, line);
89 }
90 
FatalMessage(const char * file,int line,std::string * result)91 FatalMessage::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 
~FatalMessage()97 NO_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 
Init(const char * file,int line)107 void 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 // MSVC doesn't like complex extern templates and DLLs.
113 #if !defined(COMPILER_MSVC)
114 // Explicit instantiations for commonly used comparisons.
115 template std::string* MakeCheckOpString<int, int>(
116     const int&, const int&, const char* names);
117 template std::string* MakeCheckOpString<unsigned long, unsigned long>(
118     const unsigned long&, const unsigned long&, const char* names);
119 template std::string* MakeCheckOpString<unsigned long, unsigned int>(
120     const unsigned long&, const unsigned int&, const char* names);
121 template std::string* MakeCheckOpString<unsigned int, unsigned long>(
122     const unsigned int&, const unsigned long&, const char* names);
123 template std::string* MakeCheckOpString<std::string, std::string>(
124     const std::string&, const std::string&, const char* name);
125 #endif
126 
127 }  // namespace rtc
128