diff --git a/src/Cutter.cpp b/src/Cutter.cpp index e9a9ee7d..78bc6a4c 100644 --- a/src/Cutter.cpp +++ b/src/Cutter.cpp @@ -538,7 +538,7 @@ void CutterCore::setCurrentBits(int bits, RVA offset) emit instructionChanged(offset); } -void CutterCore::setClassMethod(const QString &className, const ClassMethodDescription &meth) +void CutterCore::setClassMethod(const QString &className, const BinClassMethodDescription &meth) { RAnalMethod analMeth; analMeth.name = strdup (meth.name.toUtf8().constData()); @@ -1891,7 +1891,7 @@ QList CutterCore::getAllClassesFromBin() for (const QJsonValue &value2 : classObject[RJsonKey::methods].toArray()) { QJsonObject methObject = value2.toObject(); - ClassMethodDescription meth; + BinClassMethodDescription meth; meth.name = methObject[RJsonKey::name].toString(); meth.addr = methObject[RJsonKey::addr].toVariant().toULongLong(); @@ -1902,7 +1902,7 @@ QList CutterCore::getAllClassesFromBin() for (const QJsonValue &value2 : classObject[RJsonKey::fields].toArray()) { QJsonObject fieldObject = value2.toObject(); - ClassFieldDescription field; + BinClassFieldDescription field; field.name = fieldObject[RJsonKey::name].toString(); field.addr = fieldObject[RJsonKey::addr].toVariant().toULongLong(); @@ -1967,7 +1967,7 @@ QList CutterCore::getAllClassesFromFlags() classDesc = it.value(); } - ClassMethodDescription meth; + BinClassMethodDescription meth; meth.name = match.captured(2); meth.addr = flagObject[RJsonKey::offset].toVariant().toULongLong(); classDesc->methods << meth; @@ -1977,7 +1977,7 @@ QList CutterCore::getAllClassesFromFlags() return ret; } -QList CutterCore::getAllClassesFromAnal() +QList CutterCore::getAllAnalClasses() { QList ret; @@ -1985,6 +1985,7 @@ QList CutterCore::getAllClassesFromAnal() if (!l) { return ret; } + ret.reserve(static_cast(l->length)); SdbListIter *it; void *entry; @@ -1997,6 +1998,72 @@ QList CutterCore::getAllClassesFromAnal() return ret; } +QList CutterCore::getAnalClassMethods(const QString &cls) +{ + QList ret; + + RVector *meths = r_anal_class_method_get_all(core_->anal, cls.toUtf8().constData()); + if (!meths) { + return ret; + } + + ret.reserve(static_cast(meths->len)); + RAnalMethod *meth; + CutterRVectorForeach(meths, meth, RAnalMethod) { + AnalMethodDescription desc; + desc.name = QString::fromUtf8(meth->name); + desc.addr = meth->addr; + desc.vtableOffset = meth->vtable_offset; + } + r_vector_free(meths); + + return ret; +} + +QList CutterCore::getAnalClassBaseClasses(const QString &cls) +{ + QList ret; + + RVector *bases = r_anal_class_base_get_all(core_->anal, cls.toUtf8().constData()); + if (!bases) { + return ret; + } + + ret.reserve(static_cast(bases->len)); + RAnalBaseClass *base; + CutterRVectorForeach(bases, base, RAnalBaseClass) { + AnalBaseClassDescription desc; + desc.id = QString::fromUtf8(base->id); + desc.offset = base->offset; + desc.className = QString::fromUtf8(base->class_name); + } + r_vector_free(bases); + + return ret; +} + +QList CutterCore::getAnalClassVTables(const QString &cls) +{ + QList ret; + + RVector *vtables = r_anal_class_base_get_all(core_->anal, cls.toUtf8().constData()); + if (!vtables) { + return ret; + } + + ret.reserve(static_cast(vtables->len)); + RAnalVTable *vtable; + CutterRVectorForeach(vtables, vtable, RAnalVTable) { + AnalVTableDescription desc; + desc.id = QString::fromUtf8(vtable->id); + desc.offset = vtable->offset; + desc.addr = vtable->addr; + } + r_vector_free(vtables); + + return ret; +} + QList CutterCore::getAllResources() { CORE_LOCK(); @@ -2037,7 +2104,7 @@ QList CutterCore::getAllVTables() for (const QJsonValue &methodValue : methodArray) { QJsonObject methodObject = methodValue.toObject(); - ClassMethodDescription method; + BinClassMethodDescription method; method.addr = methodObject[RJsonKey::offset].toVariant().toULongLong(); method.name = methodObject[RJsonKey::name].toString(); diff --git a/src/Cutter.h b/src/Cutter.h index d492afbb..a3085c6a 100644 --- a/src/Cutter.h +++ b/src/Cutter.h @@ -20,6 +20,10 @@ #define CutterRListForeach(list, it, type, x) \ if (list) for (it = list->head; it && ((x=static_cast(it->data))); it = it->n) +#define CutterRVectorForeach(vec, it, type) \ + if ((vec) && (vec)->a) \ + for (it = (type *)(vec)->a; (char *)it != (char *)(vec)->a + ((vec)->len * (vec)->elem_size); it = (type *)((char *)it + (vec)->elem_size)) + #define APPNAME "Cutter" #define Core() (CutterCore::getInstance()) @@ -251,18 +255,18 @@ struct DisassemblyLine { QString text; }; -struct ClassBaseClassDescription { +struct BinClassBaseClassDescription { QString name; RVA offset; }; -struct ClassMethodDescription { +struct BinClassMethodDescription { QString name; RVA addr = RVA_INVALID; st64 vtableOffset = -1; }; -struct ClassFieldDescription { +struct BinClassFieldDescription { QString name; RVA addr = RVA_INVALID; }; @@ -272,9 +276,27 @@ struct BinClassDescription { RVA addr = RVA_INVALID; RVA vtableAddr = RVA_INVALID; ut64 index = 0; - QList baseClasses; - QList methods; - QList fields; + QList baseClasses; + QList methods; + QList fields; +}; + +struct AnalMethodDescription { + QString name; + RVA addr; + st64 vtableOffset; +}; + +struct AnalBaseClassDescription { + QString id; + RVA offset; + QString className; +}; + +struct AnalVTableDescription { + QString id; + ut64 offset; + ut64 addr; }; struct ResourcesDescription { @@ -288,7 +310,7 @@ struct ResourcesDescription { struct VTableDescription { RVA addr; - QList methods; + QList methods; }; struct BlockDescription { @@ -363,12 +385,12 @@ Q_DECLARE_METATYPE(RBinPluginDescription) Q_DECLARE_METATYPE(RIOPluginDescription) Q_DECLARE_METATYPE(RCorePluginDescription) Q_DECLARE_METATYPE(RAsmPluginDescription) -Q_DECLARE_METATYPE(ClassMethodDescription) -Q_DECLARE_METATYPE(ClassFieldDescription) +Q_DECLARE_METATYPE(BinClassMethodDescription) +Q_DECLARE_METATYPE(BinClassFieldDescription) Q_DECLARE_METATYPE(BinClassDescription) Q_DECLARE_METATYPE(const BinClassDescription *) -Q_DECLARE_METATYPE(const ClassMethodDescription *) -Q_DECLARE_METATYPE(const ClassFieldDescription *) +Q_DECLARE_METATYPE(const BinClassMethodDescription *) +Q_DECLARE_METATYPE(const BinClassFieldDescription *) Q_DECLARE_METATYPE(ResourcesDescription) Q_DECLARE_METATYPE(VTableDescription) Q_DECLARE_METATYPE(TypeDescription) @@ -455,7 +477,7 @@ public: void setCurrentBits(int bits, RVA offset = RVA_INVALID); /* Classes */ - void setClassMethod(const QString &className, const ClassMethodDescription &meth); + void setClassMethod(const QString &className, const BinClassMethodDescription &meth); void renameClassMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName); /* File related methods */ @@ -619,7 +641,6 @@ public: QList getAllEntrypoint(); QList getAllClassesFromBin(); QList getAllClassesFromFlags(); - QList getAllClassesFromAnal(); QList getAllResources(); QList getAllVTables(); @@ -662,6 +683,11 @@ public: QJsonObject getRegisterJson(); QList getVariables(RVA at); + QList getAllAnalClasses(); + QList getAnalClassMethods(const QString &cls); + QList getAnalClassBaseClasses(const QString &cls); + QList getAnalClassVTables(const QString &cls); + QList getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType = QString::null); diff --git a/src/dialogs/EditMethodDialog.cpp b/src/dialogs/EditMethodDialog.cpp index f3d9e6b7..a08c786d 100644 --- a/src/dialogs/EditMethodDialog.cpp +++ b/src/dialogs/EditMethodDialog.cpp @@ -74,7 +74,7 @@ void EditMethodDialog::setClass(const QString &className) validateInput(); } -void EditMethodDialog::setMethod(const ClassMethodDescription &meth) +void EditMethodDialog::setMethod(const BinClassMethodDescription &meth) { ui->nameEdit->setText(meth.name); ui->addressEdit->setText(meth.addr != RVA_INVALID ? RAddressString(meth.addr) : nullptr); @@ -100,9 +100,9 @@ QString EditMethodDialog::getClass() return ui->classComboBox->itemData(index).value().name; } -ClassMethodDescription EditMethodDialog::getMethod() +BinClassMethodDescription EditMethodDialog::getMethod() { - ClassMethodDescription ret; + BinClassMethodDescription ret; ret.name = ui->nameEdit->text(); ret.addr = Core()->num(ui->addressEdit->text()); if (ui->virtualCheckBox->isChecked()) { @@ -113,7 +113,7 @@ ClassMethodDescription EditMethodDialog::getMethod() return ret; } -bool EditMethodDialog::showDialog(const QString &title, const QString &className, ClassMethodDescription *meth, QWidget *parent) +bool EditMethodDialog::showDialog(const QString &title, const QString &className, BinClassMethodDescription *meth, QWidget *parent) { auto dialog = new EditMethodDialog(parent); dialog->setWindowTitle(title); @@ -124,7 +124,7 @@ bool EditMethodDialog::showDialog(const QString &title, const QString &className return result == QDialog::DialogCode::Accepted; } -void EditMethodDialog::newMethod(const QString &className, ClassMethodDescription meth) +void EditMethodDialog::newMethod(const QString &className, BinClassMethodDescription meth) { if (!showDialog(tr("Create Method"), className, &meth)) { return; @@ -132,7 +132,7 @@ void EditMethodDialog::newMethod(const QString &className, ClassMethodDescriptio Core()->setClassMethod(className, meth); } -void EditMethodDialog::editMethod(const QString &className, ClassMethodDescription meth) +void EditMethodDialog::editMethod(const QString &className, BinClassMethodDescription meth) { QString oldName = meth.name; if (!showDialog(tr("Edit Method"), className, &meth)) { diff --git a/src/dialogs/EditMethodDialog.h b/src/dialogs/EditMethodDialog.h index d4be06ce..aee65a01 100644 --- a/src/dialogs/EditMethodDialog.h +++ b/src/dialogs/EditMethodDialog.h @@ -19,14 +19,14 @@ public: ~EditMethodDialog(); void setClass(const QString &className); - void setMethod(const ClassMethodDescription &meth); + void setMethod(const BinClassMethodDescription &meth); QString getClass(); - ClassMethodDescription getMethod(); + BinClassMethodDescription getMethod(); - static bool showDialog(const QString &title, const QString &className, ClassMethodDescription *meth, QWidget *parent = nullptr); - static void newMethod(const QString &className = nullptr, ClassMethodDescription meth = ClassMethodDescription()); - static void editMethod(const QString &className, ClassMethodDescription meth); + static bool showDialog(const QString &title, const QString &className, BinClassMethodDescription *meth, QWidget *parent = nullptr); + static void newMethod(const QString &className = nullptr, BinClassMethodDescription meth = BinClassMethodDescription()); + static void editMethod(const QString &className, BinClassMethodDescription meth); private slots: void on_buttonBox_accepted(); diff --git a/src/dialogs/InitialOptionsDialog.cpp b/src/dialogs/InitialOptionsDialog.cpp index 277cc39b..eadd6274 100644 --- a/src/dialogs/InitialOptionsDialog.cpp +++ b/src/dialogs/InitialOptionsDialog.cpp @@ -259,6 +259,8 @@ void InitialOptionsDialog::setupAndStartAnalysis(/*int level, QList adv if (ui->scriptCheckBox->isChecked()) { options.script = ui->scriptLineEdit->text(); } + + options.endian = getSelectedEndianness(); options.bbsize = getSelectedBBSize(); diff --git a/src/widgets/ClassesWidget.cpp b/src/widgets/ClassesWidget.cpp index b510fb84..277b2903 100644 --- a/src/widgets/ClassesWidget.cpp +++ b/src/widgets/ClassesWidget.cpp @@ -87,9 +87,9 @@ int BinClassesModel::columnCount(const QModelIndex &) const QVariant BinClassesModel::data(const QModelIndex &index, int role) const { const BinClassDescription *cls; - const ClassMethodDescription *meth = nullptr; - const ClassFieldDescription *field = nullptr; - const ClassBaseClassDescription *base = nullptr; + const BinClassMethodDescription *meth = nullptr; + const BinClassFieldDescription *field = nullptr; + const BinClassBaseClassDescription *base = nullptr; if (index.internalId() == 0) { // class row if (index.row() >= classes.count()) { return QVariant(); @@ -218,10 +218,10 @@ AnalClassesModel::AnalClassesModel(QObject *parent) { } -void AnalClassesModel::setClasses(const QList &classes) +void AnalClassesModel::refreshClasses() { beginResetModel(); - this->classes = classes; + classes = Core()->getAllAnalClasses(); endResetModel(); } @@ -273,9 +273,9 @@ int AnalClassesModel::columnCount(const QModelIndex &) const QVariant AnalClassesModel::data(const QModelIndex &index, int role) const { QString cls; - const ClassMethodDescription *meth = nullptr; - const ClassFieldDescription *field = nullptr; - const ClassBaseClassDescription *base = nullptr; + const BinClassMethodDescription *meth = nullptr; + const BinClassFieldDescription *field = nullptr; + const BinClassBaseClassDescription *base = nullptr; if (index.internalId() == 0) { // class row if (index.row() >= classes.count()) { return QVariant(); @@ -497,7 +497,7 @@ void ClassesWidget::refreshClasses() ui->classesTreeView->setModel(anal_model); //proxy_model->setSourceModel(anal_model); } - anal_model->setClasses(Core()->getAllClassesFromAnal()); + anal_model->refreshClasses(); break; } @@ -561,7 +561,7 @@ void ClassesWidget::on_addMethodAction_triggered() className = index.parent().data(ClassesModel::NameRole).toString(); } - ClassMethodDescription meth; + BinClassMethodDescription meth; meth.addr = Core()->getOffset(); EditMethodDialog::newMethod(className, meth); @@ -575,6 +575,6 @@ void ClassesWidget::on_editMethodAction_triggered() } QString className = index.parent().data(ClassesModel::NameRole).toString(); - ClassMethodDescription meth = index.data(ClassesModel::DataRole).value(); + BinClassMethodDescription meth = index.data(ClassesModel::DataRole).value(); EditMethodDialog::editMethod(className, meth); } diff --git a/src/widgets/ClassesWidget.h b/src/widgets/ClassesWidget.h index 0a58b27a..348f4d44 100644 --- a/src/widgets/ClassesWidget.h +++ b/src/widgets/ClassesWidget.h @@ -77,7 +77,8 @@ private: public: explicit AnalClassesModel(QObject *parent = nullptr); - void setClasses(const QList &classes); + + void refreshClasses(); }; diff --git a/src/widgets/VTablesWidget.cpp b/src/widgets/VTablesWidget.cpp index 301e366b..2c4f2fb6 100644 --- a/src/widgets/VTablesWidget.cpp +++ b/src/widgets/VTablesWidget.cpp @@ -39,7 +39,7 @@ QVariant VTableModel::data(const QModelIndex &index, int role) const { QModelIndex parent = index.parent(); if (parent.isValid()) { - const ClassMethodDescription &res = vtables->at(parent.row()).methods.at(index.row()); + const BinClassMethodDescription &res = vtables->at(parent.row()).methods.at(index.row()); switch (role) { case Qt::DisplayRole: switch (index.column()) { @@ -189,7 +189,7 @@ void VTablesWidget::on_vTableTreeView_doubleClicked(const QModelIndex &index) QModelIndex parent = index.parent(); if (parent.isValid()) { Core()->seek(index.data( - VTableModel::VTableDescriptionRole).value().addr); + VTableModel::VTableDescriptionRole).value().addr); } else { Core()->seek(index.data( VTableModel::VTableDescriptionRole).value().addr);