diff --git a/src/backend/lldb/lldb_backend.cpp b/src/backend/lldb/lldb_backend.cpp index 25e9aad..f0f25f9 100644 --- a/src/backend/lldb/lldb_backend.cpp +++ b/src/backend/lldb/lldb_backend.cpp @@ -1824,14 +1824,16 @@ std::optional> return check_single_res_changed(std::move(res_node)); } - auto res_idx = this->build_nodes_for_var(var, data_res); + auto res_idx = this->build_nodes_for_var(var, data_res, + info.address_of_or_pointer); 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); + spdlog::trace( + "Got res for {}: {} ({})", info.expr_path, *res_idx, + static_cast(_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)); @@ -2133,7 +2135,7 @@ std::optional> } printf("Got local %s\n", name); - auto res_idx = this->build_nodes_for_var(var, data_res); + auto res_idx = this->build_nodes_for_var(var, data_res, false); if (!res_idx) { printf("No result\n"); @@ -2958,7 +2960,8 @@ bool LLDBBackend::is_type_equal(data::type_info::TypeID type_id, std::optional LLDBBackend::build_nodes_for_var(lldb::SBValue &val, - std::vector &to_send) + std::vector &to_send, + bool address_of_or_pointer) { using namespace lldb; using namespace data; @@ -2983,7 +2986,8 @@ std::optional for (auto i = 0; i < _var_cache.size(); ++i) { auto &entry = _var_cache[i]; - if (!entry.global_or_static) + if (!entry.global_or_static + || entry.address_of_or_pointer != address_of_or_pointer) { continue; } @@ -3012,7 +3016,8 @@ std::optional for (auto i = 0; i < _var_cache.size(); ++i) { auto &entry = _var_cache[i]; - if (entry.global_or_static) + if (entry.global_or_static + || entry.address_of_or_pointer != address_of_or_pointer) { continue; } @@ -3084,12 +3089,14 @@ std::optional } auto node_idx = *_var_cache[*cache_entry].cached_node; _var_cache[*cache_entry].used = true; - this->build_nodes_for_var_cached(val, node_idx, to_send); + this->build_nodes_for_var_cached(val, node_idx, to_send, + address_of_or_pointer); return node_idx; } - auto idx = this->build_nodes_for_var_uncached(val, to_send); + auto idx = + this->build_nodes_for_var_uncached(val, to_send, address_of_or_pointer); _var_cache.push_back( VarCacheEntry{.lldb_val = val, .sym_ctx = val.GetFrame().GetSymbolContext(true), @@ -3101,7 +3108,8 @@ std::optional } dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached( - lldb::SBValue &val, std::vector &to_send) + lldb::SBValue &val, std::vector &to_send, + bool address_of_or_pointer) { auto lldb_type = val.GetType(); auto type_id = this->build_type_from_lldb_type(lldb_type); @@ -3131,45 +3139,77 @@ dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached( // TODO: error handling auto err = lldb::SBError{}; - switch (no_alias_type.type) + if (address_of_or_pointer) { - using enum data::type_info::Type; - - case _bool: - case u8: - res_node.data = static_cast(var_data.GetUnsignedInt8(err, 0)); - break; - case u16: - res_node.data = static_cast(var_data.GetUnsignedInt16(err, 0)); - break; - case u32: - res_node.data = static_cast(var_data.GetUnsignedInt32(err, 0)); - break; - case u64: - res_node.data = static_cast(var_data.GetUnsignedInt64(err, 0)); - break; - case i8: - res_node.data = static_cast(var_data.GetSignedInt8(err, 0)); - break; - case i16: - res_node.data = static_cast(var_data.GetSignedInt16(err, 0)); - break; - case i32: - res_node.data = static_cast(var_data.GetSignedInt32(err, 0)); - break; - case i64: - res_node.data = static_cast(var_data.GetSignedInt64(err, 0)); - break; - case f32: res_node.data = var_data.GetFloat(err, 0); break; - case f64: res_node.data = var_data.GetDouble(err, 0); break; - default: + if (no_alias_type.type == data::type_info::Type::ptr) { - res_node.data = std::vector{}; - auto &vec = res_node.vec_data(); - auto size = var_data.GetByteSize(); - vec.resize(size); - var_data.ReadRawData(err, 0, vec.data(), size); - break; + res_node.data = static_cast(var_data.GetAddress(err, 0)); + } else + { + // so we don't need to create a new type for the pointer i think so just replace the node type + res_node.type_id = + data::type_info::TypeID{.type = data::type_info::Type::ptr, + .sub_type = type_id.type, + .idx = type_id.idx}; + auto addr_of = val.AddressOf(); + auto data = addr_of.GetData(); + if (!data.IsValid()) + { + // copypasted from above + to_send.push_back(res_node); + _data_res[res_idx] = + CachedDataRes{.node = std::move(res_node), + .no_delete_on_src_delete = true, + .src_id = std::numeric_limits::max()}; + return res_idx; + } + res_node.data = static_cast(data.GetAddress(err, 0)); + } + } else + { + switch (no_alias_type.type) + { + using enum data::type_info::Type; + + case _bool: + case u8: + res_node.data = static_cast(var_data.GetUnsignedInt8(err, 0)); + break; + case u16: + res_node.data = + static_cast(var_data.GetUnsignedInt16(err, 0)); + break; + case u32: + res_node.data = + static_cast(var_data.GetUnsignedInt32(err, 0)); + break; + case u64: + res_node.data = + static_cast(var_data.GetUnsignedInt64(err, 0)); + break; + case i8: + res_node.data = static_cast(var_data.GetSignedInt8(err, 0)); + break; + case i16: + res_node.data = static_cast(var_data.GetSignedInt16(err, 0)); + break; + case i32: + res_node.data = static_cast(var_data.GetSignedInt32(err, 0)); + break; + case i64: + res_node.data = static_cast(var_data.GetSignedInt64(err, 0)); + break; + case f32: res_node.data = var_data.GetFloat(err, 0); break; + case f64: res_node.data = var_data.GetDouble(err, 0); break; + default: + { + res_node.data = std::vector{}; + auto &vec = res_node.vec_data(); + auto size = var_data.GetByteSize(); + vec.resize(size); + var_data.ReadRawData(err, 0, vec.data(), size); + break; + } } } @@ -3188,7 +3228,7 @@ dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached( void LLDBBackend::build_nodes_for_var_cached( lldb::SBValue &val, data::result::NodeIdx cache_idx, - std::vector &to_send) + std::vector &to_send, bool address_of_or_pointer) { auto lldb_type = val.GetType(); // auto type_id = this->build_type_from_lldb_type(lldb_type); @@ -3216,47 +3256,81 @@ void LLDBBackend::build_nodes_for_var_cached( _types[no_alias_type.idx]->second.member_types); } + // TODO: this is copypasted from build_nodes_for_var_uncached so that should be consolidated in the future // TODO: error handling auto err = lldb::SBError{}; - switch (no_alias_type.type) - { - using enum data::type_info::Type; - case _bool: - case u8: - res_node.data = static_cast(var_data.GetUnsignedInt8(err, 0)); - break; - case u16: - res_node.data = static_cast(var_data.GetUnsignedInt16(err, 0)); - break; - case u32: - res_node.data = static_cast(var_data.GetUnsignedInt32(err, 0)); - break; - case u64: - res_node.data = static_cast(var_data.GetUnsignedInt64(err, 0)); - break; - case i8: - res_node.data = static_cast(var_data.GetSignedInt8(err, 0)); - break; - case i16: - res_node.data = static_cast(var_data.GetSignedInt16(err, 0)); - break; - case i32: - res_node.data = static_cast(var_data.GetSignedInt32(err, 0)); - break; - case i64: - res_node.data = static_cast(var_data.GetSignedInt64(err, 0)); - break; - case f32: res_node.data = var_data.GetFloat(err, 0); break; - case f64: res_node.data = var_data.GetDouble(err, 0); break; - default: + if (address_of_or_pointer) + { + if (no_alias_type.type == data::type_info::Type::ptr) { - res_node.data = std::vector{}; - auto &vec = res_node.vec_data(); - auto size = var_data.GetByteSize(); - vec.resize(size); - var_data.ReadRawData(err, 0, vec.data(), size); - break; + res_node.data = static_cast(var_data.GetAddress(err, 0)); + } else + { + // so we don't need to create a new type for the pointer i think so just replace the node type + res_node.type_id = + data::type_info::TypeID{.type = data::type_info::Type::ptr, + .sub_type = type_id.type, + .idx = type_id.idx}; + auto addr_of = val.AddressOf(); + auto data = addr_of.GetData(); + if (!data.IsValid()) + { + // copypasted from above + if (_data_res[cache_idx]->node.success) + { + to_send.push_back(res_node); + _data_res[cache_idx]->node.success = false; + } + return; + } + res_node.data = static_cast(data.GetAddress(err, 0)); + } + } else + { + switch (no_alias_type.type) + { + using enum data::type_info::Type; + + case _bool: + case u8: + res_node.data = static_cast(var_data.GetUnsignedInt8(err, 0)); + break; + case u16: + res_node.data = + static_cast(var_data.GetUnsignedInt16(err, 0)); + break; + case u32: + res_node.data = + static_cast(var_data.GetUnsignedInt32(err, 0)); + break; + case u64: + res_node.data = + static_cast(var_data.GetUnsignedInt64(err, 0)); + break; + case i8: + res_node.data = static_cast(var_data.GetSignedInt8(err, 0)); + break; + case i16: + res_node.data = static_cast(var_data.GetSignedInt16(err, 0)); + break; + case i32: + res_node.data = static_cast(var_data.GetSignedInt32(err, 0)); + break; + case i64: + res_node.data = static_cast(var_data.GetSignedInt64(err, 0)); + break; + case f32: res_node.data = var_data.GetFloat(err, 0); break; + case f64: res_node.data = var_data.GetDouble(err, 0); break; + default: + { + res_node.data = std::vector{}; + auto &vec = res_node.vec_data(); + auto size = var_data.GetByteSize(); + vec.resize(size); + var_data.ReadRawData(err, 0, vec.data(), size); + break; + } } } diff --git a/src/backend/lldb/lldb_backend.h b/src/backend/lldb/lldb_backend.h index 5125071..6d98ee4 100644 --- a/src/backend/lldb/lldb_backend.h +++ b/src/backend/lldb/lldb_backend.h @@ -86,6 +86,7 @@ namespace dbgui::backend bool used; bool global_or_static; // need to only compare compilation unit and module + bool address_of_or_pointer; std::optional cached_node; }; @@ -135,13 +136,16 @@ namespace dbgui::backend std::optional build_nodes_for_var(lldb::SBValue &val, - std::vector &to_send); + std::vector &to_send, + bool address_of_or_pointer); data::result::NodeIdx build_nodes_for_var_uncached(lldb::SBValue &, - std::vector &to_send); + std::vector &to_send, + bool address_of_or_pointer); void build_nodes_for_var_cached(lldb::SBValue &, data::result::NodeIdx cache_idx, - std::vector &to_send); + std::vector &to_send, + bool address_of_or_pointer); void clear_unused_vars_from_cache(); diff --git a/src/data.h b/src/data.h index 9ff7756..93c0f73 100644 --- a/src/data.h +++ b/src/data.h @@ -256,6 +256,7 @@ namespace dbgui::data Type type; TypeID enum_base; uint64_t byte_size; + // TODO: maybe we want a string array somewhere else? Harder to garbage collect but we save some space here std::string display_name; std::string internal_name; // sike, lldb doesnt give this to us @@ -324,6 +325,8 @@ namespace dbgui::data struct Variable { std::string expr_path; + // if this is set we want the address of whatever we got or the pointer value in case what we have is a pointer + bool address_of_or_pointer = false; }; Type type; diff --git a/src/frontend/window.cpp b/src/frontend/window.cpp index 7558ae4..ac6f137 100644 --- a/src/frontend/window.cpp +++ b/src/frontend/window.cpp @@ -1119,13 +1119,15 @@ bool WatchWindow::draw(Frontend &frontend) if (slot.buf[0] != '\0') { frontend.target->backend->remove_data_node(slot.id); + using namespace data::source; - frontend.target->backend->add_data_node(Node{ - .id = slot.id, - .type = Node::Type::source, - .data = - Source{.type = Source::Type::variable, - .data = Source::Variable{.expr_path = slot.buf}}}); + frontend.target->backend->add_data_node( + Node{.id = slot.id, + .type = Node::Type::source, + .data = Source{.type = Source::Type::variable, + .data = Source::Variable{ + .expr_path = slot.buf, + .address_of_or_pointer = false}}}); } slot.bak = slot.buf; @@ -1172,14 +1174,23 @@ bool WatchWindow::draw(Frontend &frontend) { if (this->add_slot_buf[0] != '\0') { - auto id = frontend.target->data_node_id++; + auto id = frontend.target->data_node_id++; + const auto *expr_path_buf = this->add_slot_buf; + bool address_of_or_pointer = false; + if (expr_path_buf[0] == '+') + { + address_of_or_pointer = true; + ++expr_path_buf; + } + 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->add_slot_buf}}}); + .data = Source{.type = Source::Type::variable, + .data = Source::Variable{.expr_path = expr_path_buf, + .address_of_or_pointer = + address_of_or_pointer}}}); extra_slots.push_back(ExtraSlot{.id = id, .bak = this->add_slot_buf}); memcpy(extra_slots.back().buf, this->add_slot_buf, sizeof(this->add_slot_buf)); @@ -1402,8 +1413,11 @@ void WatchWindow::draw_value(Frontend &frontend, for (size_t i = 0; i < el_count; ++i) { std::snprintf(buf, sizeof(buf), "[%lu]", i); + auto expr_path_size = expr_path.size(); + expr_path.back().array_idx = i; this->draw_value(frontend, member_ty_id, buf, node_idx, off + member_off, expr_path); + assert(expr_path.size() == expr_path_size); member_off += member_size; } diff --git a/src/frontend/window.h b/src/frontend/window.h index 699ece4..f604bc6 100644 --- a/src/frontend/window.h +++ b/src/frontend/window.h @@ -139,8 +139,9 @@ namespace dbgui::frontend struct ExprPathPart { std::string_view ident; - bool deref = false; - bool array = false; + bool deref = false; + bool array = false; + uint64_t array_idx = 0; }; bool draw(Frontend &); diff --git a/tmp/main b/tmp/main index 6506200..f2f2a67 100755 Binary files a/tmp/main and b/tmp/main differ diff --git a/tmp/main.cpp b/tmp/main.cpp index 304f70c..0214b35 100644 --- a/tmp/main.cpp +++ b/tmp/main.cpp @@ -3,7 +3,7 @@ namespace { struct MyType { - int data; + int data[3]; }; } @@ -11,11 +11,11 @@ void helper_fn(); void helper_fn2(); int main(int argc, char* argv[]) { - MyType tmp = MyType{10}; - while (tmp.data != 0) { + MyType tmp = MyType{{10, 5, 19}}; + while (tmp.data[0] != 0) { helper_fn(); helper_fn2(); - tmp.data--; + tmp.data[0]--; } return 0; }