WIP
This commit is contained in:
@@ -1510,9 +1510,21 @@ void LLDBBackend::remove_data_node(size_t id)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
_data_nodes.erase(it);
|
_data_nodes.erase(it);
|
||||||
|
_dag_linear_valid = false;
|
||||||
|
|
||||||
|
auto res_it = _data_src_id_to_res_idx.find(id);
|
||||||
|
if (res_it == _data_src_id_to_res_idx.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!_data_res[res_it->second]
|
||||||
|
|| _data_res[res_it->second]->no_delete_on_src_delete)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint16_t> to_delete{};
|
std::vector<uint16_t> to_delete{};
|
||||||
to_delete.push_back(id);
|
to_delete.push_back(res_it->second);
|
||||||
size_t old_size = 0;
|
size_t old_size = 0;
|
||||||
while (to_delete.size() != old_size)
|
while (to_delete.size() != old_size)
|
||||||
{
|
{
|
||||||
@@ -1539,8 +1551,6 @@ void LLDBBackend::remove_data_node(size_t id)
|
|||||||
this->send_remove_data_node(idx);
|
this->send_remove_data_node(idx);
|
||||||
_data_res[idx] = {};
|
_data_res[idx] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
_dag_linear_valid = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLDBBackend::check_data_changes()
|
void LLDBBackend::check_data_changes()
|
||||||
@@ -1571,6 +1581,19 @@ void LLDBBackend::check_data_changes()
|
|||||||
auto res_vec = std::vector<data::result::Node>{};
|
auto res_vec = std::vector<data::result::Node>{};
|
||||||
auto src_id_mapping = this->calc_data_res(*node_it, res_vec);
|
auto src_id_mapping = this->calc_data_res(*node_it, res_vec);
|
||||||
|
|
||||||
|
if (src_id_mapping)
|
||||||
|
{
|
||||||
|
auto it = _data_src_id_to_res_idx.find(src_id_mapping->second);
|
||||||
|
if (it != _data_src_id_to_res_idx.end())
|
||||||
|
{
|
||||||
|
it->second = src_id_mapping->first;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
_data_src_id_to_res_idx.emplace(src_id_mapping->second,
|
||||||
|
src_id_mapping->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!res_vec.empty())
|
if (!res_vec.empty())
|
||||||
{
|
{
|
||||||
// TODO: queue and send at once to prevent UI lag?
|
// TODO: queue and send at once to prevent UI lag?
|
||||||
@@ -1733,6 +1756,54 @@ std::optional<std::pair<uint16_t, size_t>>
|
|||||||
.data = pc,
|
.data = pc,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
case variable:
|
||||||
|
{
|
||||||
|
uint16_t cache_idx = 0;
|
||||||
|
if (auto found_idx = find_node_for_src_id(node.id); found_idx)
|
||||||
|
{
|
||||||
|
cache_idx = *found_idx;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cache_idx = get_free_res_slot();
|
||||||
|
// TODO: this will probably fail if cache_idx == 0
|
||||||
|
_data_res[cache_idx] = CachedDataRes{.src_id = node.id};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
const auto &info =
|
||||||
|
std::get<data::source::Source::Variable>(src_data.data);
|
||||||
|
auto res_node = data::result::Node{
|
||||||
|
.idx = cache_idx,
|
||||||
|
.type_id = data::type_info::TypeID::none(),
|
||||||
|
.success = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto thread = _process->GetSelectedThread();
|
||||||
|
auto frame = thread.GetSelectedFrame();
|
||||||
|
if (!frame.IsValid())
|
||||||
|
{
|
||||||
|
return check_single_res_changed(std::move(res_node));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto var = frame.GetValueForVariablePath(info.expr_path.c_str(),
|
||||||
|
lldb::eDynamicDontRunTarget);
|
||||||
|
if (!var.IsValid() || !var.IsInScope())
|
||||||
|
{
|
||||||
|
return check_single_res_changed(std::move(res_node));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res_idx = this->build_nodes_for_var(var, data_res);
|
||||||
|
if (!res_idx)
|
||||||
|
{
|
||||||
|
return check_single_res_changed(std::move(res_node));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Got res for %s: %u (%u)\n", info.expr_path.c_str(), *res_idx,
|
||||||
|
_data_res[*res_idx]->node.type_id.type);
|
||||||
|
res_node.success = true;
|
||||||
|
res_node.children.push_back(*res_idx);
|
||||||
|
return check_single_res_changed(std::move(res_node));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ namespace dbgui::backend
|
|||||||
bool _dag_linear_valid = false;
|
bool _dag_linear_valid = false;
|
||||||
// util::DAG _data_res_dag = {};
|
// util::DAG _data_res_dag = {};
|
||||||
std::vector<std::optional<CachedDataRes>> _data_res = {};
|
std::vector<std::optional<CachedDataRes>> _data_res = {};
|
||||||
|
std::unordered_map<size_t, data::result::NodeIdx> _data_src_id_to_res_idx =
|
||||||
|
{};
|
||||||
|
|
||||||
std::vector<Local> _locals = {};
|
std::vector<Local> _locals = {};
|
||||||
std::optional<data::result::NodeIdx> _locals_node = {};
|
std::optional<data::result::NodeIdx> _locals_node = {};
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ namespace dbgui::data
|
|||||||
frame_ip, // binds the selected frame
|
frame_ip, // binds the selected frame
|
||||||
locals, // binds to selected frame
|
locals, // binds to selected frame
|
||||||
// TODO: special IP/SP source? so that scope selection can apply to that?
|
// TODO: special IP/SP source? so that scope selection can apply to that?
|
||||||
// variable,
|
variable,
|
||||||
// const,
|
// const,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -321,8 +321,12 @@ namespace dbgui::data
|
|||||||
uint16_t idx;
|
uint16_t idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Variable {
|
||||||
|
std::string expr_path;
|
||||||
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
std::variant<std::monostate, Reg> data;
|
std::variant<std::monostate, Reg, Variable> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Disassemble
|
struct Disassemble
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ void Frontend::handle_msgs()
|
|||||||
for (size_t i = 0; i < result.nodes.size(); ++i)
|
for (size_t i = 0; i < result.nodes.size(); ++i)
|
||||||
{
|
{
|
||||||
uint16_t idx = result.nodes[i].idx;
|
uint16_t idx = result.nodes[i].idx;
|
||||||
|
printf("Got data result for %u\n", idx);
|
||||||
if (this->target->data_res_nodes.size() <= idx)
|
if (this->target->data_res_nodes.size() <= idx)
|
||||||
{
|
{
|
||||||
this->target->data_res_nodes.resize(idx + 1);
|
this->target->data_res_nodes.resize(idx + 1);
|
||||||
|
|||||||
@@ -1015,42 +1015,106 @@ bool WatchWindow::draw(Frontend &frontend)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ImGuiTableFlags_SizingFixedFit
|
// ImGuiTableFlags_SizingFixedFit
|
||||||
if (ImGui::BeginTable("##Variables", 2, ImGuiTableFlags_RowBg))
|
if (ImGui::BeginTable("##Variables", 2,
|
||||||
|
ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable))
|
||||||
{
|
{
|
||||||
ImGui::TableSetupColumn("Name");
|
ImGui::TableSetupColumn("Name");
|
||||||
ImGui::TableSetupColumn("Value");
|
ImGui::TableSetupColumn("Value");
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
auto locals_idx = frontend.target->data_idx_for_src_id(this->locals_src_id);
|
ImGui::TableNextRow();
|
||||||
if (locals_idx)
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::PushID("TTTTTT");
|
||||||
|
if (ImGui::TreeNodeEx("Locals", ImGuiTreeNodeFlags_SpanFullWidth))
|
||||||
{
|
{
|
||||||
const auto &local_node = *frontend.target->data_res_nodes[*locals_idx];
|
auto locals_idx =
|
||||||
const auto &locals_data = local_node.vec_data();
|
frontend.target->data_idx_for_src_id(this->locals_src_id);
|
||||||
size_t cur_off = 0;
|
if (locals_idx)
|
||||||
size_t cur_idx = 0;
|
|
||||||
while (cur_off < locals_data.size())
|
|
||||||
{
|
{
|
||||||
if (cur_off + 2 > locals_data.size())
|
const auto &local_node = *frontend.target->data_res_nodes[*locals_idx];
|
||||||
|
const auto &locals_data = local_node.vec_data();
|
||||||
|
size_t cur_off = 0;
|
||||||
|
size_t cur_idx = 0;
|
||||||
|
while (cur_off < locals_data.size())
|
||||||
{
|
{
|
||||||
break;
|
if (cur_off + 2 > locals_data.size())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto str_len =
|
||||||
|
*reinterpret_cast<const uint16_t *>(locals_data.data() + cur_off);
|
||||||
|
if (cur_off + 2 + str_len > locals_data.size())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name = std::string_view{
|
||||||
|
reinterpret_cast<const char *>(locals_data.data() + cur_off + 2),
|
||||||
|
str_len};
|
||||||
|
auto node_idx = local_node.children[cur_idx];
|
||||||
|
this->draw_value(frontend,
|
||||||
|
frontend.target->data_res_nodes[node_idx]->type_id,
|
||||||
|
name, node_idx, 0);
|
||||||
|
|
||||||
|
cur_idx += 1;
|
||||||
|
cur_off += 2 + str_len;
|
||||||
}
|
}
|
||||||
auto str_len =
|
}
|
||||||
*reinterpret_cast<const uint16_t *>(locals_data.data() + cur_off);
|
ImGui::TreePop();
|
||||||
if (cur_off + 2 + str_len > locals_data.size())
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
|
||||||
|
if (ImGui::InputText("##EXTRASLOT", this->extra_slot_path_buf,
|
||||||
|
sizeof(this->extra_slot_path_buf),
|
||||||
|
ImGuiInputTextFlags_AutoSelectAll
|
||||||
|
| ImGuiInputTextFlags_EnterReturnsTrue)
|
||||||
|
&& ImGui::IsItemDeactivatedAfterEdit())
|
||||||
|
{
|
||||||
|
if (this->extra_slot_bak != this->extra_slot_path_buf)
|
||||||
|
{
|
||||||
|
if (this->extra_slot_id)
|
||||||
{
|
{
|
||||||
break;
|
frontend.target->backend->remove_data_node(*this->extra_slot_id);
|
||||||
|
this->extra_slot_id = {};
|
||||||
}
|
}
|
||||||
|
this->extra_slot_bak = this->extra_slot_path_buf;
|
||||||
|
if (this->extra_slot_bak != "")
|
||||||
|
{
|
||||||
|
auto id = frontend.target->data_node_id++;
|
||||||
|
this->extra_slot_id = id;
|
||||||
|
|
||||||
auto name = std::string_view{
|
using namespace data::source;
|
||||||
reinterpret_cast<const char *>(locals_data.data() + cur_off + 2),
|
frontend.target->backend->add_data_node(
|
||||||
str_len};
|
Node{.id = id,
|
||||||
auto node_idx = local_node.children[cur_idx];
|
.type = Node::Type::source,
|
||||||
this->draw_value(frontend,
|
.data = Source{.type = Source::Type::variable,
|
||||||
frontend.target->data_res_nodes[node_idx]->type_id,
|
.data = Source::Variable{
|
||||||
name, node_idx, 0);
|
.expr_path = this->extra_slot_bak}}});
|
||||||
|
}
|
||||||
cur_idx += 1;
|
}
|
||||||
cur_off += 2 + str_len;
|
}
|
||||||
|
if (this->extra_slot_id)
|
||||||
|
{
|
||||||
|
auto res_idx = frontend.target->data_idx_for_src_id(*this->extra_slot_id);
|
||||||
|
if (res_idx)
|
||||||
|
{
|
||||||
|
const auto &node = *frontend.target->data_res_nodes[*res_idx];
|
||||||
|
if (!node.success || node.children.size() != 1)
|
||||||
|
{
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextDisabled("<not available>");
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
//printf("Extratypeid: %u", node.type_id.type);
|
||||||
|
const auto &child_node =
|
||||||
|
*frontend.target->data_res_nodes[node.children[0]];
|
||||||
|
//printf("Child: %u\n", child_node.type_id.type);
|
||||||
|
this->draw_value(frontend, child_node.type_id, this->extra_slot_bak,
|
||||||
|
node.children[0], 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ namespace dbgui::frontend
|
|||||||
bool first;
|
bool first;
|
||||||
|
|
||||||
size_t locals_src_id;
|
size_t locals_src_id;
|
||||||
|
std::optional<size_t> extra_slot_id;
|
||||||
|
char extra_slot_path_buf[256] = {0};
|
||||||
|
std::string extra_slot_bak = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Window
|
struct Window
|
||||||
|
|||||||
Reference in New Issue
Block a user