xref: /aosp_15_r20/external/swiftshader/src/Reactor/Debug.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 #include <atomic>
18 #include <cstdarg>
19 #include <cstdio>
20 #include <string>
21 
22 #if __ANDROID__
23 #	include <android/log.h>
24 #endif
25 
26 #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
36 
37 #ifdef ERROR
38 #	undef ERROR  // b/127920555
39 #endif
40 
41 #ifndef REACTOR_LOGGING_LEVEL
42 #	define REACTOR_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 	Debug,
102 	Info,
103 	Warn,
104 	Error,
105 	Fatal,
106 };
107 
108 #ifdef __ANDROID__
logv_android(Level level,const char * msg)109 [[maybe_unused]] void 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
logv_std(Level level,const char * msg)131 [[maybe_unused]] void 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 
logv(Level level,const char * format,va_list args)148 void 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;
169 	if(traceToFile)
170 	{
171 		FILE *file = fopen(TRACE_OUTPUT_FILE, "a");
172 
173 		if(file)
174 		{
175 			vfprintf(file, format, args);
176 			fclose(file);
177 		}
178 	}
179 #endif  // SWIFTSHADER_DISABLE_TRACE
180 }
181 
182 }  // anonymous namespace
183 
184 namespace rr {
185 
trace(const char * format,...)186 void trace(const char *format, ...)
187 {
188 	va_list vararg;
189 	va_start(vararg, format);
190 	logv(Level::Debug, format, vararg);
191 	va_end(vararg);
192 }
193 
warn(const char * format,...)194 void warn(const char *format, ...)
195 {
196 	va_list vararg;
197 	va_start(vararg, format);
198 	logv(Level::Warn, format, vararg);
199 	va_end(vararg);
200 }
201 
abort(const char * format,...)202 void abort(const char *format, ...)
203 {
204 	va_list vararg;
205 
206 	va_start(vararg, format);
207 	logv(Level::Fatal, format, vararg);
208 	va_end(vararg);
209 
210 	::abort();
211 }
212 
trace_assert(const char * format,...)213 void 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 
235 }  // namespace rr
236