Make EditMethodDialog Method Loading work

This commit is contained in:
Florian Märkl 2019-02-01 21:40:34 +01:00
parent 159d04e4c5
commit 7bdc28d07d
5 changed files with 84 additions and 61 deletions

View File

@ -538,23 +538,6 @@ void CutterCore::setCurrentBits(int bits, RVA offset)
emit instructionChanged(offset);
}
void CutterCore::setClassMethod(const QString &className, const BinClassMethodDescription &meth)
{
RAnalMethod analMeth;
analMeth.name = strdup (meth.name.toUtf8().constData());
analMeth.addr = meth.addr;
analMeth.vtable_offset = meth.vtableOffset;
r_anal_class_method_set(core_->anal, className.toUtf8().constData(), &analMeth);
r_anal_class_method_fini(&analMeth);
emit classesChanged();
}
void CutterCore::renameClassMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName)
{
r_anal_class_method_rename(core_->anal, className.toUtf8().constData(), oldMethodName.toUtf8().constData(), newMethodName.toUtf8().constData());
emit classesChanged();
}
void CutterCore::seek(ut64 offset)
{
// Slower than using the API, but the API is not complete
@ -2067,6 +2050,36 @@ QList<AnalVTableDescription> CutterCore::getAnalClassVTables(const QString &cls)
return ret;
}
bool CutterCore::getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc)
{
RAnalMethod analMeth;
if (r_anal_class_method_get(core_->anal, cls.toUtf8().constData(), meth.toUtf8().constData(), &analMeth) != R_ANAL_CLASS_ERR_SUCCESS) {
return false;
}
desc->name = QString::fromUtf8(analMeth.name);
desc->addr = analMeth.addr;
desc->vtableOffset = analMeth.vtable_offset;
r_anal_class_method_fini(&analMeth);
return true;
}
void CutterCore::setAnalMethod(const QString &className, const AnalMethodDescription &meth)
{
RAnalMethod analMeth;
analMeth.name = strdup (meth.name.toUtf8().constData());
analMeth.addr = meth.addr;
analMeth.vtable_offset = meth.vtableOffset;
r_anal_class_method_set(core_->anal, className.toUtf8().constData(), &analMeth);
r_anal_class_method_fini(&analMeth);
emit classesChanged();
}
void CutterCore::renameAnalMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName)
{
r_anal_class_method_rename(core_->anal, className.toUtf8().constData(), oldMethodName.toUtf8().constData(), newMethodName.toUtf8().constData());
emit classesChanged();
}
QList<ResourcesDescription> CutterCore::getAllResources()
{
CORE_LOCK();

View File

@ -480,8 +480,13 @@ public:
void setCurrentBits(int bits, RVA offset = RVA_INVALID);
/* Classes */
void setClassMethod(const QString &className, const BinClassMethodDescription &meth);
void renameClassMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName);
QList<QString> getAllAnalClasses();
QList<AnalMethodDescription> getAnalClassMethods(const QString &cls);
QList<AnalBaseClassDescription> getAnalClassBaseClasses(const QString &cls);
QList<AnalVTableDescription> getAnalClassVTables(const QString &cls);
bool getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc);
void renameAnalMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName);
void setAnalMethod(const QString &cls, const AnalMethodDescription &meth);
/* File related methods */
bool loadFile(QString path, ut64 baddr = 0LL, ut64 mapaddr = 0LL, int perms = R_PERM_R,
@ -686,11 +691,6 @@ public:
QJsonObject getRegisterJson();
QList<VariableDescription> getVariables(RVA at);
QList<QString> getAllAnalClasses();
QList<AnalMethodDescription> getAnalClassMethods(const QString &cls);
QList<AnalBaseClassDescription> getAnalClassBaseClasses(const QString &cls);
QList<AnalVTableDescription> getAnalClassVTables(const QString &cls);
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
const QString &filterType = QString::null);

View File

