1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
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 
17 #if __ANDROID__
18 #	include <android/log.h>
19 #endif
20 
21 #if defined(__unix__)
22 #	define PTRACE
23 #	include <sys/ptrace.h>
24 #	include <sys/types.h>
25 #elif defined(_WIN32) || defined(_WIN64)
26 #	include <windows.h>
27 #elif defined(__APPLE__) || defined(__MACH__)
28 #	include <sys/sysctl.h>
29 #	include <unistd.h>
30 #endif
31 
32 #include <atomic>
33 #include <cstdarg>
34 #include <cstdio>
35 #include <string>
36 
37 #ifdef ERROR
38 #	undef ERROR  // b/127920555
39 #endif
40 
41 #ifndef SWIFTSHADER_LOGGING_LEVEL
42 #	define SWIFTSHADER_LOGGING_LEVEL Info
43 #endif
44 
45 namespace {
46 
IsUnderDebugger()47 bool IsUnderDebugger()
48 {
49 #if defined(PTRACE) && !defined(__APPLE__) && !defined(__MACH__)
50 	static bool checked = false;
51 	static bool res = false;
52 
53 	if(!checked)
54 	{
55 		// 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 		}
66 	}
67 
68 	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 
99 enum class Level
100 {
101 	Verbose,
102 	Debug,
103 	Info,
104 	Warn,
105 	Error,
106 	Fatal,
107 	Disabled,
108 };
109 
110 #ifdef __ANDROID__
logv_android(Level level,const char * msg)111 void logv_android(Level level, const char *msg)
112 {
113 	switch(level)
114 	{
115 		case Level::Debug:
116 			__android_log_write(ANDROID_LOG_DEBUG, "SwiftShader", msg);
117 			break;
118 		case Level::Info:
119 			__android_log_write(ANDROID_LOG_INFO, "SwiftShader", msg);
120 			break;
121 		case Level::Warn:
122 			__android_log_write(ANDROID_LOG_WARN, "SwiftShader", msg);
123 			break;
124 		case Level::Error:
125 			__android_log_write(ANDROID_LOG_ERROR, "SwiftShader", msg);
126 			break;
127 		case Level::Fatal:
128 			__android_log_write(ANDROID_LOG_FATAL, "SwiftShader", msg);
129 			break;
130 		default:
131 			break;
132 	}
133 }
134 #else
logv_std(Level level,const char * msg)135 void logv_std(Level level, const char *msg)
136 {
137 	switch(level)
138 	{
139 		case Level::Debug:
140 		case Level::Info:
141 			fprintf(stdout, "%s", msg);
142 			break;
143 		case Level::Warn:
144 		case Level::Error:
145 		case Level::Fatal:
146 			fprintf(stderr, "%s", msg);
147 			break;
148 		default:
149 			break;
150 	}
151 }
152 #endif
153 
logv(Level level,const char * format,va_list args)154 void logv(Level level, const char *format, va_list args)
155 {
156 	if(static_cast<int>(level) >= static_cast<int>(Level::SWIFTSHADER_LOGGING_LEVEL))
157 	{
158 #ifndef SWIFTSHADER_DISABLE_TRACE
159 		char buffer[2048];
160 		vsnprintf(buffer, sizeof(buffer), format, args);
161 
162 #	if defined(__ANDROID__)
163 		logv_android(level, buffer);
164 #	elif defined(_WIN32)
165 		logv_std(level, buffer);
166 		::OutputDebugString(buffer);
167 #	else
168 		logv_std(level, buffer);
169 #	endif
170 	}
171 
172 	const Level traceToFileLevel = Level::Disabled;
173 	if(static_cast<int>(level) >= static_cast<int>(traceToFileLevel))
174 	{
175 		FILE *file = fopen(TRACE_OUTPUT_FILE, "a");
176 
177 		if(file)
178 		{
179 			vfprintf(file, format, args);
180 			fclose(file);
181 		}
182 	}
183 #endif  // SWIFTSHADER_DISABLE_TRACE
184 }
185 
186 }  // anonymous namespace
187 
188 namespace sw {
189 
trace(const char * format,...)190 void trace(const char *format, ...)
191 {
192 	va_list vararg;
193 	va_start(vararg, format);
194 	logv(Level::Debug, format, vararg);
195 	va_end(vararg);
196 }
197 
warn(const char * format,...)198 void warn(const char *format, ...)
199 {
200 	va_list vararg;
201 	va_start(vararg, format);
202 	logv(Level::Warn, format, vararg);
203 	va_end(vararg);
204 }
205 
abort(const char * format,...)206 void abort(const char *format, ...)
207 {
208 	va_list vararg;
209 
210 	va_start(vararg, format);
211 	logv(Level::Fatal, format, vararg);
212 	va_end(vararg);
213 
214 	::abort();
215 }
216 
log_trap(const char * format,...)217 void log_trap(const char *format, ...)
218 {
219 	// If enabled, log_assert will log all messages, and otherwise ignore them
220 	// unless a debugger is attached.
221 	static std::atomic<bool> asserted = { false };
222 	if(IsUnderDebugger() && !asserted.exchange(true) && static_cast<int>(Level::Debug) >= static_cast<int>(Level::SWIFTSHADER_LOGGING_LEVEL))
223 	{
224 		// If a developer wants to be aware of what's happening,
225 		// then we abort after tracing and printing to stderr
226 		va_list vararg;
227 		va_start(vararg, format);
228 		logv(Level::Fatal, format, vararg);
229 		va_end(vararg);
230 
231 		::abort();
232 	}
233 	else if(!asserted)
234 	{
235 		va_list vararg;
236 		va_start(vararg, format);
237 		logv(Level::Verbose, format, vararg);
238 		va_end(vararg);
239 	}
240 }
241 
242 }  // namespace sw
243