| // Copyright 2020 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 "tools/fidlcat/lib/fidlcat_printer.h" |
| |
| #include "src/lib/fidl_codec/display_handle.h" |
| #include "tools/fidlcat/lib/event.h" |
| #include "tools/fidlcat/lib/syscall_decoder_dispatcher.h" |
| |
| namespace fidlcat { |
| |
| FidlcatPrinter::FidlcatPrinter(SyscallDisplayDispatcher* dispatcher, Process* process, |
| std::ostream& os, const fidl_codec::Colors& colors, |
| std::string_view line_header, int tabulations) |
| : PrettyPrinter( |
| os, colors, dispatcher->message_decoder_dispatcher().display_options().pretty_print, |
| line_header, dispatcher->columns(), dispatcher->with_process_info(), tabulations), |
| inference_(dispatcher->inference()), |
| process_(process), |
| display_stack_frame_(dispatcher->decode_options().stack_level != kNoStack), |
| dump_messages_(dispatcher->dump_messages()), |
| dispatcher_(dispatcher) {} |
| |
| FidlcatPrinter::FidlcatPrinter(SyscallDisplayDispatcher* dispatcher, Process* process, |
| std::ostream& os, std::string_view line_header, int tabulations) |
| : FidlcatPrinter(dispatcher, process, os, dispatcher->colors(), line_header, tabulations) {} |
| |
| void FidlcatPrinter::DisplayHandle(const zx_handle_disposition_t& handle) { |
| HandleInfo* handle_info = process_->SearchHandleInfo(handle.handle); |
| if ((handle.type == ZX_OBJ_TYPE_NONE) && (handle_info != nullptr) && |
| (handle.operation == fidl_codec::kNoHandleDisposition)) { |
| zx_handle_disposition_t tmp = handle; |
| tmp.type = handle_info->object_type(); |
| fidl_codec::DisplayHandle(tmp, *this); |
| } else { |
| fidl_codec::DisplayHandle(handle, *this); |
| } |
| const fidl_codec::semantic::InferredHandleInfo* inferred_handle_info = |
| inference_.GetInferredHandleInfo(process_->koid(), handle.handle); |
| if (inferred_handle_info != nullptr) { |
| (*this) << '('; |
| inferred_handle_info->Display(*this); |
| (*this) << ')'; |
| } |
| } |
| |
| void FidlcatPrinter::DisplayHandleInfo(HandleInfo* handle_info) { |
| zx_handle_disposition_t disposition = {.operation = fidl_codec::kNoHandleDisposition, |
| .handle = handle_info->handle(), |
| .type = handle_info->object_type(), |
| .rights = 0, |
| .result = ZX_OK}; |
| fidl_codec::DisplayHandle(disposition, *this); |
| const fidl_codec::semantic::InferredHandleInfo* inferred_handle_info = |
| inference_.GetInferredHandleInfo(handle_info->thread()->process()->koid(), |
| handle_info->handle()); |
| if (inferred_handle_info != nullptr) { |
| (*this) << '('; |
| inferred_handle_info->Display(*this); |
| (*this) << ')'; |
| } |
| } |
| |
| void FidlcatPrinter::DisplayStatus(zx_status_t status) { |
| if (status == ZX_OK) { |
| (*this) << fidl_codec::Green; |
| } else { |
| (*this) << fidl_codec::Red; |
| } |
| (*this) << fidl_codec::StatusName(status) << fidl_codec::ResetColor; |
| } |
| |
| void FidlcatPrinter::DisplayInline( |
| const std::vector<std::unique_ptr<fidl_codec::StructMember>>& members, |
| const std::map<const fidl_codec::StructMember*, std::unique_ptr<fidl_codec::Value>>& values) { |
| *this << '('; |
| const char* separator = ""; |
| for (const auto& member : members) { |
| auto it = values.find(member.get()); |
| if (it == values.end()) |
| continue; |
| *this << separator << member->name() << ": " << fidl_codec::Green << member->type()->Name() |
| << fidl_codec::ResetColor << " = "; |
| it->second->PrettyPrint(member->type(), *this); |
| separator = ", "; |
| } |
| *this << ")"; |
| } |
| |
| void FidlcatPrinter::DisplayOutline( |
| const std::vector<std::unique_ptr<fidl_codec::StructMember>>& members, |
| const std::map<const fidl_codec::StructMember*, std::unique_ptr<fidl_codec::Value>>& values) { |
| fidl_codec::Indent indent(*this); |
| for (const auto& member : members) { |
| auto it = values.find(member.get()); |
| if (it == values.end()) |
| continue; |
| auto fidl_message_value = it->second->AsFidlMessageValue(); |
| if (fidl_message_value != nullptr) { |
| it->second->PrettyPrint(member->type(), *this); |
| } else { |
| *this << member->name() << ": " << fidl_codec::Green << member->type()->Name() |
| << fidl_codec::ResetColor << " = "; |
| it->second->PrettyPrint(member->type(), *this); |
| *this << '\n'; |
| } |
| } |
| } |
| |
| void FidlcatPrinter::DisplayStackFrame(const std::vector<Location>& stack_frame) { |
| bool save_header_on_every_line = header_on_every_line(); |
| // We want a header on every stack frame line. |
| set_header_on_every_line(true); |
| for (const auto& location : stack_frame) { |
| *this << fidl_codec::YellowBackground << "at " << fidl_codec::Red; |
| if (!location.path().empty()) { |
| *this << location.path() << fidl_codec::ResetColor << fidl_codec::YellowBackground << ':' |
| << fidl_codec::Blue << location.line() << ':' << location.column() |
| << fidl_codec::ResetColor; |
| } else { |
| *this << std::hex << location.address() << fidl_codec::ResetColor << std::dec; |
| } |
| if (!location.symbol().empty()) { |
| *this << ' ' << location.symbol(); |
| } |
| *this << '\n'; |
| } |
| set_header_on_every_line(save_header_on_every_line); |
| } |
| |
| } // namespace fidlcat |