@ -9,9 +9,9 @@ EditMethodDialog::EditMethodDialog(QWidget *parent) :
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
ui->classComboBox->clear();
/* TODO for (auto &cls : Core()->getAllClassesFromAnal()) {
ui->classComboBox->addItem(cls.name, QVariant::fromValue<BinClassDescription>(cls));
}*/
for (auto &cls : Core()->getAllAnalClasses()) {
ui->classComboBox->addItem(cls, cls);
}
updateVirtualUI();
validateInput();
@ -64,8 +64,8 @@ void EditMethodDialog::setClass(const QString &className)
}
for (int i=0; i<ui->classComboBox->count(); i++) {
BinClassDescription cls = ui->classComboBox->itemData(i).value<BinClassDescription>();
if (cls.name == className) {
QString cls = ui->classComboBox->itemData(i).toString();
if (cls == className) {
ui->classComboBox->setCurrentIndex(i);
break;
}
@ -74,14 +74,14 @@ void EditMethodDialog::setClass(const QString &className)
validateInput();
}
void EditMethodDialog::setMethod(const BinClassMethodDescription &meth)
void EditMethodDialog::setMethod(const AnalMethodDescription &desc)
{
ui->nameEdit->setText(meth.name);
ui->addressEdit->setText(meth.addr != RVA_INVALID ? RAddressString(meth.addr) : nullptr);
ui->nameEdit->setText(desc.name);
ui->addressEdit->setText(desc.addr != RVA_INVALID ? RAddressString(desc.addr) : nullptr);
if (meth.vtableOffset >= 0) {
if (desc.vtableOffset >= 0) {
ui->virtualCheckBox->setChecked(true);
ui->vtableOffsetEdit->setText(QString::number(meth.vtableOffset));
ui->vtableOffsetEdit->setText(QString::number(desc.vtableOffset));
} else {
ui->virtualCheckBox->setChecked(false);
ui->vtableOffsetEdit->setText(nullptr);
@ -100,9 +100,9 @@ QString EditMethodDialog::getClass()
return ui->classComboBox->itemData(index).value<BinClassDescription>().name;
}
BinClassMethodDescription EditMethodDialog::getMethod()
AnalMethodDescription EditMethodDialog::getMethod()
{
BinClassMethodDescription ret;
AnalMethodDescription ret;
ret.name = ui->nameEdit->text();
ret.addr = Core()->num(ui->addressEdit->text());
if (ui->virtualCheckBox->isChecked()) {
@ -113,33 +113,45 @@ BinClassMethodDescription EditMethodDialog::getMethod()
return ret;
}
bool EditMethodDialog::showDialog(const QString &title, const QString &className, BinClassMethodDescription *meth, QWidget *parent)
bool EditMethodDialog::showDialog(const QString &title, QString *className, AnalMethodDescription *desc, QWidget *parent)
{
auto dialog = new EditMethodDialog(parent);
dialog->setWindowTitle(title);
dialog->setClass(className);
dialog->setMethod(*meth);
dialog->setClass(*className);
dialog->setMethod(*desc);
int result = dialog->exec();
*meth = dialog->getMethod();
*className = dialog->getClass();
*desc = dialog->getMethod();
return result == QDialog::DialogCode::Accepted;
}
void EditMethodDialog::newMethod(const QString &className, BinClassMethodDescription meth)
void EditMethodDialog::newMethod(QString className, const QString &meth, QWidget *parent)
{
if (!showDialog(tr("Create Method"), className, &meth)) {
AnalMethodDescription desc;
desc.name = meth;
desc.vtableOffset = -1;
desc.addr = Core()->getOffset();
if (!showDialog(tr("Create Method"), &className, &desc, parent)) {
return;
}
Core()->setClassMethod(className, meth);
Core()->setAnalMethod(className, desc);
}
void EditMethodDialog::editMethod(const QString &className, BinClassMethodDescription meth)
void EditMethodDialog::editMethod(const QString &className, const QString &meth, QWidget *parent)
{
QString oldName = meth.name;
if (!showDialog(tr("Edit Method"), className, &meth)) {
AnalMethodDescription desc;
if (!Core()->getAnalMethod(className, meth, &desc)) {
return;
}
if (meth.name != oldName) {
Core()->renameClassMethod(className, oldName, meth.name);
QString classNameCopy = className;
if (!showDialog(tr("Edit Method"), &classNameCopy, &desc, parent)) {
return;
}
Core()->setClassMethod(className, meth);
if (desc.name != meth) {
Core()->renameAnalMethod(className, meth, desc.name);
}
Core()->setAnalMethod(className, desc);
}

View File

@ -19,14 +19,14 @@ public:
~EditMethodDialog();
void setClass(const QString &className);
void setMethod(const BinClassMethodDescription &meth);
void setMethod(const AnalMethodDescription &desc);
QString getClass();
BinClassMethodDescription getMethod();
AnalMethodDescription getMethod();
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);
static bool showDialog(const QString &title, QString *className, AnalMethodDescription *desc, QWidget *parent = nullptr);
static void newMethod(QString className = nullptr, const QString &meth = QString(), QWidget *parent = nullptr);
static void editMethod(const QString &className, const QString &meth, QWidget *parent = nullptr);
private slots:
void on_buttonBox_accepted();

View File

@ -321,6 +321,8 @@ QVariant AnalClassesModel::data(const QModelIndex &index, int role) const
}
case TypeRole:
return QVariant::fromValue(RowType::Class);
case NameRole:
return cls;
default:
return QVariant();
}
@ -596,10 +598,7 @@ void ClassesWidget::on_addMethodAction_triggered()
className = index.parent().data(ClassesModel::NameRole).toString();
}
BinClassMethodDescription meth;
meth.addr = Core()->getOffset();
EditMethodDialog::newMethod(className, meth);
EditMethodDialog::newMethod(className, QString(), this);
}
void ClassesWidget::on_editMethodAction_triggered()
@ -608,8 +607,7 @@ void ClassesWidget::on_editMethodAction_triggered()
if (!index.isValid() || index.data(ClassesModel::TypeRole).toInt() != static_cast<int>(ClassesModel::RowType::Method)) {
return;
}
QString className = index.parent().data(ClassesModel::NameRole).toString();
BinClassMethodDescription meth = index.data(ClassesModel::DataRole).value<BinClassMethodDescription>();
EditMethodDialog::editMethod(className, meth);
QString methName = index.data(ClassesModel::NameRole).toString();
EditMethodDialog::editMethod(className, methName, this);
}