HackStudio: Support debugging variables with Enum types
Variables with enum types can now be both viewed and modified in the variables view!
This commit is contained in:
parent
a4f23429aa
commit
f958c693ee
Notes:
sideshowbarker
2024-07-19 05:52:35 +09:00
Author: https://github.com/FalseHonesty Commit: https://github.com/SerenityOS/serenity/commit/f958c693eee Pull-request: https://github.com/SerenityOS/serenity/pull/2469
3 changed files with 41 additions and 10 deletions
|
@ -1,9 +1,15 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
enum TestEnum {
|
||||||
|
ValueOne,
|
||||||
|
ValueTwo
|
||||||
|
};
|
||||||
|
|
||||||
struct MyStruct {
|
struct MyStruct {
|
||||||
int x { -1 };
|
int x { -1 };
|
||||||
bool status { false };
|
bool status { false };
|
||||||
|
TestEnum test_value { ValueOne };
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int, char**)
|
int main(int, char**)
|
||||||
|
|
|
@ -71,7 +71,7 @@ DebugInfoWidget::DebugInfoWidget()
|
||||||
auto* variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto* variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
if (variable->location_type != DebugInfo::VariableInfo::LocationType::Address)
|
if (variable->location_type != DebugInfo::VariableInfo::LocationType::Address)
|
||||||
return false;
|
return false;
|
||||||
return variable->type.is_one_of("int", "bool");
|
return variable->is_enum_type() || variable->type_name.is_one_of("int", "bool");
|
||||||
};
|
};
|
||||||
|
|
||||||
m_variables_view->on_context_menu_request = [this, is_valid_index](auto& index, auto& event) {
|
m_variables_view->on_context_menu_request = [this, is_valid_index](auto& index, auto& event) {
|
||||||
|
|
|
@ -75,36 +75,61 @@ String variable_value_as_string(const DebugInfo::VariableInfo& variable)
|
||||||
|
|
||||||
auto variable_address = variable.location_data.address;
|
auto variable_address = variable.location_data.address;
|
||||||
|
|
||||||
if (variable.type == "int") {
|
if (variable.is_enum_type()) {
|
||||||
|
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
||||||
|
ASSERT(value.has_value());
|
||||||
|
auto it = variable.type->members.find([enumerator_value = value.value()](auto& enumerator) {
|
||||||
|
return enumerator->constant_data.as_u32 == enumerator_value;
|
||||||
|
});
|
||||||
|
ASSERT(!it.is_end());
|
||||||
|
return String::format("%s::%s", variable.type_name.characters(), (*it)->name.characters());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variable.type_name == "int") {
|
||||||
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
||||||
ASSERT(value.has_value());
|
ASSERT(value.has_value());
|
||||||
return String::format("%d", static_cast<int>(value.value()));
|
return String::format("%d", static_cast<int>(value.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (variable.type == "char") {
|
if (variable.type_name == "char") {
|
||||||
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
||||||
ASSERT(value.has_value());
|
ASSERT(value.has_value());
|
||||||
return String::format("'%c' (%d)", static_cast<char>(value.value()), static_cast<char>(value.value()));
|
return String::format("'%c' (%d)", static_cast<char>(value.value()), static_cast<char>(value.value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (variable.type == "bool") {
|
if (variable.type_name == "bool") {
|
||||||
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
auto value = Debugger::the().session()->peek((u32*)variable_address);
|
||||||
ASSERT(value.has_value());
|
ASSERT(value.has_value());
|
||||||
return (value.value() & 1) ? "true" : "false";
|
return (value.value() & 1) ? "true" : "false";
|
||||||
}
|
}
|
||||||
|
|
||||||
return String::format("type: %s @ %08x, ", variable.type.characters(), variable_address);
|
return String::format("type: %s @ %08x, ", variable.type_name.characters(), variable_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Optional<u32> string_to_value_of_type(const StringView& string_value, const StringView& type)
|
static Optional<u32> string_to_variable_value(const StringView& string_value, const DebugInfo::VariableInfo& variable)
|
||||||
{
|
{
|
||||||
if (type == "int") {
|
if (variable.is_enum_type()) {
|
||||||
|
auto prefix_string = String::format("%s::", variable.type_name.characters());
|
||||||
|
auto string_to_use = string_value;
|
||||||
|
if (string_value.starts_with(prefix_string))
|
||||||
|
string_to_use = string_value.substring_view(prefix_string.length(), string_value.length() - prefix_string.length());
|
||||||
|
|
||||||
|
auto it = variable.type->members.find([string_to_use](auto& enumerator) {
|
||||||
|
return enumerator->name == string_to_use;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it.is_end())
|
||||||
|
return {};
|
||||||
|
return (*it)->constant_data.as_u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variable.type_name == "int") {
|
||||||
bool success = false;
|
bool success = false;
|
||||||
auto value = string_value.to_int(success);
|
auto value = string_value.to_int(success);
|
||||||
return success ? value : Optional<u32>();
|
return success ? value : Optional<u32>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == "bool") {
|
if (variable.type_name == "bool") {
|
||||||
if (string_value == "true")
|
if (string_value == "true")
|
||||||
return true;
|
return true;
|
||||||
if (string_value == "false")
|
if (string_value == "false")
|
||||||
|
@ -119,7 +144,7 @@ void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const Stri
|
||||||
{
|
{
|
||||||
auto variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
auto variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
|
||||||
|
|
||||||
auto value = string_to_value_of_type(string_value, variable->type);
|
auto value = string_to_variable_value(string_value, *variable);
|
||||||
|
|
||||||
if (value.has_value()) {
|
if (value.has_value()) {
|
||||||
auto success = Debugger::the().session()->poke((u32*)variable->location_data.address, value.value());
|
auto success = Debugger::the().session()->poke((u32*)variable->location_data.address, value.value());
|
||||||
|
@ -128,7 +153,7 @@ void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const Stri
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI::MessageBox::show(
|
GUI::MessageBox::show(
|
||||||
String::format("String value \"%s\" could not be converted to a value of type %s.", string_value.to_string().characters(), variable->type.characters()),
|
String::format("String value \"%s\" could not be converted to a value of type %s.", string_value.to_string().characters(), variable->type_name.characters()),
|
||||||
"Set value failed",
|
"Set value failed",
|
||||||
GUI::MessageBox::Type::Error,
|
GUI::MessageBox::Type::Error,
|
||||||
GUI::MessageBox::InputType::OK,
|
GUI::MessageBox::InputType::OK,
|
||||||
|
|
Loading…
Add table
Reference in a new issue