| // 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 "garnet/bin/zxdb/symbols/mock_symbol_data_provider.h" |
| |
| #include <inttypes.h> |
| |
| #include <algorithm> |
| |
| #include "garnet/bin/zxdb/common/err.h" |
| #include "garnet/lib/debug_ipc/helper/message_loop.h" |
| #include "lib/fxl/strings/string_printf.h" |
| |
| namespace zxdb { |
| |
| MockSymbolDataProvider::MockSymbolDataProvider() : weak_factory_(this) {} |
| |
| void MockSymbolDataProvider::AddRegisterValue(int register_num, |
| bool synchronous, |
| uint64_t value) { |
| regs_[register_num] = RegData(synchronous, value); |
| } |
| |
| void MockSymbolDataProvider::AddMemory(uint64_t address, |
| std::vector<uint8_t> data) { |
| mem_[address] = std::move(data); |
| } |
| |
| std::optional<uint64_t> MockSymbolDataProvider::GetRegister( |
| int dwarf_register_number) { |
| if (dwarf_register_number == kRegisterIP) |
| return ip_; |
| |
| const auto& found = regs_.find(dwarf_register_number); |
| if (found == regs_.end()) |
| return std::nullopt; |
| |
| if (!found->second.synchronous) |
| return std::nullopt; // Force synchronous query. |
| |
| return found->second.value; |
| } |
| |
| void MockSymbolDataProvider::GetRegisterAsync(int dwarf_register_number, |
| GetRegisterCallback callback) { |
| debug_ipc::MessageLoop::Current()->PostTask( |
| FROM_HERE, [callback, weak_provider = weak_factory_.GetWeakPtr(), |
| dwarf_register_number]() { |
| if (!weak_provider) { |
| // Destroyed before callback ready. |
| return; |
| } |
| |
| const auto& found = weak_provider->regs_.find(dwarf_register_number); |
| if (found == weak_provider->regs_.end()) |
| callback(Err("Failed"), 0); |
| callback(Err(), found->second.value); |
| }); |
| } |
| |
| std::optional<uint64_t> MockSymbolDataProvider::GetFrameBase() { return bp_; } |
| |
| void MockSymbolDataProvider::GetFrameBaseAsync(GetRegisterCallback callback) { |
| debug_ipc::MessageLoop::Current()->PostTask( |
| FROM_HERE, [callback, weak_provider = weak_factory_.GetWeakPtr()]() { |
| if (!weak_provider) { |
| // Destroyed before callback ready. |
| return; |
| } |
| callback(Err(), weak_provider->bp_); |
| }); |
| } |
| |
| void MockSymbolDataProvider::GetMemoryAsync(uint64_t address, uint32_t size, |
| GetMemoryCallback callback) { |
| auto found = FindBlockForAddress(address); |
| if (found == mem_.end()) { |
| debug_ipc::MessageLoop::Current()->PostTask(FROM_HERE, [callback]() { |
| // The API states that invalid memory is not an error, it just does a |
| // short read. |
| callback(Err(), std::vector<uint8_t>()); |
| }); |
| } else { |
| size_t offset = address - found->first; |
| |
| uint32_t size_to_return = |
| std::min(size, static_cast<uint32_t>(found->second.size() - offset)); |
| |
| std::vector<uint8_t> subset; |
| subset.resize(size_to_return); |
| memcpy(&subset[0], &found->second[offset], size_to_return); |
| debug_ipc::MessageLoop::Current()->PostTask( |
| FROM_HERE, [callback, subset]() { callback(Err(), subset); }); |
| } |
| } |
| |
| void MockSymbolDataProvider::WriteMemory(uint64_t address, |
| std::vector<uint8_t> data, |
| std::function<void(const Err&)> cb) { |
| memory_writes_.emplace_back(address, std::move(data)); |
| |
| // Declare success. |
| debug_ipc::MessageLoop::Current()->PostTask(FROM_HERE, [cb]() { cb(Err()); }); |
| } |
| |
| MockSymbolDataProvider::RegisteredMemory::const_iterator |
| MockSymbolDataProvider::FindBlockForAddress(uint64_t address) const { |
| // Finds the first block >= address. |
| auto found = mem_.lower_bound(address); |
| |
| // We need the first block <= address. |
| if (found != mem_.end() && found->first == address) |
| return found; // Got exact match. |
| |
| // Now find the first block < address. |
| if (found == mem_.begin()) |
| return mem_.end(); // Nothing before the address. |
| |
| --found; |
| if (address >= found->first + found->second.size()) |
| return mem_.end(); // Address is after this range. |
| return found; |
| } |
| |
| } // namespace zxdb |