blob: 82a3369edbd4f088ba168a0a2543a847876d74ba [file] [log] [blame]
// 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 "src/developer/debug/zxdb/client/mock_frame.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/client/arch_info.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/expr/eval_context_impl.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/mock_symbol_data_provider.h"
namespace zxdb {
namespace {
Location MakeLocation(TargetPointer ip, const std::string& func_name, FileLine file_line) {
// The function name currently can't handle "::". Because we pass the string to set_assigned_name,
// they will be treated as literals and not scope separators. If support for those is needed,
// we need to make the hierarchy of namespaces, etc. to put the function in.
FX_DCHECK(func_name.find("::") == std::string::npos);
auto function = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
function->set_assigned_name(func_name);
return Location(ip, std::move(file_line), 0, SymbolContext::ForRelativeAddresses(), function);
}
} // namespace
MockFrame::MockFrame(Session* session, Thread* thread, const Location& location, uint64_t sp,
uint64_t cfa, std::vector<debug::RegisterValue> regs, uint64_t frame_base,
const Frame* physical_frame, bool is_ambiguous_inline)
: Frame(session),
thread_(thread),
sp_(sp),
cfa_(cfa),
general_registers_(std::move(regs)),
frame_base_(frame_base),
physical_frame_(physical_frame),
location_(location),
is_ambiguous_inline_(is_ambiguous_inline) {}
MockFrame::MockFrame(Session* session, Thread* thread, TargetPointer ip, TargetPointer sp,
const std::string& func_name, FileLine file_line)
: MockFrame(session, thread, MakeLocation(ip, func_name, std::move(file_line)), sp) {}
MockFrame::~MockFrame() = default;
void MockFrame::SetAddress(uint64_t address) {
location_ = Location(address, location_.file_line(), location_.column(),
location_.symbol_context(), location_.symbol());
}
void MockFrame::SetFileLine(const FileLine& file_line) {
location_ = Location(location_.address(), file_line, location_.column(),
location_.symbol_context(), location_.symbol());
}
MockSymbolDataProvider* MockFrame::GetMockSymbolDataProvider() {
GetSymbolDataProvider(); // Force creation.
return symbol_data_provider_.get();
}
Thread* MockFrame::GetThread() const { return thread_; }
bool MockFrame::IsInline() const { return !!physical_frame_; }
const Frame* MockFrame::GetPhysicalFrame() const {
if (physical_frame_)
return physical_frame_;
return this;
}
const Location& MockFrame::GetLocation() const { return location_; }
uint64_t MockFrame::GetAddress() const { return location_.address(); }
const std::vector<debug::RegisterValue>* MockFrame::GetRegisterCategorySync(
debug::RegisterCategory category) const {
if (category == debug::RegisterCategory::kGeneral)
return &general_registers_;
return nullptr;
}
void MockFrame::GetRegisterCategoryAsync(
debug::RegisterCategory category, bool always_request,
fit::function<void(const Err&, const std::vector<debug::RegisterValue>&)> cb) {
Err err;
std::vector<debug::RegisterValue> regs;
if (category == debug::RegisterCategory::kGeneral)
regs = general_registers_;
else
err = Err("Register category unavailable from mock.");
debug::MessageLoop::Current()->PostTask(
FROM_HERE, [err, regs, cb = std::move(cb)]() mutable { cb(err, regs); });
}
void MockFrame::WriteRegister(debug::RegisterID id, std::vector<uint8_t> data,
fit::callback<void(const Err&)> cb) {
debug::MessageLoop::Current()->PostTask(FROM_HERE, [cb = std::move(cb)]() mutable {
cb(Err("Writing registers not (yet) supported by the mock."));
});
}
std::optional<uint64_t> MockFrame::GetBasePointer() const { return frame_base_; }
void MockFrame::GetBasePointerAsync(fit::callback<void(uint64_t)> cb) {
debug::MessageLoop::Current()->PostTask(
FROM_HERE, [bp = frame_base_, cb = std::move(cb)]() mutable { cb(bp); });
}
uint64_t MockFrame::GetStackPointer() const { return sp_; }
uint64_t MockFrame::GetCanonicalFrameAddress() const { return cfa_; }
fxl::RefPtr<SymbolDataProvider> MockFrame::GetSymbolDataProvider() const {
if (!symbol_data_provider_)
symbol_data_provider_ = fxl::MakeRefCounted<MockSymbolDataProvider>();
return symbol_data_provider_;
}
fxl::RefPtr<EvalContext> MockFrame::GetEvalContext() const {
if (!eval_context_) {
eval_context_ = fxl::MakeRefCounted<EvalContextImpl>(session()->arch_info().abi(),
fxl::WeakPtr<const ProcessSymbols>(),
GetSymbolDataProvider(), location_);
}
return eval_context_;
}
bool MockFrame::IsAmbiguousInlineLocation() const { return is_ambiguous_inline_; }
} // namespace zxdb