blob: 9d044dfc35780fca21d351cc5633c474a429217c [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/syslog/cpp/macros.h>
#include <zircon/types.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <ostream>
#include <vector>
#include "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/memory_dump.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/step_thread_controller.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/symbols/symbol.h"
#include "tools/fidlcat/lib/event.h"
#include "tools/fidlcat/lib/syscall_decoder.h"
namespace fidlcat {
// TODO(b 42261): This wouldn't be necessary if zxdb would clean the paths.
std::vector<std::string_view> CleanPath(const zxdb::FileLine& file_line) {
std::vector<std::string_view> path_elements;
int ignore_leading_dot_dot = 2;
size_t pos = 0;
for (;;) {
size_t start = pos;
pos = file_line.file().find('/', pos);
if (pos == std::string::npos) {
path_elements.emplace_back(
std::string_view(file_line.file().c_str() + start, file_line.file().size() - start));
break;
}
std::string_view element(file_line.file().c_str() + start, pos - start);
if ((ignore_leading_dot_dot > 0) && (element.compare("..") == 0)) {
// The paths returned by zxdb are not relative to the Fuchsia root directory.
// We must ignore the first two ".." to be relative to the root directory.
--ignore_leading_dot_dot;
} else {
path_elements.push_back(element);
// Just in case the path didn't start with two "..".
ignore_leading_dot_dot = 0;
}
++pos;
}
// Remove the ".." we can.
int destination = 0;
for (const auto& element : path_elements) {
if (element.compare(".") != 0) {
if ((element.compare("..") == 0) && (destination > 0) &&
(path_elements[destination - 1].compare("..") != 0)) {
--destination;
} else {
path_elements[destination++] = element;
}
}
}
path_elements.resize(destination);
return path_elements;
}
void DisplayStackFrame(const std::vector<zxdb::Location>& caller_locations,
fidl_codec::PrettyPrinter& printer) {
bool header_on_every_line = printer.header_on_every_line();
// We want a header on every stack frame line.
printer.set_header_on_every_line(true);
for (const auto& location : caller_locations) {
if (location.is_valid()) {
const zxdb::LazySymbol& symbol = location.symbol();
printer << fidl_codec::YellowBackground << "at " << fidl_codec::Red;
if (location.is_symbolized()) {
std::vector<std::string_view> file = CleanPath(location.file_line());
// Display the optimized path.
const char* separator = "";
for (const auto& item : file) {
printer << separator << item;
separator = "/";
}
printer << fidl_codec::ResetColor << fidl_codec::YellowBackground << ':' << fidl_codec::Blue
<< location.file_line().line() << ':' << location.column()
<< fidl_codec::ResetColor;
} else {
printer << std::hex << location.address() << fidl_codec::ResetColor << std::dec;
}
if (symbol.is_valid()) {
printer << ' ' << symbol.Get()->GetFullName();
}
printer << '\n';
}
}
printer.set_header_on_every_line(header_on_every_line);
}
void CopyStackFrame(const std::vector<zxdb::Location>& caller_locations,
std::vector<Location>* locations) {
for (const auto& location : caller_locations) {
if (location.is_valid()) {
std::string path;
uint32_t line = 0;
uint32_t column = 0;
if (location.is_symbolized()) {
std::vector<std::string_view> file = CleanPath(location.file_line());
// Copies the optimized path.
const char* separator = "";
for (const auto& item : file) {
path += separator;
path += item;
separator = "/";
}
line = location.file_line().line();
column = location.column();
}
std::string empty_symbol;
const zxdb::LazySymbol& symbol = location.symbol();
locations->emplace_back(path, line, column, location.address(),
symbol.is_valid() ? symbol.Get()->GetFullName() : empty_symbol);
}
}
}
} // namespace fidlcat