Define string of length N in address (#1915)

* Implemented "setString" submenu for the Disasm widget
This commit is contained in:
Properrr 2019-12-18 06:26:51 -08:00 committed by Itay Cohen
parent 8f480d9c2c
commit 78c6e651c8
8 changed files with 407 additions and 7 deletions

View File

@ -258,6 +258,7 @@ QMAKE_SUBSTITUTES += CutterConfig.h.in
SOURCES += \ SOURCES += \
Main.cpp \ Main.cpp \
core/Cutter.cpp \ core/Cutter.cpp \
dialogs/EditStringDialog.cpp \
widgets/DisassemblerGraphView.cpp \ widgets/DisassemblerGraphView.cpp \
widgets/OverviewView.cpp \ widgets/OverviewView.cpp \
common/RichTextPainter.cpp \ common/RichTextPainter.cpp \
@ -393,6 +394,7 @@ HEADERS += \
core/Cutter.h \ core/Cutter.h \
core/CutterCommon.h \ core/CutterCommon.h \
core/CutterDescriptions.h \ core/CutterDescriptions.h \
dialogs/EditStringDialog.h \
widgets/DisassemblerGraphView.h \ widgets/DisassemblerGraphView.h \
widgets/OverviewView.h \ widgets/OverviewView.h \
common/RichTextPainter.h \ common/RichTextPainter.h \
@ -532,6 +534,7 @@ GRAPHVIZ_HEADERS = widgets/GraphGridLayout.h
FORMS += \ FORMS += \
dialogs/AboutDialog.ui \ dialogs/AboutDialog.ui \
dialogs/EditStringDialog.ui \
dialogs/preferences/AsmOptionsWidget.ui \ dialogs/preferences/AsmOptionsWidget.ui \
dialogs/CommentsDialog.ui \ dialogs/CommentsDialog.ui \
dialogs/EditInstructionDialog.ui \ dialogs/EditInstructionDialog.ui \

View File

@ -643,12 +643,59 @@ void CutterCore::setToCode(RVA addr)
emit instructionChanged(addr); emit instructionChanged(addr);
} }
void CutterCore::setAsString(RVA addr) void CutterCore::setAsString(RVA addr, int size, StringTypeFormats type)
{ {
cmd("Cs @ " + RAddressString(addr)); if(RVA_INVALID == addr)
{
return;
}
QString command;
switch(type)
{
case StringTypeFormats::None:
{
command = "Cs ";
break;
}
case StringTypeFormats::ASCII_LATIN1:
{
command = "Csa ";
break;
}
case StringTypeFormats::UTF8:
{
command = "Cs8 ";
break;
}
default:
return;
}
seekAndShow(addr);
QString arg;
if(size > 0) {
arg = QString::asprintf("%d @ %lld", size, addr);
} else {
arg = QString::asprintf("@ %lld", addr);
}
cmd(command + arg);
emit instructionChanged(addr); emit instructionChanged(addr);
} }
void CutterCore::removeString(RVA addr)
{
cmd("Cs- @ " + RAddressString(addr));
emit instructionChanged(addr);
}
QString CutterCore::getString(RVA addr)
{
return cmd("ps @ " + RAddressString(addr));
}
void CutterCore::setToData(RVA addr, int size, int repeat) void CutterCore::setToData(RVA addr, int size, int repeat)
{ {
if (size <= 0 || repeat <= 0) { if (size <= 0 || repeat <= 0) {

View File

@ -145,7 +145,28 @@ public:
/* Code/Data */ /* Code/Data */
void setToCode(RVA addr); void setToCode(RVA addr);
void setAsString(RVA addr); enum class StringTypeFormats { None, ASCII_LATIN1, UTF8 };
/**
* @brief Adds string at address
* That function calls the 'Cs' command
* \param addr The address of the array where the string will be applied
* \param size The size of string
* \param type The type of string
*/
void setAsString(RVA addr, int size = 0, StringTypeFormats type = StringTypeFormats::None);
/**
* @brief Removes string at address
* That function calls the 'Cs-' command
* \param addr The address of the array where the string will be applied
*/
void removeString(RVA addr);
/**
* @brief Gets string at address
* That function calls the 'ps' command
* \param addr The address of the first byte of the array
* @return string at requested address
*/
QString getString(RVA addr);
void setToData(RVA addr, int size, int repeat = 1); void setToData(RVA addr, int size, int repeat = 1);
int sizeofDataMeta(RVA addr); int sizeofDataMeta(RVA addr);

View File

@ -0,0 +1,68 @@
#include "EditStringDialog.h"
#include "ui_EditStringDialog.h"
EditStringDialog::EditStringDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::EditStringDialog)
{
ui->setupUi(this);
ui->spinBox_size->setMinimum(0);
ui->lineEdit_address->setMinimumWidth(150);
ui->pushButton_ok->setFocus();
ui->comboBox_type->addItems({"Auto", "ASCII/Latin1", "UTF-8"});
connect(ui->checkBox_autoSize, &QCheckBox::toggled, ui->spinBox_size, &QSpinBox::setDisabled);
}
EditStringDialog::~EditStringDialog()
{
delete ui;
}
void EditStringDialog::setStringStartAddress(uint64_t address)
{
ui->lineEdit_address->setText(QString::number(address, 16));
}
bool EditStringDialog::getStringStartAddress(uint64_t& returnValue) const
{
bool status = false;
returnValue = ui->lineEdit_address->text().toLongLong(&status, 16);
return status;
}
void EditStringDialog::setStringSizeValue(uint32_t size)
{
ui->spinBox_size->setValue(size);
}
int EditStringDialog::getStringSizeValue() const
{
if( ui->checkBox_autoSize->isChecked() ) {
return -1;
}
return ui->spinBox_size->value();
}
EditStringDialog::StringType EditStringDialog::getStringType() const
{
const int indexVal = ui->comboBox_type->currentIndex();
switch(indexVal)
{
case 0:
{
return EditStringDialog::StringType::Auto;
}
case 1:
{
return EditStringDialog::StringType::ASCII_LATIN1;
}
case 2:
{
return EditStringDialog::StringType::UTF8;
}
default:
return EditStringDialog::StringType::Auto;
}
}

View File

@ -0,0 +1,58 @@
#ifndef EDITSTRINGDIALOG_H
#define EDITSTRINGDIALOG_H
#include <QDialog>
namespace Ui {
class EditStringDialog;
}
class EditStringDialog : public QDialog
{
Q_OBJECT
public:
enum class StringType {Auto, ASCII_LATIN1, UTF8};
explicit EditStringDialog(QWidget *parent = nullptr);
~EditStringDialog();
/**
* @brief Sets the address of the first byte of potential string in the dialog
*
* @param address The address of the bytearray where string is located
*/
void setStringStartAddress(uint64_t address);
/**
* @brief Returns the address of the first byte of potential string in the dialog
*
* @param[out] returnValue The address of the bytearray where string is located
* @return whether the call successful or not
*/
bool getStringStartAddress(uint64_t &returnValue) const;
/**
* @brief Sets the size of string in the dialog
*
* @param size The size of string in the dialog
*/
void setStringSizeValue(uint32_t size);
/**
* @brief Returns the size of string in the dialog
*
* @return -1 on error otherwise the size of string from the dialog
*/
int getStringSizeValue() const;
/**
* @brief Returns the type of string from the dialog
*
* @return The type of string from the dialog
*/
StringType getStringType() const;
private:
Ui::EditStringDialog *ui;
};
#endif // EDITSTRINGDIALOG_H

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditStringDialog</class>
<widget class="QDialog" name="EditStringDialog">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>243</width>
<height>109</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Edit string</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_address">
<property name="text">
<string>Address:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_size">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_type">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="lineEdit_address">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_size">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBox_type"/>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="checkBox_autoSize">
<property name="text">
<string>Auto</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButton_cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButton_ok">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>pushButton_cancel</sender>
<signal>clicked()</signal>
<receiver>EditStringDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>51</x>
<y>94</y>
</hint>
<hint type="destinationlabel">
<x>174</x>
<y>67</y>
</hint>
</hints>
</connection>
<connection>
<sender>pushButton_ok</sender>
<signal>clicked()</signal>
<receiver>EditStringDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>143</x>
<y>92</y>
</hint>
<hint type="destinationlabel">
<x>153</x>
<y>71</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -9,6 +9,7 @@
#include "dialogs/SetToDataDialog.h" #include "dialogs/SetToDataDialog.h"
#include "dialogs/EditFunctionDialog.h" #include "dialogs/EditFunctionDialog.h"
#include "dialogs/LinkTypeDialog.h" #include "dialogs/LinkTypeDialog.h"
#include "dialogs/EditStringDialog.h"
#include "MainWindow.h" #include "MainWindow.h"
#include <QtCore> #include <QtCore>
@ -57,7 +58,9 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
actionAddBreakpoint(this), actionAddBreakpoint(this),
actionSetPC(this), actionSetPC(this),
actionSetToCode(this), actionSetToCode(this),
actionSetAsString(this), actionSetAsStringAuto(this),
actionSetAsStringRemove(this),
actionSetAsStringAdvanced(this),
actionSetToDataEx(this), actionSetToDataEx(this),
actionSetToDataByte(this), actionSetToDataByte(this),
actionSetToDataWord(this), actionSetToDataWord(this),
@ -219,9 +222,19 @@ void DisassemblyContextMenu::addSetAsMenu()
SLOT(on_actionSetToCode_triggered()), getSetToCodeSequence()); SLOT(on_actionSetToCode_triggered()), getSetToCodeSequence());
setAsMenu->addAction(&actionSetToCode); setAsMenu->addAction(&actionSetToCode);
initAction(&actionSetAsString, tr("String"), setAsString = setAsMenu->addMenu(tr("String..."));
initAction(&actionSetAsStringAuto, tr("Auto-detect"),
SLOT(on_actionSetAsString_triggered()), getSetAsStringSequence()); SLOT(on_actionSetAsString_triggered()), getSetAsStringSequence());
setAsMenu->addAction(&actionSetAsString); initAction(&actionSetAsStringRemove, tr("Remove"),
SLOT(on_actionSetAsStringRemove_triggered()));
initAction(&actionSetAsStringAdvanced, tr("Adanced"),
SLOT(on_actionSetAsStringAdvanced_triggered()));
setAsString->addAction(&actionSetAsStringAuto);
setAsString->addAction(&actionSetAsStringRemove);
setAsString->addAction(&actionSetAsStringAdvanced);
addSetToDataMenu(); addSetToDataMenu();
} }
@ -862,6 +875,47 @@ void DisassemblyContextMenu::on_actionSetAsString_triggered()
Core()->setAsString(offset); Core()->setAsString(offset);
} }
void DisassemblyContextMenu::on_actionSetAsStringRemove_triggered()
{
Core()->removeString(offset);
}
void DisassemblyContextMenu::on_actionSetAsStringAdvanced_triggered()
{
EditStringDialog dialog(parentWidget());
const int predictedStrSize = Core()->getString(offset).size();
dialog.setStringSizeValue(predictedStrSize);
dialog.setStringStartAddress(offset);
if(!dialog.exec())
{
return;
}
uint64_t strAddr = 0U;
if( !dialog.getStringStartAddress(strAddr) ) {
QMessageBox::critical(this->window(), tr("Wrong address"), tr("Can't edit string at this address"));
return;
}
CutterCore::StringTypeFormats coreStringType = CutterCore::StringTypeFormats::None;
const auto strSize = dialog.getStringSizeValue();
const auto strType = dialog.getStringType();
switch(strType)
{
case EditStringDialog::StringType::Auto:
coreStringType = CutterCore::StringTypeFormats::None;
break;
case EditStringDialog::StringType::ASCII_LATIN1:
coreStringType = CutterCore::StringTypeFormats::ASCII_LATIN1;
break;
case EditStringDialog::StringType::UTF8:
coreStringType = CutterCore::StringTypeFormats::UTF8;
break;
};
Core()->setAsString(strAddr, strSize, coreStringType);
}
void DisassemblyContextMenu::on_actionSetToData_triggered() void DisassemblyContextMenu::on_actionSetToData_triggered()
{ {

View File

@ -58,6 +58,8 @@ private slots:
void on_actionSetToCode_triggered(); void on_actionSetToCode_triggered();
void on_actionSetAsString_triggered(); void on_actionSetAsString_triggered();
void on_actionSetAsStringRemove_triggered();
void on_actionSetAsStringAdvanced_triggered();
void on_actionSetToData_triggered(); void on_actionSetToData_triggered();
void on_actionSetToDataEx_triggered(); void on_actionSetToDataEx_triggered();
@ -158,10 +160,14 @@ private:
QAction actionSetPC; QAction actionSetPC;
QAction actionSetToCode; QAction actionSetToCode;
QAction actionSetAsString;
QAction actionSetAsStringAuto;
QAction actionSetAsStringRemove;
QAction actionSetAsStringAdvanced;
QMenu *setToDataMenu; QMenu *setToDataMenu;
QMenu *setAsMenu; QMenu *setAsMenu;
QMenu *setAsString;
QAction actionSetToDataEx; QAction actionSetToDataEx;
QAction actionSetToDataByte; QAction actionSetToDataByte;
QAction actionSetToDataWord; QAction actionSetToDataWord;