| // 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 "src/developer/debug/zxdb/console/commands/verb_mem_read.h" |
| |
| #include "src/developer/debug/zxdb/client/memory_dump.h" |
| #include "src/developer/debug/zxdb/client/process.h" |
| #include "src/developer/debug/zxdb/client/target.h" |
| #include "src/developer/debug/zxdb/console/command.h" |
| #include "src/developer/debug/zxdb/console/command_utils.h" |
| #include "src/developer/debug/zxdb/console/console.h" |
| #include "src/developer/debug/zxdb/console/format_memory.h" |
| #include "src/developer/debug/zxdb/console/input_location_parser.h" |
| #include "src/developer/debug/zxdb/console/output_buffer.h" |
| #include "src/developer/debug/zxdb/console/verbs.h" |
| |
| namespace zxdb { |
| |
| namespace { |
| |
| constexpr int kSizeSwitch = 1; |
| |
| void MemoryReadComplete(const Err& err, MemoryDump dump) { |
| OutputBuffer out; |
| if (err.has_error()) { |
| out.Append(err); |
| } else { |
| MemoryFormatOptions opts; |
| opts.address_mode = MemoryFormatOptions::kAddresses; |
| opts.show_ascii = true; |
| opts.values_per_line = 16; |
| opts.separator_every = 8; |
| out.Append(FormatMemory(dump, dump.address(), static_cast<uint32_t>(dump.size()), opts)); |
| } |
| Console::get()->Output(out); |
| } |
| |
| const char kMemReadShortHelp[] = R"(mem-read / x: Read memory from debugged process.)"; |
| const char kMemReadHelp[] = |
| R"(mem-read [ --size=<bytes> ] <address-expression> |
| |
| Alias: "x" |
| |
| Reads memory from the process at the given address and prints it to the |
| screen. Currently, only a byte-oriented hex dump format is supported. |
| |
| The address can be an explicit number or any expression ("help expressions") |
| that evaluates to a memory address. |
| |
| When no size is given, the size will be the object size if a typed expression |
| is given, otherwise 20 lines will be output. |
| |
| See also the "mem-analyze" command to print a memory analysis and the "stack" |
| command to print a more useful dump of the raw stack. |
| |
| Arguments |
| |
| --size=<bytes> | -s <bytes> |
| Bytes to read. This defaults to the size of the function if a function |
| name is given as the location, or 64 otherwise. |
| |
| Examples |
| |
| x --size=128 0x75f19ba |
| x &foo->bar |
| mem-read --size=16 0x8f1763a7 |
| process 3 mem-read 83242384560 |
| )"; |
| Err RunVerbMemRead(ConsoleContext* context, const Command& cmd) { |
| // Only a process can have its memory read. |
| if (Err err = cmd.ValidateNouns({Noun::kProcess}); err.has_error()) |
| return err; |
| |
| // Size argument (optional). |
| std::optional<uint64_t> input_size; |
| if (cmd.HasSwitch(kSizeSwitch)) { |
| uint64_t read_size = 0; |
| if (Err err = StringToUint64(cmd.GetSwitchValue(kSizeSwitch), &read_size); err.has_error()) |
| return err; |
| input_size = read_size; |
| } |
| |
| return EvalCommandAddressExpression( |
| cmd, "mem-read", GetEvalContextForCommand(cmd), |
| [weak_target = cmd.target()->GetWeakPtr(), input_size](const Err& err, uint64_t address, |
| std::optional<uint64_t> object_size) { |
| Console* console = Console::get(); |
| if (err.has_error()) { |
| console->Output(err); // Evaluation error. |
| return; |
| } |
| if (!weak_target) { |
| // Target has been destroyed during evaluation. Normally a message will be printed when |
| // that happens so we can skip reporting the error. |
| return; |
| } |
| |
| Err run_err = AssertRunningTarget(&console->context(), "mem-read", weak_target.get()); |
| if (run_err.has_error()) { |
| console->Output(run_err); |
| return; |
| } |
| |
| uint64_t read_size; |
| if (input_size) |
| read_size = *input_size; |
| else if (object_size) |
| read_size = *object_size; |
| else |
| read_size = 64; |
| |
| weak_target->GetProcess()->ReadMemory(address, read_size, &MemoryReadComplete); |
| }); |
| |
| return Err(); |
| } |
| |
| } // namespace |
| |
| VerbRecord GetMemReadVerbRecord() { |
| // Mem-read. Note: "x" is the GDB command to read memory. |
| VerbRecord mem_read(&RunVerbMemRead, &CompleteInputLocation, {"mem-read", "x"}, kMemReadShortHelp, |
| kMemReadHelp, CommandGroup::kQuery); |
| mem_read.switches.emplace_back(kSizeSwitch, true, "size", 's'); |
| mem_read.param_type = VerbRecord::kOneParam; |
| return mem_read; |
| } |
| |
| } // namespace zxdb |