Commit 6a8a7498 by Antonio Maiorano

Fix ReactorDebugInfo off by one line issues

Before this commit, when debugging with the ReactorDebugInfo feature, variables were being incorrectly displayed in the debugger. For instance, given: Int a = 1; Int b = 2; The debugger would not display 'a', and would display 'b' as containing the value '1'. The reason for this was that while the Int constructor for 'a' was executing, we invoke boost::stacktrace() to determine the variable's source location (file and line number); however, the stack trace would return the return address of the constructor call, which would be on the next line -- that of 'Int b'. To fix this, knowing that all ReactorDebugInfo emits come from function calls in Reactor code, we assume that all backtrace addresses point to the next instruction following the call, thus we subtract 1 from these addresses. When resolving the file and line number, this gets back the previous instruction's location. There are likely corner cases where this doesn't work, but it's better than what we have now. Bug: b/161821289 Change-Id: Ie92ead393f321fc1a26fc019d6450bfddb7a5e24 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/46868Reviewed-by: 's avatarBen Clayton <bclayton@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarAntonio Maiorano <amaiorano@google.com>
parent a45603bd
......@@ -49,6 +49,8 @@ bool endswith_lower(const std::string &str, const std::string &suffix)
Backtrace getCallerBacktrace(size_t limit /* = 0 */)
{
namespace bs = boost::stacktrace;
auto shouldSkipFile = [](const std::string &fileSR) {
return fileSR.empty() ||
endswith_lower(fileSR, "ReactorDebugInfo.cpp") ||
......@@ -58,15 +60,31 @@ Backtrace getCallerBacktrace(size_t limit /* = 0 */)
endswith_lower(fileSR, "stacktrace.hpp");
};
std::vector<Location> locations;
auto offsetStackFrames = [](const bs::stacktrace &st) {
// Return a stack trace with every stack frame address offset by -1. We do this so that we get
// back the location of the function call, and not the location following it. We need this since
// all debug info emits are the result of a function call. Note that technically we shouldn't
// perform this offsetting on the top-most stack frame, but it doesn't matter as we discard it
// anyway (see shouldSkipFile).
namespace bs = boost::stacktrace;
std::vector<bs::frame> result;
result.reserve(st.size());
for(bs::frame frame : st)
{
result.emplace_back(reinterpret_cast<void *>(reinterpret_cast<size_t>(frame.address()) - 1));
}
return result;
};
std::vector<Location> locations;
// Cache to avoid expensive stacktrace lookups, especially since our use-case results in looking up the
// same call stack addresses many times.
static std::unordered_map<bs::frame::native_frame_ptr_t, Location> cache;
for(bs::frame frame : bs::stacktrace())
for(bs::frame frame : offsetStackFrames(bs::stacktrace()))
{
Location location;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment