Make use of new RzType API in Rizin

This commit is contained in:
Riccardo Schirone 2021-09-07 11:12:07 +02:00 committed by Florian Märkl
parent 62ecf3fb2a
commit f42069369c
6 changed files with 67 additions and 124 deletions

2
rizin

@ -1 +1 @@
Subproject commit 254c5119e3563d05d02665cabbcba003c921cee8
Subproject commit c9f9aea2924d2f086b5a6b1ed0216b531faea125

View File

@ -3519,145 +3519,88 @@ QList<TypeDescription> CutterCore::getAllTypes()
return types;
}
QList<TypeDescription> CutterCore::getAllPrimitiveTypes()
QList<TypeDescription> CutterCore::getBaseType(RzBaseTypeKind kind, const char *category)
{
CORE_LOCK();
QList<TypeDescription> primitiveTypes;
QList<TypeDescription> types;
QJsonArray typesArray = cmdj("tj").array();
for (const QJsonValue &value : typesArray) {
QJsonObject typeObject = value.toObject();
RzList *ts = rz_type_db_get_base_types_of_kind(core->analysis->typedb, kind);
RzBaseType *type;
RzListIter *iter;
CutterRListForeach (ts, iter, RzBaseType, type) {
TypeDescription exp;
exp.type = typeObject[RJsonKey::type].toString();
exp.size = typeObject[RJsonKey::size].toVariant().toULongLong();
exp.format = typeObject[RJsonKey::format].toString();
exp.category = tr("Primitive");
primitiveTypes << exp;
exp.type = type->name;
exp.size = rz_type_db_base_get_bitsize(core->analysis->typedb, type);
exp.format = rz_type_format(core->analysis->typedb, type->name);
exp.category = tr(category);
types << exp;
}
rz_list_free(ts);
return types;
}
return primitiveTypes;
QList<TypeDescription> CutterCore::getAllPrimitiveTypes()
{
return getBaseType(RZ_BASE_TYPE_KIND_ATOMIC, "Primitive");
}
QList<TypeDescription> CutterCore::getAllUnions()
{
CORE_LOCK();
QList<TypeDescription> unions;
QJsonArray typesArray = cmdj("tuj").array();
for (const QJsonValue value : typesArray) {
QJsonObject typeObject = value.toObject();
TypeDescription exp;
exp.type = typeObject[RJsonKey::type].toString();
exp.size = typeObject[RJsonKey::size].toVariant().toULongLong();
exp.category = "Union";
unions << exp;
}
return unions;
return getBaseType(RZ_BASE_TYPE_KIND_UNION, "Union");
}
QList<TypeDescription> CutterCore::getAllStructs()
{
CORE_LOCK();
QList<TypeDescription> structs;
QJsonArray typesArray = cmdj("tsj").array();
for (const QJsonValue value : typesArray) {
QJsonObject typeObject = value.toObject();
TypeDescription exp;
exp.type = typeObject[RJsonKey::type].toString();
exp.size = typeObject[RJsonKey::size].toVariant().toULongLong();
exp.category = "Struct";
structs << exp;
}
return structs;
return getBaseType(RZ_BASE_TYPE_KIND_STRUCT, "Struct");
}
QList<TypeDescription> CutterCore::getAllEnums()
{
CORE_LOCK();
QList<TypeDescription> enums;
QJsonObject typesObject = cmdj("tej").object();
for (QString key : typesObject.keys()) {
TypeDescription exp;
exp.type = key;
exp.size = 0;
exp.category = "Enum";
enums << exp;
}
return enums;
return getBaseType(RZ_BASE_TYPE_KIND_ENUM, "Enum");
}
QList<TypeDescription> CutterCore::getAllTypedefs()
{
CORE_LOCK();
QList<TypeDescription> typeDefs;
QJsonObject typesObject = cmdj("ttj").object();
for (QString key : typesObject.keys()) {
TypeDescription exp;
exp.type = key;
exp.size = 0;
exp.category = "Typedef";
typeDefs << exp;
}
return typeDefs;
return getBaseType(RZ_BASE_TYPE_KIND_TYPEDEF, "Typedef");
}
QString CutterCore::addTypes(const char *str)
{
CORE_LOCK();
char *error_msg = nullptr;
char *parsed = rz_type_parse_c_string(core->analysis->typedb, str, &error_msg);
int parsed = rz_type_parse_string(core->analysis->typedb, str, &error_msg);
QString error;
if (!parsed) {
if (error_msg) {
error = error_msg;
rz_mem_free(error_msg);
}
return error;
}
rz_type_db_save_parsed_type(core->analysis->typedb, parsed);
rz_mem_free(parsed);
if (error_msg) {
if (!parsed && error_msg) {
error = error_msg;
rz_mem_free(error_msg);
} else if (!parsed) {
error = QString("Failed to load new type %1").arg(str);
}
return error;
}
QString CutterCore::getTypeAsC(QString name, QString category)
QString CutterCore::getTypeAsC(QString name)
{
CORE_LOCK();
QString output = "Failed to fetch the output.";
if (name.isEmpty() || category.isEmpty()) {
if (name.isEmpty()) {
return output;
}
QString typeName = sanitizeStringForCommand(name);
if (category == "Struct") {
output = cmdRaw(QString("tsc %1").arg(typeName));
} else if (category == "Union") {
output = cmdRaw(QString("tuc %1").arg(typeName));
} else if (category == "Enum") {
output = cmdRaw(QString("tec %1").arg(typeName));
} else if (category == "Typedef") {
output = cmdRaw(QString("ttc %1").arg(typeName));
char *earg = rz_cmd_escape_arg(name.toUtf8().constData(), RZ_CMD_ESCAPE_ONE_ARG);
// TODO: use API for `tc` command once available
QString result = cmd(QString("tc %1").arg(earg));
free(earg);
return result;
}
return output;
bool CutterCore::deleteType(const char *typeName) {
CORE_LOCK();
return rz_type_db_del(core->analysis->typedb, typeName);
}
bool CutterCore::isAddressMapped(RVA addr)

View File

@ -590,11 +590,10 @@ public:
/**
* @brief Fetching the C representation of a given Type
* @param name - the name or the type of the given Type / Struct
* @param category - the category of the given Type (Struct, Union, Enum, ...)
* @param name - the name or the type of the given Type
* @return The type decleration as C output
*/
QString getTypeAsC(QString name, QString category);
QString getTypeAsC(QString name);
/**
* @brief Adds new types
@ -608,6 +607,13 @@ public:
QString addTypes(const char *str);
QString addTypes(const QString &str) { return addTypes(str.toUtf8().constData()); }
/**
* @brief Remove a type
* @param typeName Name of the type to remove
*/
bool deleteType(const char *typeName);
bool deleteType(QString typeName) { return deleteType(typeName.toUtf8().constData()); }
/**
* @brief Checks if the given address is mapped to a region
* @param addr The address to be checked
@ -788,6 +794,7 @@ private:
RizinTaskDialog *debugTaskDialog;
QVector<QString> getCutterRCFilePaths() const;
QList<TypeDescription> getBaseType(RzBaseTypeKind kind, const char *category);
};
class CUTTER_EXPORT RzCoreLocked

View File

@ -84,26 +84,18 @@ void EditVariablesDialog::updateFields()
ui->typeComboBox->setCurrentText(desc.type);
}
static void addTypeDescriptionsToComboBox(QComboBox *comboBox, QList<TypeDescription> list) {
for (const TypeDescription &thisType : list) {
comboBox->addItem(thisType.type);
}
comboBox->insertSeparator(comboBox->count());
}
void EditVariablesDialog::populateTypesComboBox()
{
// gets all loaded types, structures and enums and puts them in a list
addTypeDescriptionsToComboBox(ui->typeComboBox, Core()->getAllStructs());
addTypeDescriptionsToComboBox(ui->typeComboBox, Core()->getAllPrimitiveTypes());
addTypeDescriptionsToComboBox(ui->typeComboBox, Core()->getAllEnums());
addTypeDescriptionsToComboBox(ui->typeComboBox, Core()->getAllTypedefs());
QStringList userStructures;
QStringList userEnumerations;
QList<TypeDescription> primitiveTypesTypeList;
userStructures = Core()->cmdList("ts");
ui->typeComboBox->addItems(userStructures);
ui->typeComboBox->insertSeparator(ui->typeComboBox->count());
primitiveTypesTypeList = Core()->getAllPrimitiveTypes();
for (const TypeDescription &thisType : primitiveTypesTypeList) {
ui->typeComboBox->addItem(thisType.type);
}
ui->typeComboBox->insertSeparator(ui->typeComboBox->count());
userEnumerations = Core()->cmdList("te");
ui->typeComboBox->addItems(userEnumerations);
}

View File

@ -76,7 +76,7 @@ QVariant TypesModel::headerData(int section, Qt::Orientation, int role) const
bool TypesModel::removeRows(int row, int count, const QModelIndex &parent)
{
Core()->cmdRaw("t-" + types->at(row).type);
Core()->deleteType(types->at(row).type);
beginRemoveRows(parent, row, row + count - 1);
while (count--) {
types->removeAt(row);
@ -275,7 +275,8 @@ void TypesWidget::on_actionExport_Types_triggered()
return;
}
QTextStream fileOut(&file);
fileOut << Core()->cmdRaw("tc");
// TODO: use API for `tc` command once available
fileOut << Core()->cmd("tc");
file.close();
}
@ -304,7 +305,7 @@ void TypesWidget::viewType(bool readOnly)
} else {
dialog.setWindowTitle(tr("View Type: ") + t.type + tr(" (Read Only)"));
}
dialog.fillTextArea(Core()->getTypeAsC(t.type, t.category));
dialog.fillTextArea(Core()->getTypeAsC(t.type));
dialog.exec();
}
@ -351,7 +352,7 @@ void TypesWidget::typeItemDoubleClicked(const QModelIndex &index)
if (t.category == "Primitive") {
return;
}
dialog.fillTextArea(Core()->getTypeAsC(t.type, t.category));
dialog.fillTextArea(Core()->getTypeAsC(t.type));
dialog.setWindowTitle(tr("View Type: ") + t.type + tr(" (Read Only)"));
dialog.exec();
}

View File

@ -31,7 +31,7 @@ private:
QList<TypeDescription> *types;
public:
enum Columns { TYPE = 0, SIZE, FORMAT, CATEGORY, COUNT };
enum Columns { TYPE = 0, SIZE, CATEGORY, FORMAT, COUNT };
static const int TypeDescriptionRole = Qt::UserRole;
TypesModel(QList<TypeDescription> *types, QObject *parent = nullptr);
@ -81,7 +81,7 @@ private slots:
/**
* @brief Executed on clicking the Export Types option in the context menu
* It shows the user a file dialog box to select a file where the types
* will be exported. It uses the "tc" command of Rizin to export the types.
* will be exported.
*/
void on_actionExport_Types_triggered();