| // Copyright 2018 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 <iomanip> |
| #include <sstream> |
| |
| #include "src/developer/debug/zxdb/client/remote_api.h" |
| #include "src/developer/debug/zxdb/client/session.h" |
| #include "src/developer/debug/zxdb/client/system.h" |
| #include "src/developer/debug/zxdb/common/err.h" |
| #include "src/developer/debug/zxdb/console/command.h" |
| #include "src/developer/debug/zxdb/console/console.h" |
| #include "src/developer/debug/zxdb/console/output_buffer.h" |
| #include "src/developer/debug/zxdb/console/verbs.h" |
| #include "src/lib/fxl/strings/string_printf.h" |
| |
| namespace zxdb { |
| |
| namespace { |
| |
| // List Processes -------------------------------------------------------------- |
| |
| void OutputProcessTreeRecord(const debug_ipc::ProcessTreeRecord& rec, |
| int indent, OutputBuffer* output) { |
| std::ostringstream line; |
| line << std::setw(indent * 2) << ""; |
| |
| switch (rec.type) { |
| case debug_ipc::ProcessTreeRecord::Type::kJob: |
| line << 'j'; |
| break; |
| case debug_ipc::ProcessTreeRecord::Type::kProcess: |
| line << 'p'; |
| break; |
| default: |
| line << '?'; |
| } |
| |
| line << ": " << rec.koid << " " << rec.name << "\n"; |
| |
| output->Append(line.str()); |
| for (const auto& child : rec.children) |
| OutputProcessTreeRecord(child, indent + 1, output); |
| } |
| |
| void OnListProcessesComplete(const Err& err, |
| debug_ipc::ProcessTreeReply reply) { |
| OutputBuffer out; |
| if (err.has_error()) |
| out.Append(err); |
| else |
| OutputProcessTreeRecord(reply.root, 0, &out); |
| Console::get()->Output(out); |
| } |
| |
| const char kListProcessesShortHelp[] = |
| "ps: Prints the process tree of the debugged system."; |
| const char kListProcessesHelp[] = |
| R"(ps |
| |
| Prints the process tree of the debugged system.)"; |
| |
| Err DoListProcesses(ConsoleContext* context, const Command& cmd) { |
| context->session()->system().GetProcessTree(&OnListProcessesComplete); |
| return Err(); |
| } |
| |
| // System Info ----------------------------------------------------------------- |
| |
| const char kSysInfoShortHelp[] = |
| "sys-info: Get general information about the target system."; |
| |
| const char kSysInfoHelp[] = |
| R"(sys-info |
| |
| Get general information about the target system. |
| This includes aspects such as build version, number of CPUs, memory, etc.)"; |
| |
| void OnSysInfo(const Err& err, debug_ipc::SysInfoReply sys_info) { |
| if (err.has_error()) { |
| Console::get()->Output(err); |
| return; |
| } |
| |
| OutputBuffer out; |
| out.Append(fxl::StringPrintf("Version: %s\n", sys_info.version.c_str())); |
| out.Append(fxl::StringPrintf("Num CPUs: %u\n", sys_info.num_cpus)); |
| |
| // We don't have total ram for minidumps. We can assume a 0 value is always |
| // invalid and just not print it. |
| out.Append("Memory (MiB): "); |
| if (sys_info.memory_mb) { |
| out.Append(fxl::StringPrintf("%u\n", sys_info.memory_mb)); |
| } else { |
| out.Append(Syntax::kComment, "<Unknown>\n"); |
| } |
| |
| out.Append( |
| fxl::StringPrintf("HW Breakpoints: %u\n", sys_info.hw_breakpoint_count)); |
| out.Append( |
| fxl::StringPrintf("HW Watchpoints: %u\n", sys_info.hw_watchpoint_count)); |
| |
| Console::get()->Output(std::move(out)); |
| } |
| |
| Err DoSysInfo(ConsoleContext* context, const Command& cmd) { |
| debug_ipc::SysInfoRequest request; |
| context->session()->remote_api()->SysInfo(request, &OnSysInfo); |
| return Err(); |
| } |
| |
| } // namespace |
| |
| void AppendSystemVerbs(std::map<Verb, VerbRecord>* verbs) { |
| (*verbs)[Verb::kListProcesses] = |
| VerbRecord(&DoListProcesses, {"ps"}, kListProcessesShortHelp, |
| kListProcessesHelp, CommandGroup::kGeneral); |
| (*verbs)[Verb::kSysInfo] = |
| VerbRecord(&DoSysInfo, {"sys-info"}, kSysInfoShortHelp, kSysInfoHelp, |
| CommandGroup::kGeneral); |
| } |
| |
| } // namespace zxdb |