mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-21 14:16:08 +00:00
Update analysis method handling for name/realname (#2843)
This also fixes a crash when adding a new class method.
This commit is contained in:
parent
78a9a11209
commit
6438cc4d50
@ -3152,7 +3152,7 @@ QList<SectionDescription> CutterCore::getAllSections()
|
||||
if (!digests) {
|
||||
continue;
|
||||
}
|
||||
const char *entropy = (const char*)ht_pp_find(digests, "entropy", NULL);
|
||||
const char *entropy = (const char *)ht_pp_find(digests, "entropy", NULL);
|
||||
section.entropy = rz_str_get(entropy);
|
||||
ht_pp_free(digests);
|
||||
|
||||
@ -3376,6 +3376,7 @@ QList<AnalysisMethodDescription> CutterCore::getAnalysisClassMethods(const QStri
|
||||
{
|
||||
AnalysisMethodDescription desc;
|
||||
desc.name = QString::fromUtf8(meth->name);
|
||||
desc.realName = QString::fromUtf8(meth->real_name);
|
||||
desc.addr = meth->addr;
|
||||
desc.vtableOffset = meth->vtable_offset;
|
||||
ret.append(desc);
|
||||
@ -3465,6 +3466,7 @@ bool CutterCore::getAnalysisMethod(const QString &cls, const QString &meth,
|
||||
return false;
|
||||
}
|
||||
desc->name = QString::fromUtf8(analysisMeth.name);
|
||||
desc->realName = QString::fromUtf8(analysisMeth.real_name);
|
||||
desc->addr = analysisMeth.addr;
|
||||
desc->vtableOffset = analysisMeth.vtable_offset;
|
||||
rz_analysis_class_method_fini(&analysisMeth);
|
||||
@ -3475,7 +3477,8 @@ void CutterCore::setAnalysisMethod(const QString &className, const AnalysisMetho
|
||||
{
|
||||
CORE_LOCK();
|
||||
RzAnalysisMethod analysisMeth;
|
||||
analysisMeth.name = strdup(meth.name.toUtf8().constData());
|
||||
analysisMeth.name = rz_str_new(meth.name.toUtf8().constData());
|
||||
analysisMeth.real_name = rz_str_new(meth.realName.toUtf8().constData());
|
||||
analysisMeth.addr = meth.addr;
|
||||
analysisMeth.vtable_offset = meth.vtableOffset;
|
||||
rz_analysis_class_method_set(core->analysis, className.toUtf8().constData(), &analysisMeth);
|
||||
|
@ -248,6 +248,7 @@ struct BinClassDescription
|
||||
struct AnalysisMethodDescription
|
||||
{
|
||||
QString name;
|
||||
QString realName;
|
||||
RVA addr;
|
||||
st64 vtableOffset;
|
||||
};
|
||||
|
@ -26,6 +26,9 @@ EditMethodDialog::EditMethodDialog(bool classFixed, QWidget *parent)
|
||||
connect(ui->virtualCheckBox, &QCheckBox::stateChanged, this,
|
||||
&EditMethodDialog::updateVirtualUI);
|
||||
connect(ui->nameEdit, &QLineEdit::textChanged, this, &EditMethodDialog::validateInput);
|
||||
connect(ui->realNameEdit, &QLineEdit::textChanged, this, &EditMethodDialog::updateName);
|
||||
connect(ui->autoRenameCheckBox, &QCheckBox::stateChanged, this,
|
||||
&EditMethodDialog::updateAutoRenameEnabled);
|
||||
}
|
||||
|
||||
EditMethodDialog::~EditMethodDialog() {}
|
||||
@ -54,15 +57,42 @@ void EditMethodDialog::validateInput()
|
||||
}
|
||||
}
|
||||
|
||||
void EditMethodDialog::updateName()
|
||||
{
|
||||
if (ui->autoRenameCheckBox->isChecked()) {
|
||||
ui->nameEdit->setText(convertRealNameToName(ui->realNameEdit->text()));
|
||||
}
|
||||
|
||||
validateInput();
|
||||
}
|
||||
|
||||
void EditMethodDialog::updateAutoRenameEnabled()
|
||||
{
|
||||
ui->nameEdit->setEnabled(!ui->autoRenameCheckBox->isChecked());
|
||||
|
||||
if (ui->autoRenameCheckBox->isChecked()) {
|
||||
ui->nameEdit->setText(convertRealNameToName(ui->realNameEdit->text()));
|
||||
}
|
||||
}
|
||||
|
||||
bool EditMethodDialog::inputValid()
|
||||
{
|
||||
if (ui->nameEdit->text().isEmpty()) {
|
||||
if (ui->nameEdit->text().isEmpty() || ui->realNameEdit->text().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
// TODO: do more checks here, for example for name clashes
|
||||
return true;
|
||||
}
|
||||
|
||||
QString EditMethodDialog::convertRealNameToName(const QString &realName)
|
||||
{
|
||||
std::unique_ptr<const char, void (*)(const char *)> sanitizedCString(
|
||||
rz_str_sanitize_sdb_key(realName.toUtf8().constData()),
|
||||
[](const char *s) { rz_mem_free((void*)s); });
|
||||
|
||||
return QString(sanitizedCString.get());
|
||||
}
|
||||
|
||||
void EditMethodDialog::setClass(const QString &className)
|
||||
{
|
||||
if (classComboBox) {
|
||||
@ -89,6 +119,7 @@ void EditMethodDialog::setClass(const QString &className)
|
||||
void EditMethodDialog::setMethod(const AnalysisMethodDescription &desc)
|
||||
{
|
||||
ui->nameEdit->setText(desc.name);
|
||||
ui->realNameEdit->setText(desc.realName);
|
||||
ui->addressEdit->setText(desc.addr != RVA_INVALID ? RzAddressString(desc.addr) : nullptr);
|
||||
|
||||
if (desc.vtableOffset >= 0) {
|
||||
@ -99,6 +130,16 @@ void EditMethodDialog::setMethod(const AnalysisMethodDescription &desc)
|
||||
ui->vtableOffsetEdit->setText(nullptr);
|
||||
}
|
||||
|
||||
// Check if auto-rename should be enabled
|
||||
bool enableAutoRename = ui->nameEdit->text().isEmpty()
|
||||
|| ui->nameEdit->text() == convertRealNameToName(ui->realNameEdit->text());
|
||||
ui->autoRenameCheckBox->setChecked(enableAutoRename);
|
||||
|
||||
// Set focus to real name edit widget if auto-rename is enabled
|
||||
if (enableAutoRename) {
|
||||
ui->realNameEdit->setFocus();
|
||||
}
|
||||
|
||||
updateVirtualUI();
|
||||
validateInput();
|
||||
}
|
||||
@ -120,6 +161,7 @@ AnalysisMethodDescription EditMethodDialog::getMethod() const
|
||||
{
|
||||
AnalysisMethodDescription ret;
|
||||
ret.name = ui->nameEdit->text();
|
||||
ret.realName = ui->realNameEdit->text();
|
||||
ret.addr = Core()->num(ui->addressEdit->text());
|
||||
if (!ui->virtualCheckBox->isChecked()) {
|
||||
ret.vtableOffset = -1;
|
||||
@ -145,7 +187,8 @@ bool EditMethodDialog::showDialog(const QString &title, bool classFixed, QString
|
||||
void EditMethodDialog::newMethod(QString className, const QString &meth, QWidget *parent)
|
||||
{
|
||||
AnalysisMethodDescription desc;
|
||||
desc.name = meth;
|
||||
desc.name = convertRealNameToName(meth);
|
||||
desc.realName = meth;
|
||||
desc.vtableOffset = -1;
|
||||
desc.addr = Core()->getOffset();
|
||||
|
||||
|
@ -59,6 +59,8 @@ private slots:
|
||||
|
||||
void updateVirtualUI();
|
||||
void validateInput();
|
||||
void updateName();
|
||||
void updateAutoRenameEnabled();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::EditMethodDialog> ui;
|
||||
@ -72,6 +74,7 @@ private:
|
||||
QString fixedClass;
|
||||
|
||||
bool inputValid();
|
||||
static QString convertRealNameToName(const QString& realName);
|
||||
};
|
||||
|
||||
#endif // EDITMETHODDIALOG_H
|
||||
|
@ -29,45 +29,69 @@
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
<string>Unique Identifier (name):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="nameEdit"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="nameEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoRenameCheckBox">
|
||||
<property name="text">
|
||||
<string>Auto-Rename</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="realNameLabel">
|
||||
<property name="text">
|
||||
<string>Display Name (realname):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="realNameEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="addressLabel">
|
||||
<property name="text">
|
||||
<string>Address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="addressEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="virtualLabel">
|
||||
<property name="text">
|
||||
<string>Virtual:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="virtualCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="vtableOffsetLabel">
|
||||
<property name="text">
|
||||
<string>Offset in VTable:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="vtableOffsetEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
@ -84,6 +108,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>nameEdit</tabstop>
|
||||
<tabstop>autoRenameCheckBox</tabstop>
|
||||
<tabstop>realNameEdit</tabstop>
|
||||
<tabstop>addressEdit</tabstop>
|
||||
<tabstop>virtualCheckBox</tabstop>
|
||||
<tabstop>vtableOffsetEdit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
|
@ -17,6 +17,8 @@ QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
||||
switch (section) {
|
||||
case NAME:
|
||||
return tr("Name");
|
||||
case REAL_NAME:
|
||||
return tr("Real Name");
|
||||
case TYPE:
|
||||
return tr("Type");
|
||||
case OFFSET:
|
||||
@ -188,7 +190,8 @@ QVariant BinClassesModel::data(const QModelIndex &index, int role) const
|
||||
case OFFSET:
|
||||
return cls->addr == RVA_INVALID ? QString() : RzAddressString(cls->addr);
|
||||
case VTABLE:
|
||||
return cls->vtableAddr == RVA_INVALID ? QString() : RzAddressString(cls->vtableAddr);
|
||||
return cls->vtableAddr == RVA_INVALID ? QString()
|
||||
: RzAddressString(cls->vtableAddr);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@ -312,7 +315,8 @@ void AnalysisClassesModel::classAttrsChanged(const QString &cls)
|
||||
layoutChanged({ persistentIndex });
|
||||
}
|
||||
|
||||
const QVector<AnalysisClassesModel::Attribute> &AnalysisClassesModel::getAttrs(const QString &cls) const
|
||||
const QVector<AnalysisClassesModel::Attribute> &
|
||||
AnalysisClassesModel::getAttrs(const QString &cls) const
|
||||
{
|
||||
auto it = attrs->find(cls);
|
||||
if (it != attrs->end()) {
|
||||
@ -454,6 +458,8 @@ QVariant AnalysisClassesModel::data(const QModelIndex &index, int role) const
|
||||
switch (index.column()) {
|
||||
case NAME:
|
||||
return meth.name;
|
||||
case REAL_NAME:
|
||||
return meth.realName;
|
||||
case TYPE:
|
||||
return tr("method");
|
||||
case OFFSET:
|
||||
@ -476,6 +482,8 @@ QVariant AnalysisClassesModel::data(const QModelIndex &index, int role) const
|
||||
return QVariant::fromValue(meth.addr);
|
||||
case NameRole:
|
||||
return meth.name;
|
||||
case RealNameRole:
|
||||
return meth.realName;
|
||||
case TypeRole:
|
||||
return QVariant::fromValue(RowType::Method);
|
||||
default:
|
||||
|
@ -24,7 +24,7 @@ class ClassesWidget;
|
||||
class ClassesModel : public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
enum Columns { NAME = 0, TYPE, OFFSET, VTABLE, COUNT };
|
||||
enum Columns { NAME = 0, REAL_NAME, TYPE, OFFSET, VTABLE, COUNT };
|
||||
|
||||
/**
|
||||
* @brief values for TypeRole data
|
||||
@ -61,6 +61,14 @@ public:
|
||||
*/
|
||||
static const int VTableRole = Qt::UserRole + 3;
|
||||
|
||||
/**
|
||||
* @brief Real Name role of data for QModelIndex
|
||||
*
|
||||
* will contain values of QString, used for sorting,
|
||||
* as well as identifying classes and methods
|
||||
*/
|
||||
static const int RealNameRole = Qt::UserRole + 4;
|
||||
|
||||
explicit ClassesModel(QObject *parent = nullptr) : QAbstractItemModel(parent) {}
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
|
Loading…
Reference in New Issue
Block a user