xref: /aosp_15_r20/external/swiftshader/src/Reactor/ReactorDebugInfo.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //  http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "ReactorDebugInfo.hpp"
16*03ce13f7SAndroid Build Coastguard Worker #include "Print.hpp"
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #ifdef ENABLE_RR_DEBUG_INFO
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker #	include "boost/stacktrace.hpp"
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker #	include <algorithm>
23*03ce13f7SAndroid Build Coastguard Worker #	include <cctype>
24*03ce13f7SAndroid Build Coastguard Worker #	include <unordered_map>
25*03ce13f7SAndroid Build Coastguard Worker 
26*03ce13f7SAndroid Build Coastguard Worker namespace rr {
27*03ce13f7SAndroid Build Coastguard Worker 
28*03ce13f7SAndroid Build Coastguard Worker namespace {
to_lower(std::string str)29*03ce13f7SAndroid Build Coastguard Worker std::string to_lower(std::string str)
30*03ce13f7SAndroid Build Coastguard Worker {
31*03ce13f7SAndroid Build Coastguard Worker 	std::transform(str.begin(), str.end(), str.begin(),
32*03ce13f7SAndroid Build Coastguard Worker 	               [](unsigned char c) { return std::tolower(c); });
33*03ce13f7SAndroid Build Coastguard Worker 	return str;
34*03ce13f7SAndroid Build Coastguard Worker }
35*03ce13f7SAndroid Build Coastguard Worker 
endswith_lower(const std::string & str,const std::string & suffix)36*03ce13f7SAndroid Build Coastguard Worker bool endswith_lower(const std::string &str, const std::string &suffix)
37*03ce13f7SAndroid Build Coastguard Worker {
38*03ce13f7SAndroid Build Coastguard Worker 	size_t strLen = str.size();
39*03ce13f7SAndroid Build Coastguard Worker 	size_t suffixLen = suffix.size();
40*03ce13f7SAndroid Build Coastguard Worker 
41*03ce13f7SAndroid Build Coastguard Worker 	if(strLen < suffixLen)
42*03ce13f7SAndroid Build Coastguard Worker 	{
43*03ce13f7SAndroid Build Coastguard Worker 		return false;
44*03ce13f7SAndroid Build Coastguard Worker 	}
45*03ce13f7SAndroid Build Coastguard Worker 
46*03ce13f7SAndroid Build Coastguard Worker 	return to_lower(str).substr(strLen - suffixLen) == to_lower(suffix);
47*03ce13f7SAndroid Build Coastguard Worker }
48*03ce13f7SAndroid Build Coastguard Worker }  // namespace
49*03ce13f7SAndroid Build Coastguard Worker 
getCallerBacktrace(size_t limit)50*03ce13f7SAndroid Build Coastguard Worker Backtrace getCallerBacktrace(size_t limit /* = 0 */)
51*03ce13f7SAndroid Build Coastguard Worker {
52*03ce13f7SAndroid Build Coastguard Worker 	namespace bs = boost::stacktrace;
53*03ce13f7SAndroid Build Coastguard Worker 
54*03ce13f7SAndroid Build Coastguard Worker 	auto shouldSkipFile = [](const std::string &fileSR) {
55*03ce13f7SAndroid Build Coastguard Worker 		return fileSR.empty() ||
56*03ce13f7SAndroid Build Coastguard Worker 		       endswith_lower(fileSR, "ReactorDebugInfo.cpp") ||
57*03ce13f7SAndroid Build Coastguard Worker 		       endswith_lower(fileSR, "Reactor.cpp") ||
58*03ce13f7SAndroid Build Coastguard Worker 		       endswith_lower(fileSR, "Reactor.hpp") ||
59*03ce13f7SAndroid Build Coastguard Worker 		       endswith_lower(fileSR, "Traits.hpp") ||
60*03ce13f7SAndroid Build Coastguard Worker 		       endswith_lower(fileSR, "stacktrace.hpp");
61*03ce13f7SAndroid Build Coastguard Worker 	};
62*03ce13f7SAndroid Build Coastguard Worker 
63*03ce13f7SAndroid Build Coastguard Worker 	auto offsetStackFrames = [](const bs::stacktrace &st) {
64*03ce13f7SAndroid Build Coastguard Worker 		// Return a stack trace with every stack frame address offset by -1. We do this so that we get
65*03ce13f7SAndroid Build Coastguard Worker 		// back the location of the function call, and not the location following it. We need this since
66*03ce13f7SAndroid Build Coastguard Worker 		// all debug info emits are the result of a function call. Note that technically we shouldn't
67*03ce13f7SAndroid Build Coastguard Worker 		// perform this offsetting on the top-most stack frame, but it doesn't matter as we discard it
68*03ce13f7SAndroid Build Coastguard Worker 		// anyway (see shouldSkipFile).
69*03ce13f7SAndroid Build Coastguard Worker 
70*03ce13f7SAndroid Build Coastguard Worker 		std::vector<bs::frame> result;
71*03ce13f7SAndroid Build Coastguard Worker 		result.reserve(st.size());
72*03ce13f7SAndroid Build Coastguard Worker 
73*03ce13f7SAndroid Build Coastguard Worker 		for(bs::frame frame : st)
74*03ce13f7SAndroid Build Coastguard Worker 		{
75*03ce13f7SAndroid Build Coastguard Worker 			result.emplace_back(reinterpret_cast<void *>(reinterpret_cast<size_t>(frame.address()) - 1));
76*03ce13f7SAndroid Build Coastguard Worker 		}
77*03ce13f7SAndroid Build Coastguard Worker 
78*03ce13f7SAndroid Build Coastguard Worker 		return result;
79*03ce13f7SAndroid Build Coastguard Worker 	};
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker 	std::vector<Location> locations;
82*03ce13f7SAndroid Build Coastguard Worker 
83*03ce13f7SAndroid Build Coastguard Worker 	// Cache to avoid expensive stacktrace lookups, especially since our use-case results in looking up the
84*03ce13f7SAndroid Build Coastguard Worker 	// same call stack addresses many times.
85*03ce13f7SAndroid Build Coastguard Worker 	static std::unordered_map<bs::frame::native_frame_ptr_t, Location> cache;
86*03ce13f7SAndroid Build Coastguard Worker 
87*03ce13f7SAndroid Build Coastguard Worker 	for(bs::frame frame : offsetStackFrames(bs::stacktrace()))
88*03ce13f7SAndroid Build Coastguard Worker 	{
89*03ce13f7SAndroid Build Coastguard Worker 		Location location;
90*03ce13f7SAndroid Build Coastguard Worker 
91*03ce13f7SAndroid Build Coastguard Worker 		auto iter = cache.find(frame.address());
92*03ce13f7SAndroid Build Coastguard Worker 		if(iter == cache.end())
93*03ce13f7SAndroid Build Coastguard Worker 		{
94*03ce13f7SAndroid Build Coastguard Worker 			location.function.file = frame.source_file();
95*03ce13f7SAndroid Build Coastguard Worker 			location.function.name = frame.name();
96*03ce13f7SAndroid Build Coastguard Worker 			location.line = frame.source_line();
97*03ce13f7SAndroid Build Coastguard Worker 			cache[frame.address()] = location;
98*03ce13f7SAndroid Build Coastguard Worker 		}
99*03ce13f7SAndroid Build Coastguard Worker 		else
100*03ce13f7SAndroid Build Coastguard Worker 		{
101*03ce13f7SAndroid Build Coastguard Worker 			location = iter->second;
102*03ce13f7SAndroid Build Coastguard Worker 		}
103*03ce13f7SAndroid Build Coastguard Worker 
104*03ce13f7SAndroid Build Coastguard Worker 		if(shouldSkipFile(location.function.file))
105*03ce13f7SAndroid Build Coastguard Worker 		{
106*03ce13f7SAndroid Build Coastguard Worker 			continue;
107*03ce13f7SAndroid Build Coastguard Worker 		}
108*03ce13f7SAndroid Build Coastguard Worker 
109*03ce13f7SAndroid Build Coastguard Worker 		locations.push_back(std::move(location));
110*03ce13f7SAndroid Build Coastguard Worker 
111*03ce13f7SAndroid Build Coastguard Worker 		if(limit > 0 && locations.size() >= limit)
112*03ce13f7SAndroid Build Coastguard Worker 		{
113*03ce13f7SAndroid Build Coastguard Worker 			break;
114*03ce13f7SAndroid Build Coastguard Worker 		}
115*03ce13f7SAndroid Build Coastguard Worker 	}
116*03ce13f7SAndroid Build Coastguard Worker 
117*03ce13f7SAndroid Build Coastguard Worker 	std::reverse(locations.begin(), locations.end());
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker 	return locations;
120*03ce13f7SAndroid Build Coastguard Worker }
121*03ce13f7SAndroid Build Coastguard Worker 
emitPrintLocation(const Backtrace & backtrace)122*03ce13f7SAndroid Build Coastguard Worker void emitPrintLocation(const Backtrace &backtrace)
123*03ce13f7SAndroid Build Coastguard Worker {
124*03ce13f7SAndroid Build Coastguard Worker #	ifdef ENABLE_RR_EMIT_PRINT_LOCATION
125*03ce13f7SAndroid Build Coastguard Worker 	static Location lastLocation;
126*03ce13f7SAndroid Build Coastguard Worker 	if(backtrace.size() == 0)
127*03ce13f7SAndroid Build Coastguard Worker 	{
128*03ce13f7SAndroid Build Coastguard Worker 		return;
129*03ce13f7SAndroid Build Coastguard Worker 	}
130*03ce13f7SAndroid Build Coastguard Worker 	Location currLocation = backtrace[backtrace.size() - 1];
131*03ce13f7SAndroid Build Coastguard Worker 	if(currLocation != lastLocation)
132*03ce13f7SAndroid Build Coastguard Worker 	{
133*03ce13f7SAndroid Build Coastguard Worker 		rr::Print("rr> {0} [{1}:{2}]\n", currLocation.function.name.c_str(), currLocation.function.file.c_str(), currLocation.line);
134*03ce13f7SAndroid Build Coastguard Worker 		lastLocation = std::move(currLocation);
135*03ce13f7SAndroid Build Coastguard Worker 	}
136*03ce13f7SAndroid Build Coastguard Worker #	endif
137*03ce13f7SAndroid Build Coastguard Worker }
138*03ce13f7SAndroid Build Coastguard Worker 
139*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
140*03ce13f7SAndroid Build Coastguard Worker 
141*03ce13f7SAndroid Build Coastguard Worker #endif  // ENABLE_RR_DEBUG_INFO
142