diff --git a/src/backend/lldb/lldb_backend.cpp b/src/backend/lldb/lldb_backend.cpp index 6827ace..7d9db97 100644 --- a/src/backend/lldb/lldb_backend.cpp +++ b/src/backend/lldb/lldb_backend.cpp @@ -1510,9 +1510,21 @@ void LLDBBackend::remove_data_node(size_t id) exit(1); } _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 to_delete{}; - to_delete.push_back(id); + to_delete.push_back(res_it->second); size_t old_size = 0; while (to_delete.size() != old_size) { @@ -1539,8 +1551,6 @@ void LLDBBackend::remove_data_node(size_t id) this->send_remove_data_node(idx); _data_res[idx] = {}; } - - _dag_linear_valid = false; } void LLDBBackend::check_data_changes() @@ -1571,6 +1581,19 @@ void LLDBBackend::check_data_changes() auto res_vec = std::vector{}; 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()) { // TODO: queue and send at once to prevent UI lag? @@ -1733,6 +1756,54 @@ std::optional> .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(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; } diff --git a/src/backend/lldb/lldb_backend.h b/src/backend/lldb/lldb_backend.h index 23591ab..bfd78d9 100644 --- a/src/backend/lldb/lldb_backend.h +++ b/src/backend/lldb/lldb_backend.h @@ -175,6 +175,8 @@ namespace dbgui::backend bool _dag_linear_valid = false; // util::DAG _data_res_dag = {}; std::vector> _data_res = {}; + std::unordered_map _data_src_id_to_res_idx = + {}; std::vector _locals = {}; std::optional _locals_node = {}; diff --git a/src/data.h b/src/data.h index 49aa5d5..35bcbef 100644 --- a/src/data.h +++ b/src/data.h @@ -310,7 +310,7 @@ namespace dbgui::data frame_ip, // binds the selected frame locals, // binds to selected frame // TODO: special IP/SP source? so that scope selection can apply to that? - // variable, + variable, // const, }; @@ -321,8 +321,12 @@ namespace dbgui::data uint16_t idx; }; + struct Variable { + std::string expr_path; + }; + Type type; - std::variant data; + std::variant data; }; struct Disassemble diff --git a/src/frontend/frontend.cpp b/src/frontend/frontend.cpp index ba8f0c3..b8a9ace 100644 --- a/src/frontend/frontend.cpp +++ b/src/frontend/frontend.cpp @@ -352,6 +352,7 @@ void Frontend::handle_msgs() for (size_t i = 0; i < result.nodes.size(); ++i) { uint16_t idx = result.nodes[i].idx; + printf("Got data result for %u\n", idx); if (this->target->data_res_nodes.size() <= idx) { this->target->data_res_nodes.resize(idx + 1); diff --git a/src/frontend/window.cpp b/src/frontend/window.cpp index 1de9c23..2239f38 100644 --- a/src/frontend/window.cpp +++ b/src/frontend/window.cpp @@ -1015,42 +1015,106 @@ bool WatchWindow::draw(Frontend &frontend) } // ImGuiTableFlags_SizingFixedFit - if (ImGui::BeginTable("##Variables", 2, ImGuiTableFlags_RowBg)) + if (ImGui::BeginTable("##Variables", 2, + ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable)) { ImGui::TableSetupColumn("Name"); ImGui::TableSetupColumn("Value"); ImGui::TableHeadersRow(); - auto locals_idx = frontend.target->data_idx_for_src_id(this->locals_src_id); - if (locals_idx) + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::PushID("TTTTTT"); + if (ImGui::TreeNodeEx("Locals", ImGuiTreeNodeFlags_SpanFullWidth)) { - 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()) + auto locals_idx = + frontend.target->data_idx_for_src_id(this->locals_src_id); + if (locals_idx) { - 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(locals_data.data() + cur_off); + if (cur_off + 2 + str_len > locals_data.size()) + { + break; + } + + auto name = std::string_view{ + reinterpret_cast(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(locals_data.data() + cur_off); - if (cur_off + 2 + str_len > locals_data.size()) + } + ImGui::TreePop(); + } + + 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{ - reinterpret_cast(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; + using namespace data::source; + frontend.target->backend->add_data_node( + Node{.id = id, + .type = Node::Type::source, + .data = Source{.type = Source::Type::variable, + .data = Source::Variable{ + .expr_path = this->extra_slot_bak}}}); + } + } + } + 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(""); + } 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); + } } } diff --git a/src/frontend/window.h b/src/frontend/window.h index c993178..79d90b3 100644 --- a/src/frontend/window.h +++ b/src/frontend/window.h @@ -136,6 +136,9 @@ namespace dbgui::frontend bool first; size_t locals_src_id; + std::optional extra_slot_id; + char extra_slot_path_buf[256] = {0}; + std::string extra_slot_bak = ""; }; struct Window