blob: 18849998e0a60f0bc6de1685b332a97ed8836706 [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 Maiorano4b777772020-06-22 14:55:37 -040023# include <cctype>
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050024# include <unordered_map>
Antonio Maioranoaae33732020-02-14 14:52:34 -050025
26namespace rr {
27
28namespace {
29std::string to_lower(std::string str)
30{
31 std::transform(str.begin(), str.end(), str.begin(),
32 [](unsigned char c) { return std::tolower(c); });
33 return str;
34}
35
36bool endswith_lower(const std::string &str, const std::string &suffix)
37{
38 size_t strLen = str.size();
39 size_t suffixLen = suffix.size();
40
41 if(strLen < suffixLen)
42 {
43 return false;
44 }
45
46 return to_lower(str).substr(strLen - suffixLen) == to_lower(suffix);
47}
48} // namespace
49
50Backtrace getCallerBacktrace(size_t limit /* = 0 */)
51{
Antonio Maiorano6a8a7492020-07-21 16:23:14 -040052 namespace bs = boost::stacktrace;
53
Antonio Maioranoaae33732020-02-14 14:52:34 -050054 auto shouldSkipFile = [](const std::string &fileSR) {
55 return fileSR.empty() ||
56 endswith_lower(fileSR, "ReactorDebugInfo.cpp") ||
57 endswith_lower(fileSR, "Reactor.cpp") ||
58 endswith_lower(fileSR, "Reactor.hpp") ||
59 endswith_lower(fileSR, "Traits.hpp") ||
60 endswith_lower(fileSR, "stacktrace.hpp");
61 };
62
Antonio Maiorano6a8a7492020-07-21 16:23:14 -040063 auto offsetStackFrames = [](const bs::stacktrace &st) {
64 // Return a stack trace with every stack frame address offset by -1. We do this so that we get
65 // back the location of the function call, and not the location following it. We need this since
66 // all debug info emits are the result of a function call. Note that technically we shouldn't
67 // perform this offsetting on the top-most stack frame, but it doesn't matter as we discard it
68 // anyway (see shouldSkipFile).
Antonio Maioranoaae33732020-02-14 14:52:34 -050069
Antonio Maiorano6a8a7492020-07-21 16:23:14 -040070 std::vector<bs::frame> result;
71 result.reserve(st.size());
72
73 for(bs::frame frame : st)
74 {
75 result.emplace_back(reinterpret_cast<void *>(reinterpret_cast<size_t>(frame.address()) - 1));
76 }
77
78 return result;
79 };
80
81 std::vector<Location> locations;
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050082
83 // Cache to avoid expensive stacktrace lookups, especially since our use-case results in looking up the
84 // same call stack addresses many times.
85 static std::unordered_map<bs::frame::native_frame_ptr_t, Location> cache;
86
Antonio Maiorano6a8a7492020-07-21 16:23:14 -040087 for(bs::frame frame : offsetStackFrames(bs::stacktrace()))
Antonio Maioranoaae33732020-02-14 14:52:34 -050088 {
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -050089 Location location;
90
91 auto iter = cache.find(frame.address());
92 if(iter == cache.end())
93 {
94 location.function.file = frame.source_file();
95 location.function.name = frame.name();
96 location.line = frame.source_line();
97 cache[frame.address()] = location;
98 }
99 else
100 {
101 location = iter->second;
102 }
103
104 if(shouldSkipFile(location.function.file))
Antonio Maioranoaae33732020-02-14 14:52:34 -0500105 {
106 continue;
107 }
108
Antonio Maiorano0bbf7ba2020-02-17 13:39:37 -0500109 locations.push_back(std::move(location));
Antonio Maioranoaae33732020-02-14 14:52:34 -0500110
111 if(limit > 0 && locations.size() >= limit)
112 {
113 break;
114 }
115 }
116
117 std::reverse(locations.begin(), locations.end());
118
119 return locations;
120}
121
122void emitPrintLocation(const Backtrace &backtrace)
123{
Antonio Maiorano4b777772020-06-22 14:55:37 -0400124# ifdef ENABLE_RR_EMIT_PRINT_LOCATION
Antonio Maioranoaae33732020-02-14 14:52:34 -0500125 static Location lastLocation;
126 if(backtrace.size() == 0)
127 {
128 return;
129 }
130 Location currLocation = backtrace[backtrace.size() - 1];
131 if(currLocation != lastLocation)
132 {
133 rr::Print("rr> {0} [{1}:{2}]\n", currLocation.function.name.c_str(), currLocation.function.file.c_str(), currLocation.line);
134 lastLocation = std::move(currLocation);
135 }
Antonio Maiorano4b777772020-06-22 14:55:37 -0400136# endif
Antonio Maioranoaae33732020-02-14 14:52:34 -0500137}
138
139} // namespace rr
140
141#endif // ENABLE_RR_DEBUG_INFO