Skip to content

Commit

Permalink
Add global variables support
Browse files Browse the repository at this point in the history
- Add Globals widget
- Add global variable add/modify dialog
- Add "Add at" context submenu in Disassembly widget
  • Loading branch information
XVilka committed Aug 1, 2023
1 parent 6b07348 commit 0b697b7
Show file tree
Hide file tree
Showing 13 changed files with 607 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(SOURCES
dialogs/CommentsDialog.cpp
dialogs/EditInstructionDialog.cpp
dialogs/FlagDialog.cpp
dialogs/GlobalVariableDialog.cpp
dialogs/RemoteDebugDialog.cpp
dialogs/NativeDebugDialog.cpp
dialogs/XrefsDialog.cpp
Expand All @@ -36,6 +37,7 @@ set(SOURCES
widgets/ExportsWidget.cpp
widgets/FlagsWidget.cpp
widgets/FunctionsWidget.cpp
widgets/GlobalsWidget.cpp
widgets/ImportsWidget.cpp
widgets/Omnibar.cpp
widgets/RelocsWidget.cpp
Expand Down Expand Up @@ -172,6 +174,7 @@ set(HEADER_FILES
dialogs/CommentsDialog.h
dialogs/EditInstructionDialog.h
dialogs/FlagDialog.h
dialogs/GlobalVariableDialog.h
dialogs/RemoteDebugDialog.h
dialogs/NativeDebugDialog.h
dialogs/XrefsDialog.h
Expand Down Expand Up @@ -327,6 +330,7 @@ set(UI_FILES
dialogs/CommentsDialog.ui
dialogs/EditInstructionDialog.ui
dialogs/FlagDialog.ui
dialogs/GlobalVariableDialog.ui
dialogs/RemoteDebugDialog.ui
dialogs/NativeDebugDialog.ui
dialogs/XrefsDialog.ui
Expand Down
126 changes: 123 additions & 3 deletions src/core/Cutter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,6 +1815,32 @@ QList<VariableDescription> CutterCore::getVariables(RVA at)
return ret;
}

QList<GlobalDescription> CutterCore::getAllGlobals()
{
CORE_LOCK();
RzListIter *it;

QList<GlobalDescription> ret;

RzAnalysisVarGlobal *glob;
if (core && core->analysis && core->analysis->typedb) {
const RzList *globals = rz_analysis_var_global_get_all(core->analysis);
CutterRzListForeach (globals, it, RzAnalysisVarGlobal, glob) {
const char *gtype = rz_type_as_string(core->analysis->typedb, glob->type);
if (!gtype) {
continue;
}
GlobalDescription global;
global.addr = glob->addr;
global.name = QString(glob->name);
global.type = QString(gtype);
ret << global;
}
}

return ret;
}

QVector<RegisterRefValueDescription> CutterCore::getRegisterRefValues()
{
QVector<RegisterRefValueDescription> result;
Expand Down Expand Up @@ -3141,7 +3167,7 @@ QList<ExportDescription> CutterCore::getAllExports()
}

RzBinSymNames sn = {};
rz_core_sym_name_init(&sn, symbol);
rz_core_sym_name_init(&sn, symbol, true);

ExportDescription exportDescription;
exportDescription.vaddr = rva(bf->o, symbol->paddr, symbol->vaddr, va);
Expand Down Expand Up @@ -4021,6 +4047,100 @@ QList<XrefDescription> CutterCore::getXRefs(RVA addr, bool to, bool whole_functi
return xrefList;
}

void CutterCore::addGlobalVariable(RVA offset, QString name, QString typ)
{
name = sanitizeStringForCommand(name);
typ = sanitizeStringForCommand(typ);
CORE_LOCK();
char *errmsg = NULL;
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
typ.toStdString().c_str(), &errmsg);
if (errmsg) {
qWarning() << tr("Error parsing type: \"") << typ << tr("\" message: ") << errmsg;
free(errmsg);
return;
}
if (!rz_analysis_var_global_create(core->analysis, name.toStdString().c_str(),
globType, offset)) {
return;
}

emit globalVarsChanged();
}

void CutterCore::modifyGlobalVariable(RVA offset, QString name, QString typ)
{
name = sanitizeStringForCommand(name);
typ = sanitizeStringForCommand(typ);
CORE_LOCK();
RzAnalysisVarGlobal *glob = rz_analysis_var_global_get_byaddr_at(core->analysis, offset);
if (!glob) {
return;
}
// Compare if the name is not the same - also rename it
if (name.compare(glob->name)) {
rz_analysis_var_global_rename(core->analysis, glob->name, name.toStdString().c_str());
}
char *errmsg = NULL;
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
typ.toStdString().c_str(), &errmsg);
if (errmsg) {
qWarning() << tr("Error parsing type: \"") << typ << tr("\" message: ") << errmsg;
free(errmsg);
return;
}
rz_analysis_var_global_set_type(glob, globType);

emit globalVarsChanged();
}

void CutterCore::delGlobalVariable(QString name)
{
name = sanitizeStringForCommand(name);
CORE_LOCK();
rz_analysis_var_global_delete_byname(core->analysis, name.toStdString().c_str());

emit globalVarsChanged();
}

void CutterCore::delGlobalVariable(RVA offset)
{
CORE_LOCK();
rz_analysis_var_global_delete_byaddr_at(core->analysis, offset);

emit globalVarsChanged();
}

QString CutterCore::getGlobalVariableType(QString name)
{
name = sanitizeStringForCommand(name);
CORE_LOCK();
RzAnalysisVarGlobal *glob = rz_analysis_var_global_get_byname(core->analysis,
name.toStdString().c_str());
if (!glob) {
return QString("");
}
const char *gtype = rz_type_as_string(core->analysis->typedb, glob->type);
if (!gtype) {
return QString("");
}
return QString(gtype);
}

QString CutterCore::getGlobalVariableType(RVA offset)
{
CORE_LOCK();
RzAnalysisVarGlobal *glob = rz_analysis_var_global_get_byaddr_at(core->analysis, offset);
if (!glob) {
return QString("");
}
const char *gtype = rz_type_as_string(core->analysis->typedb, glob->type);
if (!gtype) {
return QString("");
}
return QString(gtype);
}

void CutterCore::addFlag(RVA offset, QString name, RVA size)
{
name = sanitizeStringForCommand(name);
Expand Down Expand Up @@ -4526,9 +4646,9 @@ char *CutterCore::getTextualGraphAt(RzCoreGraphType type, RzCoreGraphFormat form
RzGraph *graph = rz_core_graph(core, type, address);
if (!graph) {
if (address == RVA_INVALID) {
qWarning() << "Cannot get global graph";
qWarning() << tr("Cannot get global graph");
} else {
qWarning() << "Cannot get graph at " << RzAddressString(address);
qWarning() << tr("Cannot get graph at ") << RzAddressString(address);
}
return nullptr;
}
Expand Down
10 changes: 10 additions & 0 deletions src/core/Cutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ class CUTTER_EXPORT CutterCore : public QObject
QString nearestFlag(RVA offset, RVA *flagOffsetOut);
void triggerFlagsChanged();

/* Global Variables */
void addGlobalVariable(RVA offset, QString name, QString typ);
void delGlobalVariable(QString name);
void delGlobalVariable(RVA offset);
void modifyGlobalVariable(RVA offset, QString name, QString typ);
QString getGlobalVariableType(QString name);
QString getGlobalVariableType(RVA offset);

/* Edition functions */
PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr);
QString getInstructionBytes(RVA addr);
Expand Down Expand Up @@ -584,6 +592,7 @@ class CUTTER_EXPORT CutterCore : public QObject
QList<ExportDescription> getAllExports();
QList<SymbolDescription> getAllSymbols();
QList<HeaderDescription> getAllHeaders();
QList<GlobalDescription> getAllGlobals();
QList<FlirtDescription> getSignaturesDB();
QList<CommentDescription> getAllComments(const QString &filterType);
QList<RelocDescription> getAllRelocs();
Expand Down Expand Up @@ -750,6 +759,7 @@ class CUTTER_EXPORT CutterCore : public QObject

void functionRenamed(const RVA offset, const QString &new_name);
void varsChanged();
void globalVarsChanged();
void functionsChanged();
void flagsChanged();
void commentsChanged(RVA addr);
Expand Down
8 changes: 8 additions & 0 deletions src/core/CutterDescriptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,13 @@ struct VariableDescription
QString value;
};

struct GlobalDescription
{
RVA addr;
QString type;
QString name;
};

struct RegisterRefValueDescription
{
QString name;
Expand Down Expand Up @@ -407,6 +414,7 @@ Q_DECLARE_METATYPE(RelocDescription)
Q_DECLARE_METATYPE(StringDescription)
Q_DECLARE_METATYPE(FlagspaceDescription)
Q_DECLARE_METATYPE(FlagDescription)
Q_DECLARE_METATYPE(GlobalDescription)
Q_DECLARE_METATYPE(XrefDescription)
Q_DECLARE_METATYPE(EntrypointDescription)
Q_DECLARE_METATYPE(RzBinPluginDescription)
Expand Down
3 changes: 3 additions & 0 deletions src/core/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "widgets/DisassemblerGraphView.h"
#include "widgets/GraphView.h"
#include "widgets/GraphWidget.h"
#include "widgets/GlobalsWidget.h"
#include "widgets/OverviewWidget.h"
#include "widgets/OverviewView.h"
#include "widgets/FunctionsWidget.h"
Expand Down Expand Up @@ -401,6 +402,7 @@ void MainWindow::initDocks()
sectionsDock = new SectionsWidget(this),
segmentsDock = new SegmentsWidget(this),
symbolsDock = new SymbolsWidget(this),
globalsDock = new GlobalsWidget(this),
vTablesDock = new VTablesWidget(this),
flirtDock = new FlirtWidget(this),
rzGraphDock = new RizinGraphWidget(this),
Expand Down Expand Up @@ -905,6 +907,7 @@ void MainWindow::restoreDocks()
tabifyDockWidget(dashboardDock, headersDock);
tabifyDockWidget(dashboardDock, flirtDock);
tabifyDockWidget(dashboardDock, symbolsDock);
tabifyDockWidget(dashboardDock, globalsDock);
tabifyDockWidget(dashboardDock, classesDock);
tabifyDockWidget(dashboardDock, resourcesDock);
tabifyDockWidget(dashboardDock, vTablesDock);
Expand Down
2 changes: 2 additions & 0 deletions src/core/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class FunctionsWidget;
class ImportsWidget;
class ExportsWidget;
class SymbolsWidget;
class GlobalsWidget;
class RelocsWidget;
class CommentsWidget;
class StringsWidget;
Expand Down Expand Up @@ -240,6 +241,7 @@ private slots:
TypesWidget *typesDock = nullptr;
SearchWidget *searchDock = nullptr;
SymbolsWidget *symbolsDock = nullptr;
GlobalsWidget *globalsDock = nullptr;
RelocsWidget *relocsDock = nullptr;
CommentsWidget *commentsDock = nullptr;
StringsWidget *stringsDock = nullptr;
Expand Down
64 changes: 64 additions & 0 deletions src/dialogs/GlobalVariableDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "GlobalVariableDialog.h"
#include "ui_GlobalVariableDialog.h"

#include <QIntValidator>
#include "core/Cutter.h"

GlobalVariableDialog::GlobalVariableDialog(RVA offset, QWidget *parent)
: QDialog(parent), ui(new Ui::GlobalVariableDialog), offset(offset), globalVariableName("")
{
// Setup UI
ui->setupUi(this);
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
RzAnalysisVarGlobal *globalVariable = rz_analysis_var_global_get_byaddr_at(Core()->core()->analysis, offset);
if (globalVariable) {
globalVariableName = QString(globalVariable->name);
globalVariableOffset = globalVariable->addr;
}

if (globalVariable) {
ui->nameEdit->setText(globalVariable->name);
QString globalVarType = Core()->getGlobalVariableType(globalVariable->name);
ui->typeEdit->setText(globalVarType);
ui->labelAction->setText(tr("Edit global variable at %1").arg(RzAddressString(offset)));
} else {
ui->labelAction->setText(tr("Add global variable at %1").arg(RzAddressString(offset)));
}

// Connect slots
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &GlobalVariableDialog::buttonBoxAccepted);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &GlobalVariableDialog::buttonBoxRejected);
}

