174 lines
4.0 KiB
C++
174 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <cstring>
|
|
|
|
#include "backend/debug_backend.h"
|
|
|
|
namespace dbgui::frontend
|
|
{
|
|
struct Target
|
|
{
|
|
struct Reg
|
|
{
|
|
std::string name;
|
|
// TODO: handle registers as sets of 64bit?
|
|
std::vector<uint8_t> bytes;
|
|
};
|
|
|
|
struct RegSet
|
|
{
|
|
std::string name;
|
|
std::vector<Reg> regs;
|
|
};
|
|
|
|
struct Thread
|
|
{
|
|
uint64_t id;
|
|
uint64_t ip;
|
|
uint64_t stop_extra;
|
|
ThreadStopReason stop_reason;
|
|
std::string name;
|
|
std::string cur_display_fn;
|
|
};
|
|
|
|
struct Frame
|
|
{
|
|
uint64_t ip;
|
|
std::string display_name;
|
|
};
|
|
|
|
// TODO: need a way for the backend to report where the breakpoint was actually placed
|
|
// (might have been moved) or if it could be placed at all
|
|
// iow let the backend resolve the address + possible file location for the breakpoint
|
|
// and then display it
|
|
// this should be needed anyways when you want to add expression-based breakpoints, e.g. 'main'
|
|
struct Breakpoint
|
|
{
|
|
struct FileLoc
|
|
{
|
|
std::string name;
|
|
uint32_t line;
|
|
};
|
|
|
|
bool removed = false;
|
|
std::variant<uint64_t, FileLoc> data;
|
|
|
|
bool at_addr(uint64_t addr) const
|
|
{
|
|
return this->data.index() == 0
|
|
&& std::get<uint64_t>(this->data) == addr;
|
|
}
|
|
|
|
bool at_file_loc(std::string_view file, uint32_t line) const
|
|
{
|
|
if (this->data.index() != 1)
|
|
{
|
|
return false;
|
|
}
|
|
const auto &loc = std::get<FileLoc>(this->data);
|
|
if (loc.line == line && loc.name == file)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
struct ExprCacheEntry
|
|
{
|
|
std::string expr_path;
|
|
size_t id;
|
|
size_t id2;
|
|
bool used_this_frame = false;
|
|
bool is_cstr = false;
|
|
};
|
|
|
|
Target(std::string filename, bool stop_at_entry);
|
|
|
|
std::optional<uint16_t> data_idx_for_src_id(size_t id)
|
|
{
|
|
for (auto &[entry_id, idx] : this->src_id_to_data_idx)
|
|
{
|
|
if (entry_id == id)
|
|
{
|
|
return idx;
|
|
}
|
|
}
|
|
return {};
|
|
}
|
|
|
|
data::result::Node *data_node_for_src_id(size_t id)
|
|
{
|
|
auto idx = this->data_idx_for_src_id(id);
|
|
if (!idx)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
if (*idx >= data_res_nodes.size() || !data_res_nodes[*idx])
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
return &*data_res_nodes[*idx];
|
|
}
|
|
|
|
size_t find_or_create_expr_path(std::string &&path, bool is_cstr = false)
|
|
{
|
|
for (auto &entry : expr_cache)
|
|
{
|
|
if (entry.expr_path == path)
|
|
{
|
|
entry.used_this_frame = true;
|
|
return entry.is_cstr ? entry.id2 : entry.id;
|
|
}
|
|
}
|
|
|
|
using namespace data::source;
|
|
auto id = this->id++;
|
|
size_t cstr_id = -1;
|
|
this->backend->add_data_node(
|
|
Node{.id = id,
|
|
.type = Node::Type::source,
|
|
.data = Source{.type = Source::Type::variable,
|
|
.data = Source::Variable{.expr_path = path}}});
|
|
if (is_cstr)
|
|
{
|
|
cstr_id = this->id++;
|
|
this->backend->add_data_node(Node{.id = cstr_id,
|
|
.type = Node::Type::read_cstr,
|
|
.data = ReadAsCStr{.src_id = id}});
|
|
}
|
|
expr_cache.push_back(ExprCacheEntry{.expr_path = std::move(path),
|
|
.id = id,
|
|
.id2 = cstr_id,
|
|
.used_this_frame = true,
|
|
.is_cstr = is_cstr});
|
|
return id;
|
|
}
|
|
|
|
TargetState state = TargetState::stopped;
|
|
std::string filename;
|
|
uint64_t id;
|
|
size_t data_node_id = 0;
|
|
Arch arch;
|
|
bool step_instruction = false;
|
|
uint16_t selected_thread = 0;
|
|
uint16_t selected_frame = 0;
|
|
|
|
std::vector<RegSet> reg_sets;
|
|
std::vector<std::optional<Thread>> threads;
|
|
std::vector<std::optional<Frame>> frames;
|
|
std::vector<Breakpoint> breakpoints;
|
|
std::vector<std::pair<size_t, uint16_t>> src_id_to_data_idx;
|
|
std::vector<std::optional<data::result::Node>> data_res_nodes;
|
|
std::vector<data::type_info::TypeInfo> types;
|
|
std::vector<ExprCacheEntry> expr_cache;
|
|
|
|
std::shared_ptr<backend::Backend> backend = nullptr;
|
|
};
|
|
} // namespace dbgui::frontend
|