blob: a518715ed3d5cb253687d10705e8f51fdb0d7bbc [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 <zircon/system/public/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 "src/lib/fxl/logging.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 fidl_codec::Colors& colors, std::string_view line_header,
const std::vector<zxdb::Location>& caller_locations, std::ostream& os) {
for (const auto& location : caller_locations) {
if (location.is_valid()) {
const zxdb::LazySymbol& symbol = location.symbol();
os << line_header << colors.yellow_background << "at " << colors.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) {
os << separator << item;
separator = "/";
}
os << colors.reset << colors.yellow_background << ':' << colors.blue
<< location.file_line().line() << colors.reset;
} else {
os << std::hex << location.address() << colors.reset << std::dec;
}
if (symbol.is_valid()) {
os << ' ' << symbol.Get()->GetFullName();
}
os << '\n';
}
}
}
} // namespace fidlcat