GlobalVariableDialog::~GlobalVariableDialog() {}

void GlobalVariableDialog::buttonBoxAccepted()
{
QString name = ui->nameEdit->text();
QString typ = ui->typeEdit->text();

if (name.isEmpty()) {
if (globalVariableOffset != RVA_INVALID) {
// Empty name and global variable exists -> delete the global variable
Core()->delGlobalVariable(globalVariableOffset);
} else {
// GlobalVariable was not existing and we gave an empty name, do nothing
}
} else {
if (globalVariableOffset != RVA_INVALID) {
// Name provided and global variable exists -> rename the global variable
Core()->modifyGlobalVariable(globalVariableOffset, name, typ);
} else {
// Name provided and global variable does not exist -> create the global variable
Core()->addGlobalVariable(globalVariableOffset, name, typ);
}
}
close();
this->setResult(QDialog::Accepted);
}

void GlobalVariableDialog::buttonBoxRejected()
{
close();
this->setResult(QDialog::Rejected);
}
32 changes: 32 additions & 0 deletions src/dialogs/GlobalVariableDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef GLOBALVARIABLEDIALOG_H
#define GLOBALVARIABLEDIALOG_H

#include <QDialog>
#include <memory>
#include "core/CutterCommon.h"

namespace Ui {
class GlobalVariableDialog;
}

class GlobalVariableDialog : public QDialog
{
Q_OBJECT

public:
explicit GlobalVariableDialog(RVA offset, QWidget *parent = nullptr);
~GlobalVariableDialog();

private slots:
void buttonBoxAccepted();
void buttonBoxRejected();

private:
std::unique_ptr<Ui::GlobalVariableDialog> ui;
RVA offset;
QString globalVariableName;
ut64 globalVariableOffset;
QString typ;
};

#endif // GLOBALVARIABLEDIALOG_H
Loading

0 comments on commit 0b697b7

Please sign in to comment.