| // 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 |