add basic array sizing with constant size, tho the parsing is probably not correct
this should just be a normal array index also missing handling to correctly construct the expr path when accessing pointers (maybe just make this node based in the future?)
This commit is contained in:
@@ -143,9 +143,11 @@ void LLDBBackend::handle_state_change(lldb::StateType state)
|
||||
{
|
||||
spdlog::trace("Got initial state change: {}", static_cast<uint32_t>(state));
|
||||
|
||||
if (state != lldb::StateType::eStateStopped) {
|
||||
if (state != lldb::StateType::eStateStopped)
|
||||
{
|
||||
// TODO: handle other stopped states, e.g. crashed
|
||||
spdlog::trace("Not handling initial state {}", static_cast<uint32_t>(state));
|
||||
spdlog::trace("Not handling initial state {}",
|
||||
static_cast<uint32_t>(state));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -286,8 +288,8 @@ void LLDBBackend::prepare_proc_info(
|
||||
}
|
||||
|
||||
auto frame = _process->GetThreadAtIndex(0).GetFrameAtIndex(0);
|
||||
/*const auto regs = frame.GetRegisters();
|
||||
const auto len = regs.GetSize();
|
||||
const auto regs = frame.GetRegisters();
|
||||
/*const auto len = regs.GetSize();
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
auto reg_or_set = regs.GetValueAtIndex(i);
|
||||
if (reg_or_set.GetValueType() == eValueTypeRegister) {
|
||||
@@ -1530,6 +1532,29 @@ void LLDBBackend::add_data_node(const data::source::Node &node)
|
||||
_data_dag.add_edge(node.id, src_id);
|
||||
break;
|
||||
}
|
||||
case read_array:
|
||||
{
|
||||
const auto &arr_node = std::get<data::source::ReadAsArray>(node.data);
|
||||
auto src_id = arr_node.addr_src_id;
|
||||
if (!_data_dag.nodes.contains(src_id))
|
||||
{
|
||||
printf("Invalid add sequence\n");
|
||||
exit(1);
|
||||
}
|
||||
_data_dag.add_edge(node.id, src_id);
|
||||
|
||||
if (!arr_node.is_const_size)
|
||||
{
|
||||
auto size_id = arr_node.size_src_id;
|
||||
if (!_data_dag.nodes.contains(size_id))
|
||||
{
|
||||
printf("Invalid add sequence\n");
|
||||
exit(1);
|
||||
}
|
||||
_data_dag.add_edge(node.id, size_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_dag_linear_valid = false;
|
||||
@@ -1681,6 +1706,7 @@ std::optional<std::pair<uint16_t, size_t>>
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: reserve the slot
|
||||
auto idx = this->_data_res.size();
|
||||
this->_data_res.resize(idx + 1);
|
||||
return idx;
|
||||
@@ -2292,6 +2318,121 @@ std::optional<std::pair<uint16_t, size_t>>
|
||||
.success = true,
|
||||
.data = std::move(buf)});
|
||||
}
|
||||
case read_array:
|
||||
{
|
||||
using namespace lldb;
|
||||
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();
|
||||
// reserve the slot
|
||||
_data_res[cache_idx] = CachedDataRes{.src_id = node.id};
|
||||
}
|
||||
|
||||
const auto &arr_node = std::get<data::source::ReadAsArray>(node.data);
|
||||
auto res_node = data::result::Node{
|
||||
.idx = cache_idx,
|
||||
.type_id = data::type_info::TypeID::none(),
|
||||
.success = false,
|
||||
};
|
||||
|
||||
size_t addr_id = arr_node.addr_src_id;
|
||||
uint16_t addr_parent_idx = *find_node_for_src_id(addr_id);
|
||||
if (!_data_res[addr_parent_idx]
|
||||
|| !_data_res[addr_parent_idx]->node.success
|
||||
|| _data_res[addr_parent_idx]->node.children.size() != 1)
|
||||
{
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
|
||||
uint16_t addr_idx = _data_res[addr_parent_idx]->node.children[0];
|
||||
|
||||
if (!_data_res[addr_idx] || !_data_res[addr_idx]->node.success
|
||||
|| _data_res[addr_idx]->node.type_id.type
|
||||
!= data::type_info::Type::ptr)
|
||||
{
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
|
||||
if (!arr_node.is_const_size)
|
||||
{
|
||||
spdlog::trace("read_as_array: non-const size not supported");
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
|
||||
const auto addr = _data_res[addr_idx]->node.get_primitive<uint64_t>(0);
|
||||
spdlog::trace("read_as_array: addr: {:X}", addr);
|
||||
|
||||
const auto pointee_type_idx = _data_res[addr_idx]->node.type_id.idx;
|
||||
if (!_types[pointee_type_idx])
|
||||
{
|
||||
spdlog::trace("Found no pointee type for read_as_array");
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
|
||||
auto pointee_type = _types[pointee_type_idx]->first;
|
||||
if (pointee_type.IsArrayType())
|
||||
{
|
||||
// TODO: should we do this until there is no array left?
|
||||
pointee_type = pointee_type.GetArrayElementType();
|
||||
}
|
||||
spdlog::trace("read_as_array: pointee_type valid?: {}",
|
||||
pointee_type.IsValid());
|
||||
|
||||
std::string type_buf;
|
||||
format_type(pointee_type, type_buf);
|
||||
spdlog::trace("read_as_array: pointee_type: {}", type_buf);
|
||||
|
||||
auto arr_type = pointee_type.GetArrayType(arr_node.size_const);
|
||||
|
||||
spdlog::trace("read_as_array: arr_type valid?: {}", arr_type.IsValid());
|
||||
type_buf.clear();
|
||||
format_type(arr_type, type_buf);
|
||||
spdlog::trace("read_as_array: arr_type: {}", type_buf);
|
||||
|
||||
char buf[128], buf2[32];
|
||||
/*std::snprintf(buf2, sizeof(buf2), "%zX", node.id);
|
||||
std::snprintf(buf, sizeof(buf), "*((%s *)0x%zX)", arr_type.GetName(),
|
||||
addr);
|
||||
auto arr_val = _target.CreateValueFromExpression(buf2, buf);
|
||||
if (!arr_val.IsValid())
|
||||
{
|
||||
spdlog::trace("read_as_array: arr_val not valid");
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}*/
|
||||
std::snprintf(buf, sizeof(buf), "(char*)0x%zX", addr);
|
||||
auto tmp_val = _target.CreateValueFromExpression("arr_tmp", buf);
|
||||
if (!tmp_val.IsValid())
|
||||
{
|
||||
spdlog::trace("read_as_array: tmp_val not valid");
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
|
||||
std::snprintf(buf, sizeof(buf), "%zX", node.id);
|
||||
auto arr_val = tmp_val.CreateValueFromAddress(buf, addr, arr_type);
|
||||
if (!arr_val.IsValid())
|
||||
{
|
||||
spdlog::trace("read_as_array: arr_val not valid");
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
//arr_val = arr_val.Cast(arr_type);
|
||||
|
||||
auto res_idx = this->build_nodes_for_var(arr_val, data_res, false);
|
||||
if (!res_idx)
|
||||
{
|
||||
return check_single_res_changed(std::move(res_node));
|
||||
}
|
||||
|
||||
spdlog::trace(
|
||||
"Got res for {}: {} ({})", node.id, *res_idx,
|
||||
static_cast<uint8_t>(_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));
|
||||
}
|
||||
}
|
||||
|
||||
printf("Unhandled data type\n");
|
||||
|
||||
12
src/data.h
12
src/data.h
@@ -355,6 +355,15 @@ namespace dbgui::data
|
||||
size_t src_id;
|
||||
};
|
||||
|
||||
struct ReadAsArray {
|
||||
size_t addr_src_id;
|
||||
union {
|
||||
size_t size_src_id;
|
||||
uint64_t size_const;
|
||||
};
|
||||
bool is_const_size;
|
||||
};
|
||||
|
||||
struct Node
|
||||
{
|
||||
enum class Type : uint8_t
|
||||
@@ -364,12 +373,13 @@ namespace dbgui::data
|
||||
line_entry,
|
||||
locals,
|
||||
read_cstr,
|
||||
read_array,
|
||||
};
|
||||
|
||||
size_t id;
|
||||
Type type;
|
||||
// when adding something here, remember to update LLDBBackend::add_data_node
|
||||
std::variant<std::monostate, Source, Disassemble, LineEntry, ReadAsCStr>
|
||||
std::variant<std::monostate, Source, Disassemble, LineEntry, ReadAsCStr, ReadAsArray>
|
||||
data;
|
||||
};
|
||||
} // namespace source
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "imgui_internal.h"
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <charconv>
|
||||
|
||||
using namespace dbgui;
|
||||
using namespace dbgui::frontend;
|
||||
@@ -818,6 +819,9 @@ namespace
|
||||
return token;
|
||||
}
|
||||
|
||||
std::optional<size_t> parse_array_desc_inner(ParseState& state, size_t addr_src_id);
|
||||
|
||||
|
||||
// <data desc> = <data desc>.<data desc> | <array desc> | <ident> | <reg>
|
||||
std::optional<size_t> parse_data_desc(ParseState &state)
|
||||
{
|
||||
@@ -917,6 +921,27 @@ namespace
|
||||
}
|
||||
state.path_buf.append(ident);
|
||||
|
||||
const auto create_var_node = [&](bool address_of) -> size_t {
|
||||
spdlog::trace("Parsing data_desc: creating variable source (address?: {}) with path {}",
|
||||
address_of, state.path_buf);
|
||||
auto node_id = state.frontend->target->data_node_id++;
|
||||
state.nodes.push_back(data::source::Node{
|
||||
.id = node_id,
|
||||
.type = data::source::Node::Type::source,
|
||||
.data =
|
||||
data::source::Source{
|
||||
.type = data::source::Source::Type::variable,
|
||||
.data =
|
||||
data::source::Source::Variable{
|
||||
.expr_path = state.path_buf,
|
||||
.address_of_or_pointer = address_of,
|
||||
},
|
||||
},
|
||||
});
|
||||
state.path_buf.clear();
|
||||
return node_id;
|
||||
};
|
||||
|
||||
// differentiate between <data desc>, <array desc> and end of <data desc>
|
||||
const auto peek_token_opt = peek_token(state);
|
||||
if (peek_token_opt)
|
||||
@@ -934,30 +959,85 @@ namespace
|
||||
|
||||
if (peek_token == WatchToken::bracket_open)
|
||||
{
|
||||
// TODO: parse <array desc>
|
||||
assert(0);
|
||||
return {};
|
||||
// parse <array desc>
|
||||
// consume token
|
||||
next_token(state);
|
||||
const auto src_node = create_var_node(true);
|
||||
const auto res = parse_array_desc_inner(state, src_node);
|
||||
if (!res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// we expect a closing bracket
|
||||
const auto closing_opt = next_token(state);
|
||||
if (!closing_opt) {
|
||||
spdlog::trace("Failed to parse data_desc: Expected closing bracket in array_desc but got none");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (*closing_opt != WatchToken::bracket_close) {
|
||||
spdlog::trace("Failed to parse data_desc: Expected closing bracket in array_desc but got {}", token_to_str(state, *closing_opt));
|
||||
return {};
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
spdlog::trace("Parsing data_desc: creating variable source with path {}",
|
||||
state.path_buf);
|
||||
// something else, end of <data desc>
|
||||
auto node_id = state.frontend->target->data_node_id++;
|
||||
state.nodes.push_back(data::source::Node{
|
||||
.id = node_id,
|
||||
.type = data::source::Node::Type::source,
|
||||
.data =
|
||||
data::source::Source{
|
||||
.type = data::source::Source::Type::variable,
|
||||
.data =
|
||||
data::source::Source::Variable{
|
||||
.expr_path = state.path_buf,
|
||||
.address_of_or_pointer = false,
|
||||
},
|
||||
},
|
||||
});
|
||||
return create_var_node(false);
|
||||
}
|
||||
|
||||
// <array desc> = <ident>\[<arrsize spec>|<arrpath>\]
|
||||
std::optional<size_t> parse_array_desc_inner(ParseState& state, size_t addr_src_id) {
|
||||
// the bracket has already been consumed by the caller
|
||||
spdlog::trace("Parsing array_desc_inner");
|
||||
|
||||
// for now only support constant sized arrays
|
||||
const auto peek_opt = peek_token(state);
|
||||
if (!peek_opt) {
|
||||
spdlog::trace("Failed to parse array_desc_inner: end of token");
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto peek_token = *peek_opt;
|
||||
if (!token_is_literal(peek_token)) {
|
||||
spdlog::trace("Failed to parse array_desc_inner: Expected literal but got {}", token_to_str(state, peek_token));
|
||||
return {};
|
||||
}
|
||||
|
||||
// consume
|
||||
next_token(state);
|
||||
|
||||
auto literal = token_literal(state, peek_token);
|
||||
spdlog::trace("Parsing array_desc_inner: Got literal {}", literal);
|
||||
|
||||
int base = 10;
|
||||
if (literal.starts_with("0x")) {
|
||||
base = 16;
|
||||
literal.remove_prefix(2);
|
||||
}
|
||||
uint64_t size = 0;
|
||||
|
||||
const auto parse_res = std::from_chars(literal.begin(), literal.end(), size, base);
|
||||
if (parse_res.ec != std::errc{} || parse_res.ptr != literal.end()) {
|
||||
spdlog::trace("Failed parsing array_desc_inner: Literal is not a number");
|
||||
return {};
|
||||
}
|
||||
|
||||
auto node_id = state.frontend->target->data_node_id++;
|
||||
spdlog::trace("Parsing array_desc_inner: creating read_as_array with size {} and id {}",
|
||||
size, node_id);
|
||||
state.nodes.push_back(data::source::Node{
|
||||
.id = node_id,
|
||||
.type = data::source::Node::Type::read_array,
|
||||
.data =
|
||||
data::source::ReadAsArray{
|
||||
.addr_src_id = addr_src_id,
|
||||
.size_const = size,
|
||||
.is_const_size = true,
|
||||
},
|
||||
});
|
||||
return node_id;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user