• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // debug.cpp: Debugging utilities.
8 
9 #include "common/debug.h"
10 
11 #include <stdarg.h>
12 
13 #include <array>
14 #include <cstdio>
15 #include <fstream>
16 #include <mutex>
17 #include <ostream>
18 #include <vector>
19 
20 #if defined(ANGLE_PLATFORM_ANDROID)
21 #    include <android/log.h>
22 #endif
23 
24 #include "anglebase/no_destructor.h"
25 #include "common/Optional.h"
26 #include "common/angleutils.h"
27 #include "common/system_utils.h"
28 
29 namespace gl
30 {
31 
32 namespace
33 {
34 
35 DebugAnnotator *g_debugAnnotator = nullptr;
36 
37 std::mutex *g_debugMutex = nullptr;
38 
39 constexpr std::array<const char *, LOG_NUM_SEVERITIES> g_logSeverityNames = {
40     {"EVENT", "INFO", "WARN", "ERR", "FATAL"}};
41 
LogSeverityName(int severity)42 constexpr const char *LogSeverityName(int severity)
43 {
44     return (severity >= 0 && severity < LOG_NUM_SEVERITIES) ? g_logSeverityNames[severity]
45                                                             : "UNKNOWN";
46 }
47 
ShouldCreateLogMessage(LogSeverity severity)48 bool ShouldCreateLogMessage(LogSeverity severity)
49 {
50 #if defined(ANGLE_TRACE_ENABLED)
51     return true;
52 #elif defined(ANGLE_ENABLE_ASSERTS)
53     return severity != LOG_EVENT;
54 #else
55     return false;
56 #endif
57 }
58 
59 }  // namespace
60 
61 namespace priv
62 {
63 
ShouldCreatePlatformLogMessage(LogSeverity severity)64 bool ShouldCreatePlatformLogMessage(LogSeverity severity)
65 {
66 #if defined(ANGLE_TRACE_ENABLED)
67     return true;
68 #else
69     return severity != LOG_EVENT;
70 #endif
71 }
72 
73 // This is never instantiated, it's just used for EAT_STREAM_PARAMETERS to an object of the correct
74 // type on the LHS of the unused part of the ternary operator.
75 std::ostream *gSwallowStream;
76 }  // namespace priv
77 
DebugAnnotationsActive()78 bool DebugAnnotationsActive()
79 {
80 #if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
81     return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
82 #else
83     return false;
84 #endif
85 }
86 
DebugAnnotationsInitialized()87 bool DebugAnnotationsInitialized()
88 {
89     return g_debugAnnotator != nullptr;
90 }
91 
InitializeDebugAnnotations(DebugAnnotator * debugAnnotator)92 void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
93 {
94     UninitializeDebugAnnotations();
95     g_debugAnnotator = debugAnnotator;
96 }
97 
UninitializeDebugAnnotations()98 void UninitializeDebugAnnotations()
99 {
100     // Pointer is not managed.
101     g_debugAnnotator = nullptr;
102 }
103 
InitializeDebugMutexIfNeeded()104 void InitializeDebugMutexIfNeeded()
105 {
106     if (g_debugMutex == nullptr)
107     {
108         g_debugMutex = new std::mutex();
109     }
110 }
111 
ScopedPerfEventHelper(const char * format,...)112 ScopedPerfEventHelper::ScopedPerfEventHelper(const char *format, ...) : mFunctionName(nullptr)
113 {
114     bool dbgTrace = DebugAnnotationsActive();
115 #if !defined(ANGLE_ENABLE_DEBUG_TRACE)
116     if (!dbgTrace)
117     {
118         return;
119     }
120 #endif  // !ANGLE_ENABLE_DEBUG_TRACE
121 
122     va_list vararg;
123     va_start(vararg, format);
124     std::vector<char> buffer(512);
125     size_t len = FormatStringIntoVector(format, vararg, buffer);
126     ANGLE_LOG(EVENT) << std::string(&buffer[0], len);
127     // Pull function name from variable args
128     mFunctionName = va_arg(vararg, const char *);
129     va_end(vararg);
130     if (dbgTrace)
131     {
132         g_debugAnnotator->beginEvent(mFunctionName, buffer.data());
133     }
134 }
135 
~ScopedPerfEventHelper()136 ScopedPerfEventHelper::~ScopedPerfEventHelper()
137 {
138     if (DebugAnnotationsActive())
139     {
140         g_debugAnnotator->endEvent(mFunctionName);
141     }
142 }
143 
LogMessage(const char * function,int line,LogSeverity severity)144 LogMessage::LogMessage(const char *function, int line, LogSeverity severity)
145     : mFunction(function), mLine(line), mSeverity(severity)
146 {
147     // EVENT() does not require additional function(line) info.
148     if (mSeverity != LOG_EVENT)
149     {
150         mStream << mFunction << "(" << mLine << "): ";
151     }
152 }
153 
~LogMessage()154 LogMessage::~LogMessage()
155 {
156     std::unique_lock<std::mutex> lock;
157     if (g_debugMutex != nullptr)
158     {
159         lock = std::unique_lock<std::mutex>(*g_debugMutex);
160     }
161 
162     if (DebugAnnotationsInitialized() && (mSeverity >= LOG_INFO))
163     {
164         g_debugAnnotator->logMessage(*this);
165     }
166     else
167     {
168         Trace(getSeverity(), getMessage().c_str());
169     }
170 
171     if (mSeverity == LOG_FATAL)
172     {
173         if (angle::IsDebuggerAttached())
174         {
175             angle::BreakDebugger();
176         }
177         else
178         {
179             ANGLE_CRASH();
180         }
181     }
182 }
183 
Trace(LogSeverity severity,const char * message)184 void Trace(LogSeverity severity, const char *message)
185 {
186     if (!ShouldCreateLogMessage(severity))
187     {
188         return;
189     }
190 
191     std::string str(message);
192 
193     if (DebugAnnotationsActive())
194     {
195 
196         switch (severity)
197         {
198             case LOG_EVENT:
199                 // Debugging logging done in ScopedPerfEventHelper
200                 break;
201             default:
202                 g_debugAnnotator->setMarker(message);
203                 break;
204         }
205     }
206 
207     if (severity == LOG_FATAL || severity == LOG_ERR || severity == LOG_WARN ||
208         severity == LOG_INFO)
209     {
210 #if defined(ANGLE_PLATFORM_ANDROID)
211         android_LogPriority android_priority = ANDROID_LOG_ERROR;
212         switch (severity)
213         {
214             case LOG_INFO:
215                 android_priority = ANDROID_LOG_INFO;
216                 break;
217             case LOG_WARN:
218                 android_priority = ANDROID_LOG_WARN;
219                 break;
220             case LOG_ERR:
221                 android_priority = ANDROID_LOG_ERROR;
222                 break;
223             case LOG_FATAL:
224                 android_priority = ANDROID_LOG_FATAL;
225                 break;
226             default:
227                 UNREACHABLE();
228         }
229         __android_log_print(android_priority, "ANGLE", "%s: %s\n", LogSeverityName(severity),
230                             str.c_str());
231 #else
232         // Note: we use fprintf because <iostream> includes static initializers.
233         fprintf((severity >= LOG_ERR) ? stderr : stdout, "%s: %s\n", LogSeverityName(severity),
234                 str.c_str());
235 #endif
236     }
237 
238 #if defined(ANGLE_PLATFORM_WINDOWS) && \
239     (defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER) || !defined(NDEBUG))
240 #    if !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
241     if (severity >= LOG_ERR)
242 #    endif  // !defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
243     {
244         OutputDebugStringA(str.c_str());
245     }
246 #endif
247 
248 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
249 #    if defined(NDEBUG)
250     if (severity == LOG_EVENT || severity == LOG_WARN || severity == LOG_INFO)
251     {
252         return;
253     }
254 #    endif  // defined(NDEBUG)
255     static angle::base::NoDestructor<std::ofstream> file(TRACE_OUTPUT_FILE, std::ofstream::app);
256     if (file->good())
257     {
258         *file << LogSeverityName(severity) << ": " << str << std::endl;
259         file->flush();
260     }
261 #endif  // defined(ANGLE_ENABLE_DEBUG_TRACE)
262 }
263 
getSeverity() const264 LogSeverity LogMessage::getSeverity() const
265 {
266     return mSeverity;
267 }
268 
getMessage() const269 std::string LogMessage::getMessage() const
270 {
271     return mStream.str();
272 }
273 
274 #if defined(ANGLE_PLATFORM_WINDOWS)
FmtHR(HRESULT value)275 priv::FmtHexHelper<HRESULT> FmtHR(HRESULT value)
276 {
277     return priv::FmtHexHelper<HRESULT>("HRESULT: ", value);
278 }
279 
FmtErr(DWORD value)280 priv::FmtHexHelper<DWORD> FmtErr(DWORD value)
281 {
282     return priv::FmtHexHelper<DWORD>("error: ", value);
283 }
284 #endif  // defined(ANGLE_PLATFORM_WINDOWS)
285 
286 }  // namespace gl
287