add way to get the address of variable

This commit is contained in:
T0b1
2024-05-06 04:10:13 +02:00
parent 53899ef3c3
commit eb98d911f6
7 changed files with 200 additions and 104 deletions

View File

@@ -1824,14 +1824,16 @@ std::optional<std::pair<uint16_t, size_t>>
return check_single_res_changed(std::move(res_node)); 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) if (!res_idx)
{ {
return check_single_res_changed(std::move(res_node)); return check_single_res_changed(std::move(res_node));
} }
printf("Got res for %s: %u (%u)\n", info.expr_path.c_str(), *res_idx, spdlog::trace(
_data_res[*res_idx]->node.type_id.type); "Got res for {}: {} ({})", info.expr_path, *res_idx,
static_cast<uint8_t>(_data_res[*res_idx]->node.type_id.type));
res_node.success = true; res_node.success = true;
res_node.children.push_back(*res_idx); res_node.children.push_back(*res_idx);
return check_single_res_changed(std::move(res_node)); return check_single_res_changed(std::move(res_node));
@@ -2133,7 +2135,7 @@ std::optional<std::pair<uint16_t, size_t>>
} }
printf("Got local %s\n", name); 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) if (!res_idx)
{ {
printf("No result\n"); printf("No result\n");
@@ -2958,7 +2960,8 @@ bool LLDBBackend::is_type_equal(data::type_info::TypeID type_id,
std::optional<dbgui::data::result::NodeIdx> std::optional<dbgui::data::result::NodeIdx>
LLDBBackend::build_nodes_for_var(lldb::SBValue &val, LLDBBackend::build_nodes_for_var(lldb::SBValue &val,
std::vector<data::result::Node> &to_send) std::vector<data::result::Node> &to_send,
bool address_of_or_pointer)
{ {
using namespace lldb; using namespace lldb;
using namespace data; using namespace data;
@@ -2983,7 +2986,8 @@ std::optional<dbgui::data::result::NodeIdx>
for (auto i = 0; i < _var_cache.size(); ++i) for (auto i = 0; i < _var_cache.size(); ++i)
{ {
auto &entry = _var_cache[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; continue;
} }
@@ -3012,7 +3016,8 @@ std::optional<dbgui::data::result::NodeIdx>
for (auto i = 0; i < _var_cache.size(); ++i) for (auto i = 0; i < _var_cache.size(); ++i)
{ {
auto &entry = _var_cache[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; continue;
} }
@@ -3084,12 +3089,14 @@ std::optional<dbgui::data::result::NodeIdx>
} }
auto node_idx = *_var_cache[*cache_entry].cached_node; auto node_idx = *_var_cache[*cache_entry].cached_node;
_var_cache[*cache_entry].used = true; _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; 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( _var_cache.push_back(
VarCacheEntry{.lldb_val = val, VarCacheEntry{.lldb_val = val,
.sym_ctx = val.GetFrame().GetSymbolContext(true), .sym_ctx = val.GetFrame().GetSymbolContext(true),
@@ -3101,7 +3108,8 @@ std::optional<dbgui::data::result::NodeIdx>
} }
dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached( dbgui::data::result::NodeIdx LLDBBackend::build_nodes_for_var_uncached(
lldb::SBValue &val, std::vector<data::result::Node> &to_send) lldb::SBValue &val, std::vector<data::result::Node> &to_send,
bool address_of_or_pointer)
{ {
auto lldb_type = val.GetType(); auto lldb_type = val.GetType();
auto type_id = this->build_type_from_lldb_type(lldb_type); 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 // TODO: error handling
auto err = lldb::SBError{}; auto err = lldb::SBError{};
switch (no_alias_type.type) if (address_of_or_pointer)
{ {
using enum data::type_info::Type; if (no_alias_type.type == data::type_info::Type::ptr)
case _bool:
case u8:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt8(err, 0));
break;
case u16:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
break;
case u32:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
break;
case u64:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
break;
case i8:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
break;
case i16:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
break;
case i32:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
break;
case i64:
res_node.data = static_cast<uint64_t>(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<uint8_t>{}; res_node.data = static_cast<uint64_t>(var_data.GetAddress(err, 0));
auto &vec = res_node.vec_data(); } else
auto size = var_data.GetByteSize(); {
vec.resize(size); // so we don't need to create a new type for the pointer i think so just replace the node type
var_data.ReadRawData(err, 0, vec.data(), size); res_node.type_id =
break; 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<size_t>::max()};
return res_idx;
}
res_node.data = static_cast<uint64_t>(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<uint64_t>(var_data.GetUnsignedInt8(err, 0));
break;
case u16:
res_node.data =
static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
break;
case u32:
res_node.data =
static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
break;
case u64:
res_node.data =
static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
break;
case i8:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
break;
case i16:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
break;
case i32:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
break;
case i64:
res_node.data = static_cast<uint64_t>(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<uint8_t>{};
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( void LLDBBackend::build_nodes_for_var_cached(
lldb::SBValue &val, data::result::NodeIdx cache_idx, lldb::SBValue &val, data::result::NodeIdx cache_idx,
std::vector<data::result::Node> &to_send) std::vector<data::result::Node> &to_send, bool address_of_or_pointer)
{ {
auto lldb_type = val.GetType(); auto lldb_type = val.GetType();
// auto type_id = this->build_type_from_lldb_type(lldb_type); // 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); _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 // TODO: error handling
auto err = lldb::SBError{}; auto err = lldb::SBError{};
switch (no_alias_type.type)
{
using enum data::type_info::Type;
case _bool: if (address_of_or_pointer)
case u8: {
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt8(err, 0)); if (no_alias_type.type == data::type_info::Type::ptr)
break;
case u16:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
break;
case u32:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
break;
case u64:
res_node.data = static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
break;
case i8:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
break;
case i16:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
break;
case i32:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
break;
case i64:
res_node.data = static_cast<uint64_t>(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<uint8_t>{}; res_node.data = static_cast<uint64_t>(var_data.GetAddress(err, 0));
auto &vec = res_node.vec_data(); } else
auto size = var_data.GetByteSize(); {
vec.resize(size); // so we don't need to create a new type for the pointer i think so just replace the node type
var_data.ReadRawData(err, 0, vec.data(), size); res_node.type_id =
break; 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<uint64_t>(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<uint64_t>(var_data.GetUnsignedInt8(err, 0));
break;
case u16:
res_node.data =
static_cast<uint64_t>(var_data.GetUnsignedInt16(err, 0));
break;
case u32:
res_node.data =
static_cast<uint64_t>(var_data.GetUnsignedInt32(err, 0));
break;
case u64:
res_node.data =
static_cast<uint64_t>(var_data.GetUnsignedInt64(err, 0));
break;
case i8:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt8(err, 0));
break;
case i16:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt16(err, 0));
break;
case i32:
res_node.data = static_cast<uint64_t>(var_data.GetSignedInt32(err, 0));
break;
case i64:
res_node.data = static_cast<uint64_t>(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<uint8_t>{};
auto &vec = res_node.vec_data();
auto size = var_data.GetByteSize();
vec.resize(size);
var_data.ReadRawData(err, 0, vec.data(), size);
break;
}
} }
} }

View File

@@ -86,6 +86,7 @@ namespace dbgui::backend
bool used; bool used;
bool bool
global_or_static; // need to only compare compilation unit and module global_or_static; // need to only compare compilation unit and module
bool address_of_or_pointer;
std::optional<data::result::NodeIdx> cached_node; std::optional<data::result::NodeIdx> cached_node;
}; };
@@ -135,13 +136,16 @@ namespace dbgui::backend
std::optional<data::result::NodeIdx> std::optional<data::result::NodeIdx>
build_nodes_for_var(lldb::SBValue &val, build_nodes_for_var(lldb::SBValue &val,
std::vector<data::result::Node> &to_send); std::vector<data::result::Node> &to_send,
bool address_of_or_pointer);
data::result::NodeIdx data::result::NodeIdx
build_nodes_for_var_uncached(lldb::SBValue &, build_nodes_for_var_uncached(lldb::SBValue &,
std::vector<data::result::Node> &to_send); std::vector<data::result::Node> &to_send,
bool address_of_or_pointer);
void build_nodes_for_var_cached(lldb::SBValue &, void build_nodes_for_var_cached(lldb::SBValue &,
data::result::NodeIdx cache_idx, data::result::NodeIdx cache_idx,
std::vector<data::result::Node> &to_send); std::vector<data::result::Node> &to_send,
bool address_of_or_pointer);
void clear_unused_vars_from_cache(); void clear_unused_vars_from_cache();

View File

@@ -256,6 +256,7 @@ namespace dbgui::data
Type type; Type type;
TypeID enum_base; TypeID enum_base;
uint64_t byte_size; 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 display_name;
std::string internal_name; std::string internal_name;
// sike, lldb doesnt give this to us // sike, lldb doesnt give this to us
@@ -324,6 +325,8 @@ namespace dbgui::data
struct Variable struct Variable
{ {
std::string expr_path; 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; Type type;

View File

@@ -1119,13 +1119,15 @@ bool WatchWindow::draw(Frontend &frontend)
if (slot.buf[0] != '\0') if (slot.buf[0] != '\0')
{ {
frontend.target->backend->remove_data_node(slot.id); frontend.target->backend->remove_data_node(slot.id);
using namespace data::source; using namespace data::source;
frontend.target->backend->add_data_node(Node{ frontend.target->backend->add_data_node(
.id = slot.id, Node{.id = slot.id,
.type = Node::Type::source, .type = Node::Type::source,
.data = .data = Source{.type = Source::Type::variable,
Source{.type = Source::Type::variable, .data = Source::Variable{
.data = Source::Variable{.expr_path = slot.buf}}}); .expr_path = slot.buf,
.address_of_or_pointer = false}}});
} }
slot.bak = slot.buf; slot.bak = slot.buf;
@@ -1172,14 +1174,23 @@ bool WatchWindow::draw(Frontend &frontend)
{ {
if (this->add_slot_buf[0] != '\0') 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; using namespace data::source;
frontend.target->backend->add_data_node(Node{ frontend.target->backend->add_data_node(Node{
.id = id, .id = id,
.type = Node::Type::source, .type = Node::Type::source,
.data = .data = Source{.type = Source::Type::variable,
Source{.type = Source::Type::variable, .data = Source::Variable{.expr_path = expr_path_buf,
.data = Source::Variable{.expr_path = this->add_slot_buf}}}); .address_of_or_pointer =
address_of_or_pointer}}});
extra_slots.push_back(ExtraSlot{.id = id, .bak = this->add_slot_buf}); extra_slots.push_back(ExtraSlot{.id = id, .bak = this->add_slot_buf});
memcpy(extra_slots.back().buf, this->add_slot_buf, memcpy(extra_slots.back().buf, this->add_slot_buf,
sizeof(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) for (size_t i = 0; i < el_count; ++i)
{ {
std::snprintf(buf, sizeof(buf), "[%lu]", 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, this->draw_value(frontend, member_ty_id, buf, node_idx,
off + member_off, expr_path); off + member_off, expr_path);
assert(expr_path.size() == expr_path_size);
member_off += member_size; member_off += member_size;
} }

View File

@@ -139,8 +139,9 @@ namespace dbgui::frontend
struct ExprPathPart struct ExprPathPart
{ {
std::string_view ident; std::string_view ident;
bool deref = false; bool deref = false;
bool array = false; bool array = false;
uint64_t array_idx = 0;
}; };
bool draw(Frontend &); bool draw(Frontend &);

BIN
tmp/main

Binary file not shown.

View File

@@ -3,7 +3,7 @@
namespace { namespace {
struct MyType { struct MyType {
int data; int data[3];
}; };
} }
@@ -11,11 +11,11 @@ void helper_fn();
void helper_fn2(); void helper_fn2();
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
MyType tmp = MyType{10}; MyType tmp = MyType{{10, 5, 19}};
while (tmp.data != 0) { while (tmp.data[0] != 0) {
helper_fn(); helper_fn();
helper_fn2(); helper_fn2();
tmp.data--; tmp.data[0]--;
} }
return 0; return 0;
} }