blob: cd7cc44e9a8b3c67ed5954d8a4f7be346513e898 [file] [log] [blame]
Antonio Maioranoaae33732020-02-14 14:52:34 -05001// Copyright 2020 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 "ReactorDebugInfo.hpp"
16#include "Print.hpp"
17
18#ifdef ENABLE_RR_DEBUG_INFO
19
20# include "boost/stacktrace.hpp"
21
22# include <algorithm>
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050023# include <unordered_map>
Antonio Maioranoaae33732020-02-14 14:52:34 -050024
25namespace rr {
26
27namespace {
28std::string to_lower(std::string str)
29{
30 std::transform(str.begin(), str.end(), str.begin(),
31 [](unsigned char c) { return std::tolower(c); });
32 return str;
33}
34
35bool endswith_lower(const std::string &str, const std::string &suffix)
36{
37 size_t strLen = str.size();
38 size_t suffixLen = suffix.size();
39
40 if(strLen < suffixLen)
41 {
42 return false;
43 }
44
45 return to_lower(str).substr(strLen - suffixLen) == to_lower(suffix);
46}
47} // namespace
48
49Backtrace getCallerBacktrace(size_t limit /* = 0 */)
50{
51 auto shouldSkipFile = [](const std::string &fileSR) {
52 return fileSR.empty() ||
53 endswith_lower(fileSR, "ReactorDebugInfo.cpp") ||
54 endswith_lower(fileSR, "Reactor.cpp") ||
55 endswith_lower(fileSR, "Reactor.hpp") ||
56 endswith_lower(fileSR, "Traits.hpp") ||
57 endswith_lower(fileSR, "stacktrace.hpp");
58 };
59
60 std::vector<Location> locations;
61
Antonio Maioranoaae33732020-02-14 14:52:34 -050062 namespace bs = boost::stacktrace;
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050063
64 // Cache to avoid expensive stacktrace lookups, especially since our use-case results in looking up the
65 // same call stack addresses many times.
66 static std::unordered_map<bs::frame::native_frame_ptr_t, Location> cache;
67
Antonio Maioranoaae33732020-02-14 14:52:34 -050068 for(bs::frame frame : bs::stacktrace())
69 {
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050070 Location location;
71
72 auto iter = cache.find(frame.address());
73 if(iter == cache.end())
74 {
75 location.function.file = frame.source_file();
76 location.function.name = frame.name();
77 location.line = frame.source_line();
78 cache[frame.address()] = location;
79 }
80 else
81 {
82 location = iter->second;
83 }
84
85 if(shouldSkipFile(location.function.file))
Antonio Maioranoaae33732020-02-14 14:52:34 -050086 {
87 continue;
88 }
89
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050090 locations.push_back(std::move(location));
Antonio Maioranoaae33732020-02-14 14:52:34 -050091
92 if(limit > 0 && locations.size() >= limit)
93 {
94 break;
95 }
96 }
97
98 std::reverse(locations.begin(), locations.end());
99
100 return locations;
101}
102
103void emitPrintLocation(const Backtrace &backtrace)
104{
105 static Location lastLocation;
106 if(backtrace.size() == 0)
107 {
108 return;
109 }
110 Location currLocation = backtrace[backtrace.size() - 1];
111 if(currLocation != lastLocation)
112 {
113 rr::Print("rr> {0} [{1}:{2}]\n", currLocation.function.name.c_str(), currLocation.function.file.c_str(), currLocation.line);
114 lastLocation = std::move(currLocation);
115 }
116}
117
118} // namespace rr
119
120#endif // ENABLE_RR_DEBUG_INFO