blob: 5b100368a50aaa56c5deea52b91f8c970966b12c [file] [log] [blame]
Ben Claytonce54c592020-02-07 11:30:51 +00001// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
Nicolas Capensc07dc4b2018-08-06 14:20:45 -04002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Debug.hpp"
16
Ben Claytonce54c592020-02-07 11:30:51 +000017#include <atomic>
Antonio Maioranof47a73a2019-12-13 16:21:01 -050018#include <cstdarg>
19#include <cstdio>
Ben Clayton713b8d32019-12-17 20:37:56 +000020#include <string>
Nicolas Capensc07dc4b2018-08-06 14:20:45 -040021
Ben Claytonce54c592020-02-07 11:30:51 +000022#if __ANDROID__
23# include <android/log.h>
Antonio Maioranof47a73a2019-12-13 16:21:01 -050024#endif
25
Ben Claytonce54c592020-02-07 11:30:51 +000026#if defined(__unix__)
27# define PTRACE
28# include <sys/ptrace.h>
29# include <sys/types.h>
30#elif defined(_WIN32) || defined(_WIN64)
31# include <windows.h>
32#elif defined(__APPLE__) || defined(__MACH__)
33# include <sys/sysctl.h>
34# include <unistd.h>
35#endif
Ben Claytoneb50d252019-04-15 13:50:01 -040036
Ben Claytonce54c592020-02-07 11:30:51 +000037#ifdef ERROR
38# undef ERROR // b/127920555
39#endif
40
41#ifndef REACTOR_LOGGING_LEVEL
42# define REACTOR_LOGGING_LEVEL INFO
43#endif
44
45namespace {
46
47bool IsUnderDebugger()
Nicolas Capensc07dc4b2018-08-06 14:20:45 -040048{
Ben Claytonce54c592020-02-07 11:30:51 +000049#if defined(PTRACE) && !defined(__APPLE__) && !defined(__MACH__)
50 static bool checked = false;
51 static bool res = false;
Antonio Maioranof47a73a2019-12-13 16:21:01 -050052
Ben Claytonce54c592020-02-07 11:30:51 +000053 if(!checked)
Antonio Maioranof47a73a2019-12-13 16:21:01 -050054 {
Ben Claytonce54c592020-02-07 11:30:51 +000055 // If a debugger is attached then we're already being ptraced and ptrace
56 // will return a non-zero value.
57 checked = true;
58 if(ptrace(PTRACE_TRACEME, 0, 1, 0) != 0)
59 {
60 res = true;
61 }
62 else
63 {
64 ptrace(PTRACE_DETACH, 0, 1, 0);
65 }
Antonio Maioranof47a73a2019-12-13 16:21:01 -050066 }
67
Ben Claytonce54c592020-02-07 11:30:51 +000068 return res;
69#elif defined(_WIN32) || defined(_WIN64)
70 return IsDebuggerPresent() != 0;
71#elif defined(__APPLE__) || defined(__MACH__)
72 // Code comes from the Apple Technical Q&A QA1361
73
74 // Tell sysctl what info we're requestion. Specifically we're asking for
75 // info about this our PID.
76 int res = 0;
77 int request[4] = {
78 CTL_KERN,
79 KERN_PROC,
80 KERN_PROC_PID,
81 getpid()
82 };
83 struct kinfo_proc info;
84 size_t size = sizeof(info);
85
86 info.kp_proc.p_flag = 0;
87
88 // Get the info we're requesting, if sysctl fails then info.kp_proc.p_flag will remain 0.
89 res = sysctl(request, sizeof(request) / sizeof(*request), &info, &size, NULL, 0);
90 ASSERT_MSG(res == 0, "syscl returned %d", res);
91
92 // We're being debugged if the P_TRACED flag is set
93 return ((info.kp_proc.p_flag & P_TRACED) != 0);
94#else
95 return false;
96#endif
97}
98
99enum class Level
100{
101 DEBUG,
102 INFO,
103 WARN,
104 ERROR,
105 FATAL,
106};
107
108#ifdef __ANDROID__
109void logv_android(Level level, const char *msg)
110{
111 switch(level)
112 {
113 case Level::DEBUG:
114 __android_log_write(ANDROID_LOG_DEBUG, "SwiftShader", msg);
115 break;
116 case Level::INFO:
117 __android_log_write(ANDROID_LOG_INFO, "SwiftShader", msg);
118 break;
119 case Level::WARN:
120 __android_log_write(ANDROID_LOG_WARN, "SwiftShader", msg);
121 break;
122 case Level::ERROR:
123 __android_log_write(ANDROID_LOG_ERROR, "SwiftShader", msg);
124 break;
125 case Level::FATAL:
126 __android_log_write(ANDROID_LOG_FATAL, "SwiftShader", msg);
127 break;
128 }
129}
130#else
131void logv_std(Level level, const char *msg)
132{
133 switch(level)
134 {
135 case Level::DEBUG:
136 case Level::INFO:
137 fprintf(stdout, "%s", msg);
138 break;
139 case Level::WARN:
140 case Level::ERROR:
141 case Level::FATAL:
142 fprintf(stderr, "%s", msg);
143 break;
144 }
145}
146#endif
147
148void logv(Level level, const char *format, va_list args)
149{
150 if(static_cast<int>(level) < static_cast<int>(Level::REACTOR_LOGGING_LEVEL))
151 {
152 return;
153 }
154
155#ifndef SWIFTSHADER_DISABLE_TRACE
156 char buffer[2048];
157 vsnprintf(buffer, sizeof(buffer), format, args);
158
159# if defined(__ANDROID__)
160 logv_android(level, buffer);
161# elif defined(_WIN32)
162 logv_std(level, buffer);
163 ::OutputDebugString(buffer);
164# else
165 logv_std(level, buffer);
166# endif
167
168 const bool traceToFile = false;
Antonio Maioranof47a73a2019-12-13 16:21:01 -0500169 if(traceToFile)
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400170 {
Ben Claytoneb50d252019-04-15 13:50:01 -0400171 FILE *file = fopen(TRACE_OUTPUT_FILE, "a");
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400172
173 if(file)
174 {
Ben Claytoneb50d252019-04-15 13:50:01 -0400175 vfprintf(file, format, args);
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400176 fclose(file);
177 }
178 }
Ben Claytonce54c592020-02-07 11:30:51 +0000179#endif // SWIFTSHADER_DISABLE_TRACE
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400180}
Ben Claytoneb50d252019-04-15 13:50:01 -0400181
Ben Claytonce54c592020-02-07 11:30:51 +0000182} // anonymous namespace
183
184namespace rr {
185
Ben Claytoneb50d252019-04-15 13:50:01 -0400186void trace(const char *format, ...)
187{
188 va_list vararg;
189 va_start(vararg, format);
Ben Claytonce54c592020-02-07 11:30:51 +0000190 logv(Level::DEBUG, format, vararg);
Ben Claytoneb50d252019-04-15 13:50:01 -0400191 va_end(vararg);
192}
193
194void warn(const char *format, ...)
195{
196 va_list vararg;
197 va_start(vararg, format);
Ben Claytonce54c592020-02-07 11:30:51 +0000198 logv(Level::WARN, format, vararg);
Ben Claytoneb50d252019-04-15 13:50:01 -0400199 va_end(vararg);
200}
201
202void abort(const char *format, ...)
203{
204 va_list vararg;
205
206 va_start(vararg, format);
Ben Claytonce54c592020-02-07 11:30:51 +0000207 logv(Level::FATAL, format, vararg);
Ben Claytoneb50d252019-04-15 13:50:01 -0400208 va_end(vararg);
209
210 ::abort();
211}
212
Ben Claytonce54c592020-02-07 11:30:51 +0000213void trace_assert(const char *format, ...)
214{
215 static std::atomic<bool> asserted = { false };
216 if(IsUnderDebugger() && !asserted.exchange(true))
217 {
218 // Abort after tracing and printing to stderr
219 va_list vararg;
220 va_start(vararg, format);
221 logv(Level::FATAL, format, vararg);
222 va_end(vararg);
223
224 ::abort();
225 }
226 else if(!asserted)
227 {
228 va_list vararg;
229 va_start(vararg, format);
230 logv(Level::FATAL, format, vararg);
231 va_end(vararg);
232 }
233}
234
Nicolas Capens157ba262019-12-10 17:49:14 -0500235} // namespace rr