Use rizin instead of Qt to parse JSON (#2902)

Qt truncates integers to 52-bit, corrupting e.g. memory addresses. Use
rizin's JSON parser, which can parse integers whose size is up to 64
bits.
This commit is contained in:
Akihiko Odaki 2022-03-14 17:04:49 +09:00 committed by Anton Kochkov
parent ddaa02c0f8
commit 518014ee19
28 changed files with 575 additions and 528 deletions

View File

@ -47,7 +47,7 @@ Example:
.. code:: cpp .. code:: cpp
QJsonArray array = Core()->cmdj("pdj 1 @ main").array(); CutterJson array = Core()->cmdj("pdj 1 @ main");
Seek the Current File Seek the Current File
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~

View File

@ -4,6 +4,7 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CutterConfig.h.in"
set(SOURCES set(SOURCES
Main.cpp Main.cpp
core/Cutter.cpp core/Cutter.cpp
core/CutterJson.cpp
dialogs/EditStringDialog.cpp dialogs/EditStringDialog.cpp
dialogs/WriteCommandsDialogs.cpp dialogs/WriteCommandsDialogs.cpp
widgets/DisassemblerGraphView.cpp widgets/DisassemblerGraphView.cpp
@ -153,6 +154,7 @@ set(HEADER_FILES
core/Cutter.h core/Cutter.h
core/CutterCommon.h core/CutterCommon.h
core/CutterDescriptions.h core/CutterDescriptions.h
core/CutterJson.h
dialogs/EditStringDialog.h dialogs/EditStringDialog.h
dialogs/WriteCommandsDialogs.h dialogs/WriteCommandsDialogs.h
widgets/DisassemblerGraphView.h widgets/DisassemblerGraphView.h

View File

@ -12,13 +12,13 @@ void openIssue()
// Pull in info needed for git issue // Pull in info needed for git issue
osInfo = QSysInfo::productType() + " " osInfo = QSysInfo::productType() + " "
+ (QSysInfo::productVersion() == "unknown" ? "" : QSysInfo::productVersion()); + (QSysInfo::productVersion() == "unknown" ? "" : QSysInfo::productVersion());
QJsonDocument docu = Core()->getFileInfo(); CutterJson docu = Core()->getFileInfo();
QJsonObject coreObj = docu.object()["core"].toObject(); CutterJson coreObj = docu["core"];
QJsonObject binObj = docu.object()["bin"].toObject(); CutterJson binObj = docu["bin"];
if (!binObj.QJsonObject::isEmpty()) { if (binObj.size()) {
format = coreObj["format"].toString(); format = coreObj["format"].toString();
arch = binObj["arch"].toString(); arch = binObj["arch"].toString();
if (!binObj["type"].isUndefined()) { if (binObj["type"].valid()) {
type = coreObj["type"].toString(); type = coreObj["type"].toString();
} else { } else {
type = "N/A"; type = "N/A";

View File

@ -128,22 +128,34 @@ bool ColorThemeWorker::isThemeExist(const QString &name) const
QJsonDocument ColorThemeWorker::getTheme(const QString &themeName) const QJsonDocument ColorThemeWorker::getTheme(const QString &themeName) const
{ {
int r, g, b, a; int r, g, b, a;
CutterJson rzTheme;
QVariantMap theme; QVariantMap theme;
QString curr = Config()->getColorTheme(); QString curr = Config()->getColorTheme();
if (themeName != curr) { if (themeName != curr) {
RzCoreLocked core(Core()); RzCoreLocked core(Core());
rz_core_theme_load(core, themeName.toUtf8().constData()); rz_core_theme_load(core, themeName.toUtf8().constData());
theme = Core()->cmdj("ecj").object().toVariantMap(); rzTheme = Core()->cmdj("ecj");
rz_core_theme_load(core, curr.toUtf8().constData()); rz_core_theme_load(core, curr.toUtf8().constData());
} else { } else {
theme = Core()->cmdj("ecj").object().toVariantMap(); rzTheme = Core()->cmdj("ecj");
} }
for (auto it = theme.begin(); it != theme.end(); it++) { for (CutterJson value : rzTheme) {
auto arr = it.value().toList(); QJsonArray arr;
QColor(arr[0].toInt(), arr[1].toInt(), arr[2].toInt()).getRgb(&r, &g, &b, &a); int count = 0;
theme[it.key()] = QJsonArray({ r, g, b, a }); for (CutterJson element : value) {
arr.append(element.toSt64());
count++;
if (count >= 3) {
break;
}
}
while (count < 3) {
arr.append(0);
}
arr.append(255);
theme[value.key()] = arr;
} }
ColorFlags colorFlags = ColorFlags::DarkFlag; ColorFlags colorFlags = ColorFlags::DarkFlag;
@ -278,9 +290,8 @@ bool ColorThemeWorker::isFileTheme(const QString &filePath, bool *ok) const
} }
const QString colors = "black|red|white|green|magenta|yellow|cyan|blue|gray|none"; const QString colors = "black|red|white|green|magenta|yellow|cyan|blue|gray|none";
QString options = (Core()->cmdj("ecj").object().keys() << cutterSpecificOptions) QString options =
.join('|') (Core()->cmdj("ecj").keys() << cutterSpecificOptions).join('|').replace(".", "\\.");
.replace(".", "\\.");
QString pattern = QString("((ec\\s+(%1)\\s+(((rgb:|#)[0-9a-fA-F]{3,8})|(%2))))\\s*") QString pattern = QString("((ec\\s+(%1)\\s+(((rgb:|#)[0-9a-fA-F]{3,8})|(%2))))\\s*")
.arg(options) .arg(options)
@ -315,7 +326,7 @@ QStringList ColorThemeWorker::customThemes() const
const QStringList &ColorThemeWorker::getRizinSpecificOptions() const QStringList &ColorThemeWorker::getRizinSpecificOptions()
{ {
if (rizinSpecificOptions.isEmpty()) { if (rizinSpecificOptions.isEmpty()) {
rizinSpecificOptions = Core()->cmdj("ecj").object().keys(); rizinSpecificOptions = Core()->cmdj("ecj").keys();
} }
return rizinSpecificOptions; return rizinSpecificOptions;
} }

View File

@ -5,6 +5,7 @@
#include <QColor> #include <QColor>
#include <QObject> #include <QObject>
#include "Cutter.h" #include "Cutter.h"
#include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#define ThemeWorker() (ColorThemeWorker::instance()) #define ThemeWorker() (ColorThemeWorker::instance())

View File

@ -33,40 +33,37 @@ void JSDecDecompiler::decompileAt(RVA addr)
} }
task = new RizinCmdTask("pddj @ " + QString::number(addr)); task = new RizinCmdTask("pddj @ " + QString::number(addr));
connect(task, &RizinCmdTask::finished, this, [this]() { connect(task, &RizinCmdTask::finished, this, [this]() {
QJsonObject json = task->getResultJson().object(); CutterJson json = task->getResultJson();
delete task; delete task;
task = nullptr; task = nullptr;
if (json.isEmpty()) { if (!json.size()) {
emit finished(Decompiler::makeWarning(tr("Failed to parse JSON from jsdec"))); emit finished(Decompiler::makeWarning(tr("Failed to parse JSON from jsdec")));
return; return;
} }
RzAnnotatedCode *code = rz_annotated_code_new(nullptr); RzAnnotatedCode *code = rz_annotated_code_new(nullptr);
QString codeString = ""; QString codeString = "";
for (const auto &line : json["log"].toArray()) { for (auto line : json["log"]) {
if (!line.isString()) { if (line.type() != RZ_JSON_STRING) {
continue; continue;
} }
codeString.append(line.toString() + "\n"); codeString.append(line.toString() + "\n");
} }
auto linesArray = json["lines"].toArray(); for (auto lineObject : json["lines"]) {
for (const auto &line : linesArray) { if (!lineObject.size()) {
QJsonObject lineObject = line.toObject();
if (lineObject.isEmpty()) {
continue; continue;
} }
RzCodeAnnotation annotationi = {}; RzCodeAnnotation annotationi = {};
annotationi.start = codeString.length(); annotationi.start = codeString.length();
codeString.append(lineObject["str"].toString() + "\n"); codeString.append(lineObject["str"].toString() + "\n");
annotationi.end = codeString.length(); annotationi.end = codeString.length();
bool ok;
annotationi.type = RZ_CODE_ANNOTATION_TYPE_OFFSET; annotationi.type = RZ_CODE_ANNOTATION_TYPE_OFFSET;
annotationi.offset.offset = lineObject["offset"].toVariant().toULongLong(&ok); annotationi.offset.offset = lineObject["offset"].toUt64();
rz_annotated_code_add_annotation(code, &annotationi); rz_annotated_code_add_annotation(code, &annotationi);
} }
for (const auto &line : json["errors"].toArray()) { for (auto line : json["errors"]) {
if (!line.isString()) { if (line.type() != RZ_JSON_STRING) {
continue; continue;
} }
codeString.append(line.toString() + "\n"); codeString.append(line.toString() + "\n");

View File

@ -78,11 +78,10 @@ bool IOModesController::prepareForWriting()
bool IOModesController::allChangesComitted() bool IOModesController::allChangesComitted()
{ {
// Get a list of available write changes // Get a list of available write changes
QJsonArray changes = Core()->cmdj("wcj").array(); CutterJson changes = Core()->cmdj("wcj");
// Check if there is a change which isn't written to the file // Check if there is a change which isn't written to the file
for (const QJsonValue &value : changes) { for (CutterJson changeObject : changes) {
QJsonObject changeObject = value.toObject();
if (!changeObject["written"].toBool()) { if (!changeObject["written"].toBool()) {
return false; return false;
} }

View File

@ -54,13 +54,15 @@ QString RizinCmdTask::getResult()
return QString::fromUtf8(res); return QString::fromUtf8(res);
} }
QJsonDocument RizinCmdTask::getResultJson() CutterJson RizinCmdTask::getResultJson()
{ {
const char *res = rz_core_cmd_task_get_result(task); const char *res = rz_core_cmd_task_get_result(task);
if (!res) { if (!res) {
return QJsonDocument(); return CutterJson();
} }
return Core()->parseJson(res, nullptr); char *copy = static_cast<char *>(rz_mem_alloc(strlen(res) + 1));
strcpy(copy, res);
return Core()->parseJson(copy, nullptr);
} }
const char *RizinCmdTask::getResultRaw() const char *RizinCmdTask::getResultRaw()

View File

@ -38,7 +38,7 @@ public:
explicit RizinCmdTask(const QString &cmd, bool transient = true); explicit RizinCmdTask(const QString &cmd, bool transient = true);
QString getResult(); QString getResult();
QJsonDocument getResultJson(); CutterJson getResultJson();
const char *getResultRaw(); const char *getResultRaw();
}; };

View File

@ -181,7 +181,7 @@ void Cutter::initializeSettings()
static void removeObsoleteOptionsFromCustomThemes() static void removeObsoleteOptionsFromCustomThemes()
{ {
const QStringList options = Core()->cmdj("ecj").object().keys() const QStringList options = Core()->cmdj("ecj").keys()
<< ColorThemeWorker::cutterSpecificOptions; << ColorThemeWorker::cutterSpecificOptions;
RzList *themes_list = rz_core_theme_list(Core()->core()); RzList *themes_list = rz_core_theme_list(Core()->core());
RzListIter *th_iter; RzListIter *th_iter;

File diff suppressed because it is too large Load Diff

View File

@ -3,15 +3,16 @@
#include "core/CutterCommon.h" #include "core/CutterCommon.h"
#include "core/CutterDescriptions.h" #include "core/CutterDescriptions.h"
#include "core/CutterJson.h"
#include "common/BasicInstructionHighlighter.h" #include "common/BasicInstructionHighlighter.h"
#include <QMap> #include <QMap>
#include <QMenu> #include <QMenu>
#include <QDebug> #include <QDebug>
#include <QObject> #include <QObject>
#include <QSharedPointer>
#include <QStringList> #include <QStringList>
#include <QMessageBox> #include <QMessageBox>
#include <QJsonDocument>
#include <QErrorMessage> #include <QErrorMessage>
#include <QMutex> #include <QMutex>
#include <QDir> #include <QDir>
@ -34,6 +35,29 @@ class RizinTaskDialog;
class RzCoreLocked; class RzCoreLocked;
struct CUTTER_EXPORT AddrRefs
{
RVA addr;
QString mapname;
QString section;
QString reg;
QString fcn;
QString type;
QString asm_op;
QString perms;
ut64 value;
bool has_value;
QString string;
QSharedPointer<AddrRefs> ref;
};
struct CUTTER_EXPORT RegisterRef
{
ut64 value;
AddrRefs ref;
QString name;
};
class CUTTER_EXPORT CutterCore : public QObject class CUTTER_EXPORT CutterCore : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -124,16 +148,16 @@ public:
seekSilent(oldOffset); seekSilent(oldOffset);
} }
QJsonDocument cmdj(const char *str); CutterJson cmdj(const char *str);
QJsonDocument cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); } CutterJson cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
QJsonDocument cmdjAt(const char *str, RVA address); CutterJson cmdjAt(const char *str, RVA address);
QStringList cmdList(const char *str) QStringList cmdList(const char *str)
{ {
return cmd(str).split(QLatin1Char('\n'), CUTTER_QT_SKIP_EMPTY_PARTS); return cmd(str).split(QLatin1Char('\n'), CUTTER_QT_SKIP_EMPTY_PARTS);
} }
QStringList cmdList(const QString &str) { return cmdList(str.toUtf8().constData()); } QStringList cmdList(const QString &str) { return cmdList(str.toUtf8().constData()); }
QString cmdTask(const QString &str); QString cmdTask(const QString &str);
QJsonDocument cmdjTask(const QString &str); CutterJson cmdjTask(const QString &str);
/** /**
* @brief send a command to Rizin and check for ESIL errors * @brief send a command to Rizin and check for ESIL errors
* @param command the command you want to execute * @param command the command you want to execute
@ -159,8 +183,8 @@ public:
QString getRizinVersionReadable(); QString getRizinVersionReadable();
QString getVersionInformation(); QString getVersionInformation();
QJsonDocument parseJson(const char *res, const char *cmd = nullptr); CutterJson parseJson(char *res, const char *cmd = nullptr);
QJsonDocument parseJson(const char *res, const QString &cmd = QString()) CutterJson parseJson(char *res, const QString &cmd = QString())
{ {
return parseJson(res, cmd.isNull() ? nullptr : cmd.toLocal8Bit().constData()); return parseJson(res, cmd.isNull() ? nullptr : cmd.toLocal8Bit().constData());
} }
@ -376,8 +400,8 @@ public:
bool sdbSet(QString path, QString key, QString val); bool sdbSet(QString path, QString key, QString val);
/* Debug */ /* Debug */
QJsonDocument getRegistersInfo(); CutterJson getRegistersInfo();
QJsonDocument getRegisterValues(); CutterJson getRegisterValues();
QString getRegisterName(QString registerRole); QString getRegisterName(QString registerRole);
RVA getProgramCounterValue(); RVA getProgramCounterValue();
void setRegister(QString regName, QString regValue); void setRegister(QString regName, QString regValue);
@ -391,32 +415,32 @@ public:
* @param size number of bytes to scan * @param size number of bytes to scan
* @param depth telescoping depth * @param depth telescoping depth
*/ */
QList<QJsonObject> getStack(int size = 0x100, int depth = 6); QList<AddrRefs> getStack(int size = 0x100, int depth = 6);
/** /**
* @brief Recursively dereferences pointers starting at the specified address * @brief Recursively dereferences pointers starting at the specified address
* up to a given depth * up to a given depth
* @param addr telescoping addr * @param addr telescoping addr
* @param depth telescoping depth * @param depth telescoping depth
*/ */
QJsonObject getAddrRefs(RVA addr, int depth); AddrRefs getAddrRefs(RVA addr, int depth);
/** /**
* @brief return a RefDescription with a formatted ref string and configured colors * @brief return a RefDescription with a formatted ref string and configured colors
* @param ref the "ref" JSON node from getAddrRefs * @param ref the "ref" JSON node from getAddrRefs
*/ */
RefDescription formatRefDesc(QJsonObject ref); RefDescription formatRefDesc(const AddrRefs &ref);
/** /**
* @brief Get a list of a given process's threads * @brief Get a list of a given process's threads
* @param pid The pid of the process, -1 for the currently debugged process * @param pid The pid of the process, -1 for the currently debugged process
* @return JSON object result of dptj * @return JSON object result of dptj
*/ */
QJsonDocument getProcessThreads(int pid); CutterJson getProcessThreads(int pid);
/** /**
* @brief Get a list of a given process's child processes * @brief Get a list of a given process's child processes
* @param pid The pid of the process, -1 for the currently debugged process * @param pid The pid of the process, -1 for the currently debugged process
* @return JSON object result of dptj * @return JSON object result of dptj
*/ */
QJsonDocument getChildProcesses(int pid); CutterJson getChildProcesses(int pid);
QJsonDocument getBacktrace(); CutterJson getBacktrace();
/** /**
* @brief Get a list of heap chunks * @brief Get a list of heap chunks
* Uses RZ_API rz_heap_chunks_list to get vector of chunks * Uses RZ_API rz_heap_chunks_list to get vector of chunks
@ -532,9 +556,9 @@ public:
bool registerDecompiler(Decompiler *decompiler); bool registerDecompiler(Decompiler *decompiler);
RVA getOffsetJump(RVA addr); RVA getOffsetJump(RVA addr);
QJsonDocument getFileInfo(); CutterJson getFileInfo();
QJsonDocument getSignatureInfo(); CutterJson getSignatureInfo();
QJsonDocument getFileVersionInfo(); CutterJson getFileVersionInfo();
QStringList getStats(); QStringList getStats();
void setGraphEmpty(bool empty); void setGraphEmpty(bool empty);
bool isGraphEmpty(); bool isGraphEmpty();
@ -631,7 +655,7 @@ public:
* @brief returns a list of reg values and their telescoped references * @brief returns a list of reg values and their telescoped references
* @param depth telescoping depth * @param depth telescoping depth
*/ */
QList<QJsonObject> getRegisterRefs(int depth = 6); QList<RegisterRef> getRegisterRefs(int depth = 6);
QVector<RegisterRefValueDescription> getRegisterRefValues(); QVector<RegisterRefValueDescription> getRegisterRefValues();
QList<VariableDescription> getVariables(RVA at); QList<VariableDescription> getVariables(RVA at);
/** /**
@ -649,7 +673,7 @@ public:
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function, QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
const QString &filterType = QString()); const QString &filterType = QString());
QList<StringDescription> parseStringsJson(const QJsonDocument &doc); QList<StringDescription> parseStringsJson(const CutterJson &doc);
void handleREvent(int type, void *data); void handleREvent(int type, void *data);

28
src/core/CutterJson.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "core/CutterJson.h"
CutterJson CutterJson::last() const
{
if (!has_children()) {
return CutterJson();
}
const RzJson *last = value->children.first;
while (last->next) {
last = last->next;
}
return CutterJson(last, owner);
}
QStringList CutterJson::keys() const
{
QStringList list;
if (value && value->type == RZ_JSON_OBJECT) {
for (const RzJson *child = value->children.first; child; child = child->next) {
list.append(child->key);
}
}
return list;
}

119
src/core/CutterJson.h Normal file
View File

@ -0,0 +1,119 @@
#ifndef CUTTER_JSON_H
#define CUTTER_JSON_H
#include "core/CutterCommon.h"
#include <QSharedPointer>
#include <QString>
#include <QStringList>
#include <rz_project.h>
class CutterJsonOwner;
class CUTTER_EXPORT CutterJson
{
public:
class iterator
{
public:
iterator(const RzJson *value, QSharedPointer<CutterJsonOwner> owner)
: value(value), owner(owner)
{
}
CutterJson operator*() const { return CutterJson(value, owner); }
bool operator!=(const iterator &other) const { return value != other.value; }
iterator &operator++()
{
value = value->next;
return *this;
}
private:
const RzJson *value;
QSharedPointer<CutterJsonOwner> owner;
};
CutterJson() : value(nullptr), owner(nullptr) {}
CutterJson(const RzJson *value, QSharedPointer<CutterJsonOwner> owner)
: value(value), owner(owner)
{
}
CutterJson first() const
{
return CutterJson(has_children() ? value->children.first : nullptr, owner);
}
CutterJson last() const;
CutterJson operator[](const QString &key) const
{
QByteArray utf8 = key.toUtf8();
return (*this)[utf8.data()];
}
CutterJson operator[](const char *key) const
{
return CutterJson(
value && value->type == RZ_JSON_OBJECT ? rz_json_get(value, key) : nullptr, owner);
}
iterator begin() const
{
return iterator(has_children() ? value->children.first : nullptr, owner);
}
iterator end() const { return iterator(nullptr, nullptr); }
bool toBool() const { return value && value->type == RZ_JSON_BOOLEAN && value->num.u_value; }
QString toJson() const { return rz_json_as_string(value); }
st64 toSt64() const { return value && value->type == RZ_JSON_INTEGER ? value->num.s_value : 0; }
ut64 toUt64() const { return value && value->type == RZ_JSON_INTEGER ? value->num.u_value : 0; }
RVA toRVA() const
{
return value && value->type == RZ_JSON_INTEGER ? value->num.u_value : RVA_INVALID;
}
QString toString() const
{
return value && value->type == RZ_JSON_STRING ? QString(value->str_value) : QString();
}
QString key() const { return value ? value->key : QString(); }
QStringList keys() const;
size_t size() const { return has_children() ? value->children.count : 0; }
RzJsonType type() const { return value ? value->type : RZ_JSON_NULL; }
bool valid() const { return value ? true : false; }
private:
bool has_children() const
{
return value && (value->type == RZ_JSON_OBJECT || value->type == RZ_JSON_ARRAY);
}
const RzJson *value;
QSharedPointer<CutterJsonOwner> owner;
};
class CUTTER_EXPORT CutterJsonOwner
{
public:
CutterJsonOwner(RzJson *value, char *text) : value(value), text(text) {}
virtual ~CutterJsonOwner()
{
rz_json_free(value);
rz_mem_free(text);
}
private:
RzJson *value;
char *text;
};
#endif // CUTTER_JSON_H

View File

@ -24,12 +24,12 @@ VersionInfoDialog::~VersionInfoDialog() {}
void VersionInfoDialog::fillVersionInfo() void VersionInfoDialog::fillVersionInfo()
{ {
QJsonDocument doc = Core()->getFileVersionInfo(); CutterJson doc = Core()->getFileVersionInfo();
// Case ELF // Case ELF
if (doc.object().contains("verneed")) { if (doc["verneed"].valid()) {
QJsonObject verneed = doc.object()["verneed"].toArray().first().toObject(); CutterJson verneed = doc["verneed"].first();
QJsonObject versym = doc.object()["versym"].toArray().first().toObject(); CutterJson versym = doc["versym"].first();
// Set labels // Set labels
ui->leftLabel->setText("Version symbols"); ui->leftLabel->setText("Version symbols");
@ -43,17 +43,17 @@ void VersionInfoDialog::fillVersionInfo()
QTreeWidgetItem *addrItemL = new QTreeWidgetItem(); QTreeWidgetItem *addrItemL = new QTreeWidgetItem();
addrItemL->setText(0, "Address:"); addrItemL->setText(0, "Address:");
addrItemL->setText(1, RzAddressString(versym["address"].toDouble())); addrItemL->setText(1, RzAddressString(versym["address"].toRVA()));
ui->leftTreeWidget->addTopLevelItem(addrItemL); ui->leftTreeWidget->addTopLevelItem(addrItemL);
QTreeWidgetItem *offItemL = new QTreeWidgetItem(); QTreeWidgetItem *offItemL = new QTreeWidgetItem();
offItemL->setText(0, "Offset:"); offItemL->setText(0, "Offset:");
offItemL->setText(1, RzAddressString(versym["offset"].toDouble())); offItemL->setText(1, RzAddressString(versym["offset"].toRVA()));
ui->leftTreeWidget->addTopLevelItem(offItemL); ui->leftTreeWidget->addTopLevelItem(offItemL);
QTreeWidgetItem *linkItemL = new QTreeWidgetItem(); QTreeWidgetItem *linkItemL = new QTreeWidgetItem();
linkItemL->setText(0, "Link:"); linkItemL->setText(0, "Link:");
linkItemL->setText(1, QString::number(versym["link"].toDouble())); linkItemL->setText(1, QString::number(versym["link"].toRVA()));
ui->leftTreeWidget->addTopLevelItem(linkItemL); ui->leftTreeWidget->addTopLevelItem(linkItemL);
QTreeWidgetItem *linkNameItemL = new QTreeWidgetItem(); QTreeWidgetItem *linkNameItemL = new QTreeWidgetItem();
@ -63,10 +63,9 @@ void VersionInfoDialog::fillVersionInfo()
QTreeWidgetItem *entriesItemL = new QTreeWidgetItem(); QTreeWidgetItem *entriesItemL = new QTreeWidgetItem();
entriesItemL->setText(0, "Entries:"); entriesItemL->setText(0, "Entries:");
for (QJsonValue val : versym["entries"].toArray()) { for (CutterJson obj : versym["entries"]) {
QJsonObject obj = val.toObject();
QTreeWidgetItem *tempItem = new QTreeWidgetItem(); QTreeWidgetItem *tempItem = new QTreeWidgetItem();
tempItem->setText(0, RzAddressString(obj["idx"].toDouble())); tempItem->setText(0, RzAddressString(obj["idx"].toRVA()));
tempItem->setText(1, obj["value"].toString()); tempItem->setText(1, obj["value"].toString());
entriesItemL->addChild(tempItem); entriesItemL->addChild(tempItem);
} }
@ -83,17 +82,17 @@ void VersionInfoDialog::fillVersionInfo()
QTreeWidgetItem *addrItemR = new QTreeWidgetItem(); QTreeWidgetItem *addrItemR = new QTreeWidgetItem();
addrItemR->setText(0, "Address:"); addrItemR->setText(0, "Address:");
addrItemR->setText(1, RzAddressString(verneed["address"].toDouble())); addrItemR->setText(1, RzAddressString(verneed["address"].toRVA()));
ui->rightTreeWidget->addTopLevelItem(addrItemR); ui->rightTreeWidget->addTopLevelItem(addrItemR);
QTreeWidgetItem *offItemR = new QTreeWidgetItem(); QTreeWidgetItem *offItemR = new QTreeWidgetItem();
offItemR->setText(0, "Offset:"); offItemR->setText(0, "Offset:");
offItemR->setText(1, RzAddressString(verneed["offset"].toDouble())); offItemR->setText(1, RzAddressString(verneed["offset"].toRVA()));
ui->rightTreeWidget->addTopLevelItem(offItemR); ui->rightTreeWidget->addTopLevelItem(offItemR);
QTreeWidgetItem *linkItemR = new QTreeWidgetItem(); QTreeWidgetItem *linkItemR = new QTreeWidgetItem();
linkItemR->setText(0, "Link:"); linkItemR->setText(0, "Link:");
linkItemR->setText(1, QString::number(verneed["link"].toDouble())); linkItemR->setText(1, QString::number(verneed["link"].toSt64()));
ui->rightTreeWidget->addTopLevelItem(linkItemR); ui->rightTreeWidget->addTopLevelItem(linkItemR);
QTreeWidgetItem *linkNameItemR = new QTreeWidgetItem(); QTreeWidgetItem *linkNameItemR = new QTreeWidgetItem();
@ -103,24 +102,22 @@ void VersionInfoDialog::fillVersionInfo()
QTreeWidgetItem *entriesItemR = new QTreeWidgetItem(); QTreeWidgetItem *entriesItemR = new QTreeWidgetItem();
entriesItemR->setText(0, "Entries:"); entriesItemR->setText(0, "Entries:");
for (QJsonValue parentVal : verneed["entries"].toArray()) { for (CutterJson parentObj : verneed["entries"]) {
QJsonObject parentObj = parentVal.toObject();
QTreeWidgetItem *parentItem = new QTreeWidgetItem(); QTreeWidgetItem *parentItem = new QTreeWidgetItem();
QString parentString; QString parentString;
parentItem->setText(0, RzAddressString(parentObj["idx"].toDouble())); parentItem->setText(0, RzAddressString(parentObj["idx"].toRVA()));
parentString.append("Version: " + QString::number(parentObj["vn_version"].toDouble()) parentString.append("Version: " + QString::number(parentObj["vn_version"].toSt64())
+ "\t"); + "\t");
parentString.append("File: " + parentObj["file_name"].toString()); parentString.append("File: " + parentObj["file_name"].toString());
parentItem->setText(1, parentString); parentItem->setText(1, parentString);
for (QJsonValue childVal : parentObj["vernaux"].toArray()) { for (CutterJson childObj : parentObj["vernaux"]) {
QJsonObject childObj = childVal.toObject();
QTreeWidgetItem *childItem = new QTreeWidgetItem(); QTreeWidgetItem *childItem = new QTreeWidgetItem();
QString childString; QString childString;
childItem->setText(0, RzAddressString(childObj["idx"].toDouble())); childItem->setText(0, RzAddressString(childObj["idx"].toRVA()));
childString.append("Name: " + childObj["name"].toString() + "\t"); childString.append("Name: " + childObj["name"].toString() + "\t");
childString.append("Flags: " + childObj["flags"].toString() + "\t"); childString.append("Flags: " + childObj["flags"].toString() + "\t");
childString.append("Version: " + QString::number(childObj["version"].toDouble())); childString.append("Version: " + QString::number(childObj["version"].toSt64()));
childItem->setText(1, childString); childItem->setText(1, childString);
parentItem->addChild(childItem); parentItem->addChild(childItem);
} }
@ -134,22 +131,22 @@ void VersionInfoDialog::fillVersionInfo()
} }
// Case PE // Case PE
else if (doc.object().contains("VS_FIXEDFILEINFO")) { else if (doc["VS_FIXEDFILEINFO"].valid()) {
QJsonObject vs = doc.object()["VS_FIXEDFILEINFO"].toObject(); CutterJson vs = doc["VS_FIXEDFILEINFO"];
QJsonObject strings = doc.object()["StringTable"].toObject(); CutterJson strings = doc["StringTable"];
// Set labels // Set labels
ui->leftLabel->setText("VS Fixed file info"); ui->leftLabel->setText("VS Fixed file info");
ui->rightLabel->setText("String table"); ui->rightLabel->setText("String table");
// Left tree // Left tree
for (QString key : vs.keys()) { for (CutterJson property : vs) {
QTreeWidgetItem *tempItem = new QTreeWidgetItem(); QTreeWidgetItem *tempItem = new QTreeWidgetItem();
tempItem->setText(0, key); tempItem->setText(0, property.key());
if (vs[key].isDouble()) if (property.type() == RZ_JSON_INTEGER)
tempItem->setText(1, RzHexString(vs[key].toDouble())); tempItem->setText(1, RzHexString(property.toRVA()));
else else
tempItem->setText(1, vs[key].toString()); tempItem->setText(1, property.toString());
ui->leftTreeWidget->addTopLevelItem(tempItem); ui->leftTreeWidget->addTopLevelItem(tempItem);
// Adjust columns to content // Adjust columns to content
@ -157,10 +154,10 @@ void VersionInfoDialog::fillVersionInfo()
} }
// Right tree // Right tree
for (QString key : strings.keys()) { for (CutterJson property : strings) {
QTreeWidgetItem *tempItem = new QTreeWidgetItem(); QTreeWidgetItem *tempItem = new QTreeWidgetItem();
tempItem->setText(0, key); tempItem->setText(0, property.key());
tempItem->setText(1, strings[key].toString()); tempItem->setText(1, property.toString());
ui->rightTreeWidget->addTopLevelItem(tempItem); ui->rightTreeWidget->addTopLevelItem(tempItem);
// Adjust columns to content // Adjust columns to content

View File

@ -314,15 +314,15 @@ void DisassemblyContextMenu::addDebugMenu()
QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingUsedHere(RVA offset) QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingUsedHere(RVA offset)
{ {
QVector<ThingUsedHere> result; QVector<ThingUsedHere> result;
const QJsonArray array = Core()->cmdj("anj @ " + QString::number(offset)).array(); const CutterJson array = Core()->cmdj("anj @ " + QString::number(offset));
result.reserve(array.size()); result.reserve(array.size());
for (const auto &thing : array) { for (const auto &thing : array) {
auto obj = thing.toObject(); auto obj = thing;
RVA offset = obj["offset"].toVariant().toULongLong(); RVA offset = obj["offset"].toRVA();
QString name; QString name;
// If real names display is enabled, show flag's real name instead of full flag name // If real names display is enabled, show flag's real name instead of full flag name
if (Config()->getConfigBool("asm.flags.real") && obj.contains("realname")) { if (Config()->getConfigBool("asm.flags.real") && obj["realname"].valid()) {
name = obj["realname"].toString(); name = obj["realname"].toString();
} else { } else {
name = obj["name"].toString(); name = obj["name"].toString();
@ -482,29 +482,24 @@ void DisassemblyContextMenu::setupRenaming()
void DisassemblyContextMenu::aboutToShowSlot() void DisassemblyContextMenu::aboutToShowSlot()
{ {
// check if set immediate base menu makes sense // check if set immediate base menu makes sense
QJsonObject instObject = CutterJson instObject = Core()->cmdj("aoj @ " + QString::number(offset)).first();
Core()->cmdj("aoj @ " + QString::number(offset)).array().first().toObject(); bool immBase = instObject["val"].valid() || instObject["ptr"].valid();
auto keys = instObject.keys();
bool immBase = keys.contains("val") || keys.contains("ptr");
setBaseMenu->menuAction()->setVisible(immBase); setBaseMenu->menuAction()->setVisible(immBase);
setBitsMenu->menuAction()->setVisible(true); setBitsMenu->menuAction()->setVisible(true);
// Create structure offset menu if it makes sense // Create structure offset menu if it makes sense
QString memBaseReg; // Base register QString memBaseReg; // Base register
QVariant memDisp; // Displacement st64 memDisp; // Displacement
if (instObject.contains("opex") && instObject["opex"].toObject().contains("operands")) {
// Loop through both the operands of the instruction
for (const QJsonValue value : instObject["opex"].toObject()["operands"].toArray()) {
QJsonObject operand = value.toObject();
if (operand.contains("type") && operand["type"].toString() == "mem"
&& operand.contains("base") && !operand["base"].toString().contains("bp")
&& operand.contains("disp") && operand["disp"].toVariant().toLongLong() > 0) {
// The current operand is the one which has an immediate displacement // Loop through both the operands of the instruction
memBaseReg = operand["base"].toString(); for (const CutterJson operand : instObject["opex"]["operands"]) {
memDisp = operand["disp"].toVariant(); if (operand["type"].toString() == "mem" && !operand["base"].toString().contains("bp")
break; && operand["disp"].toSt64() > 0) {
}
// The current operand is the one which has an immediate displacement
memBaseReg = operand["base"].toString();
memDisp = operand["disp"].toSt64();
break;
} }
} }
if (memBaseReg.isEmpty()) { if (memBaseReg.isEmpty()) {
@ -517,7 +512,7 @@ void DisassemblyContextMenu::aboutToShowSlot()
// Get the possible offsets using the "ahts" command // Get the possible offsets using the "ahts" command
// TODO: add ahtj command to Rizin and then use it here // TODO: add ahtj command to Rizin and then use it here
QStringList ret = Core()->cmdList("ahts " + memDisp.toString()); QStringList ret = Core()->cmdList("ahts " + QString::number(memDisp));
for (const QString &val : ret) { for (const QString &val : ret) {
if (val.isEmpty()) { if (val.isEmpty()) {
continue; continue;
@ -714,12 +709,12 @@ void DisassemblyContextMenu::showReverseJmpQuery()
{ {
QString type; QString type;
QJsonArray array = Core()->cmdj("pdj 1 @ " + RzAddressString(offset)).array(); CutterJson array = Core()->cmdj("pdj 1 @ " + RzAddressString(offset));
if (array.isEmpty()) { if (!array.size()) {
return; return;
} }
type = array.first().toObject()["type"].toString(); type = array.first()["type"].toString();
if (type == "cjmp") { if (type == "cjmp") {
actionJmpReverse.setVisible(true); actionJmpReverse.setVisible(true);
} else { } else {

View File

@ -44,13 +44,11 @@ void BacktraceWidget::updateContents()
void BacktraceWidget::setBacktraceGrid() void BacktraceWidget::setBacktraceGrid()
{ {
QJsonArray backtraceValues = Core()->getBacktrace().array();
int i = 0; int i = 0;
for (const QJsonValue &value : backtraceValues) { for (CutterJson backtraceItem : Core()->getBacktrace()) {
QJsonObject backtraceItem = value.toObject(); QString progCounter = RzAddressString(backtraceItem["pc"].toRVA());
QString progCounter = RzAddressString(backtraceItem["pc"].toVariant().toULongLong()); QString stackPointer = RzAddressString(backtraceItem["sp"].toRVA());
QString stackPointer = RzAddressString(backtraceItem["sp"].toVariant().toULongLong()); st64 frameSize = backtraceItem["frame_size"].toSt64();
int frameSize = backtraceItem["frame_size"].toVariant().toInt();
QString funcName = backtraceItem["fname"].toString(); QString funcName = backtraceItem["fname"].toString();
QString desc = backtraceItem["desc"].toString(); QString desc = backtraceItem["desc"].toString();

View File

@ -77,8 +77,7 @@ void CallGraphView::loadCurrentGraph()
blockContent.clear(); blockContent.clear();
blocks.clear(); blocks.clear();
QJsonDocument functionsDoc = Core()->cmdj(global ? "agCj" : QString("agcj @ %1").arg(address)); CutterJson nodes = Core()->cmdj(global ? "agCj" : QString("agcj @ %1").arg(address));
auto nodes = functionsDoc.array();
QHash<QString, uint64_t> idMapping; QHash<QString, uint64_t> idMapping;
@ -91,11 +90,10 @@ void CallGraphView::loadCurrentGraph()
return itemId; return itemId;
}; };
for (const QJsonValueRef &value : nodes) { for (CutterJson block : nodes) {
QJsonObject block = value.toObject(); QString name = block["name"].toString();
QString name = block["name"].toVariant().toString();
auto edges = block["imports"].toArray(); auto edges = block["imports"];
GraphLayout::GraphBlock layoutBlock; GraphLayout::GraphBlock layoutBlock;
layoutBlock.entry = getId(name); layoutBlock.entry = getId(name);
for (auto edge : edges) { for (auto edge : edges) {

View File

@ -3,6 +3,7 @@
#include <QTimer> #include <QTimer>
#include <QListView> #include <QListView>
#include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QStyledItemDelegate> #include <QStyledItemDelegate>

View File

@ -32,16 +32,16 @@ Dashboard::~Dashboard() {}
void Dashboard::updateContents() void Dashboard::updateContents()
{ {
QJsonDocument docu = Core()->getFileInfo(); CutterJson docu = Core()->getFileInfo();
QJsonObject item = docu.object()["core"].toObject(); CutterJson item = docu["core"];
QJsonObject item2 = docu.object()["bin"].toObject(); CutterJson item2 = docu["bin"];
setPlainText(this->ui->fileEdit, item["file"].toString()); setPlainText(this->ui->fileEdit, item["file"].toString());
setPlainText(this->ui->formatEdit, item["format"].toString()); setPlainText(this->ui->formatEdit, item["format"].toString());
setPlainText(this->ui->modeEdit, item["mode"].toString()); setPlainText(this->ui->modeEdit, item["mode"].toString());
setPlainText(this->ui->typeEdit, item["type"].toString()); setPlainText(this->ui->typeEdit, item["type"].toString());
setPlainText(this->ui->sizeEdit, qhelpers::formatBytecount(item["size"].toDouble())); setPlainText(this->ui->sizeEdit, qhelpers::formatBytecount(item["size"].toUt64()));
setPlainText(this->ui->fdEdit, QString::number(item["fd"].toDouble())); setPlainText(this->ui->fdEdit, QString::number(item["fd"].toUt64()));
setPlainText(this->ui->archEdit, item2["arch"].toString()); setPlainText(this->ui->archEdit, item2["arch"].toString());
setPlainText(this->ui->langEdit, item2["lang"].toString().toUpper()); setPlainText(this->ui->langEdit, item2["lang"].toString().toUpper());
@ -52,7 +52,7 @@ void Dashboard::updateContents()
setPlainText(this->ui->endianEdit, item2["endian"].toString()); setPlainText(this->ui->endianEdit, item2["endian"].toString());
setPlainText(this->ui->compilationDateEdit, item2["compiled"].toString()); setPlainText(this->ui->compilationDateEdit, item2["compiled"].toString());
setPlainText(this->ui->compilerEdit, item2["compiler"].toString()); setPlainText(this->ui->compilerEdit, item2["compiler"].toString());
setPlainText(this->ui->bitsEdit, QString::number(item2["bits"].toDouble())); setPlainText(this->ui->bitsEdit, QString::number(item2["bits"].toUt64()));
if (!item2["relro"].toString().isEmpty()) { if (!item2["relro"].toString().isEmpty()) {
QString relro = item2["relro"].toString().section(QLatin1Char(' '), 0, 0); QString relro = item2["relro"].toString().section(QLatin1Char(' '), 0, 0);
@ -62,7 +62,7 @@ void Dashboard::updateContents()
setPlainText(this->ui->relroEdit, "N/A"); setPlainText(this->ui->relroEdit, "N/A");
} }
setPlainText(this->ui->baddrEdit, RzAddressString(item2["baddr"].toVariant().toULongLong())); setPlainText(this->ui->baddrEdit, RzAddressString(item2["baddr"].toRVA()));
// set booleans // set booleans
setBool(this->ui->vaEdit, item2, "va"); setBool(this->ui->vaEdit, item2, "va");
@ -110,16 +110,16 @@ void Dashboard::updateContents()
hashesLayout->addRow(new QLabel(label), hashLineEdit); hashesLayout->addRow(new QLabel(label), hashLineEdit);
} }
QJsonObject analinfo = Core()->cmdj("aaij").object(); CutterJson analinfo = Core()->cmdj("aaij");
setPlainText(ui->functionsLineEdit, QString::number(analinfo["fcns"].toInt())); setPlainText(ui->functionsLineEdit, QString::number(analinfo["fcns"].toSt64()));
setPlainText(ui->xRefsLineEdit, QString::number(analinfo["xrefs"].toInt())); setPlainText(ui->xRefsLineEdit, QString::number(analinfo["xrefs"].toSt64()));
setPlainText(ui->callsLineEdit, QString::number(analinfo["calls"].toInt())); setPlainText(ui->callsLineEdit, QString::number(analinfo["calls"].toSt64()));
setPlainText(ui->stringsLineEdit, QString::number(analinfo["strings"].toInt())); setPlainText(ui->stringsLineEdit, QString::number(analinfo["strings"].toSt64()));
setPlainText(ui->symbolsLineEdit, QString::number(analinfo["symbols"].toInt())); setPlainText(ui->symbolsLineEdit, QString::number(analinfo["symbols"].toSt64()));
setPlainText(ui->importsLineEdit, QString::number(analinfo["imports"].toInt())); setPlainText(ui->importsLineEdit, QString::number(analinfo["imports"].toSt64()));
setPlainText(ui->coverageLineEdit, QString::number(analinfo["covrage"].toInt()) + " bytes"); setPlainText(ui->coverageLineEdit, QString::number(analinfo["covrage"].toSt64()) + " bytes");
setPlainText(ui->codeSizeLineEdit, QString::number(analinfo["codesz"].toInt()) + " bytes"); setPlainText(ui->codeSizeLineEdit, QString::number(analinfo["codesz"].toSt64()) + " bytes");
setPlainText(ui->percentageLineEdit, QString::number(analinfo["percent"].toInt()) + "%"); setPlainText(ui->percentageLineEdit, QString::number(analinfo["percent"].toSt64()) + "%");
QStringList libs = Core()->cmdList("il"); QStringList libs = Core()->cmdList("il");
if (!libs.isEmpty()) { if (!libs.isEmpty()) {
@ -155,10 +155,10 @@ void Dashboard::updateContents()
QStringList stats = Core()->getStats(); QStringList stats = Core()->getStats();
// Check if signature info and version info available // Check if signature info and version info available
if (Core()->getSignatureInfo().isEmpty()) { if (!Core()->getSignatureInfo().size()) {
ui->certificateButton->setEnabled(false); ui->certificateButton->setEnabled(false);
} }
if (Core()->getFileVersionInfo().isEmpty()) { if (!Core()->getFileVersionInfo().size()) {
ui->versioninfoButton->setEnabled(false); ui->versioninfoButton->setEnabled(false);
} }
} }
@ -173,8 +173,7 @@ void Dashboard::on_certificateButton_clicked()
viewDialog = new QDialog(this); viewDialog = new QDialog(this);
view = new CutterTreeView(viewDialog); view = new CutterTreeView(viewDialog);
model = new JsonModel(); model = new JsonModel();
QJsonDocument qjsonCertificatesDoc = Core()->getSignatureInfo(); qstrCertificates = Core()->getSignatureInfo().toJson();
qstrCertificates = qjsonCertificatesDoc.toJson(QJsonDocument::Compact);
} }
if (!viewDialog->isVisible()) { if (!viewDialog->isVisible()) {
std::string strCertificates = qstrCertificates.toUtf8().constData(); std::string strCertificates = qstrCertificates.toUtf8().constData();
@ -230,9 +229,9 @@ void Dashboard::setPlainText(QLineEdit *textBox, const QString &text)
* @param textBox * @param textBox
* @param isTrue * @param isTrue
*/ */
void Dashboard::setBool(QLineEdit *textBox, const QJsonObject &jsonObject, const QString &key) void Dashboard::setBool(QLineEdit *textBox, const CutterJson &jsonObject, const char *key)
{ {
if (jsonObject.contains(key)) { if (jsonObject[key].valid()) {
if (jsonObject[key].toBool()) { if (jsonObject[key].toBool()) {
setPlainText(textBox, tr("True")); setPlainText(textBox, tr("True"));
} else { } else {

View File

@ -3,6 +3,7 @@
#include <QFormLayout> #include <QFormLayout>
#include <memory> #include <memory>
#include "core/Cutter.h"
#include "CutterDockWidget.h" #include "CutterDockWidget.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -32,7 +33,7 @@ private slots:
private: private:
std::unique_ptr<Ui::Dashboard> ui; std::unique_ptr<Ui::Dashboard> ui;
void setPlainText(QLineEdit *textBox, const QString &text); void setPlainText(QLineEdit *textBox, const QString &text);
void setBool(QLineEdit *textBox, const QJsonObject &jsonObject, const QString &key); void setBool(QLineEdit *textBox, const CutterJson &jsonObject, const char *key);
QWidget *hashesWidget = nullptr; QWidget *hashesWidget = nullptr;
}; };

View File

@ -182,12 +182,11 @@ void DisassemblerGraphView::loadCurrentGraph()
.set("asm.lines", false) .set("asm.lines", false)
.set("asm.lines.fcn", false); .set("asm.lines.fcn", false);
QJsonArray functions; CutterJson functions;
RzAnalysisFunction *fcn = Core()->functionIn(seekable->getOffset()); RzAnalysisFunction *fcn = Core()->functionIn(seekable->getOffset());
if (fcn) { if (fcn) {
currentFcnAddr = fcn->addr; currentFcnAddr = fcn->addr;
QJsonDocument functionsDoc = Core()->cmdj("agJ " + RzAddressString(fcn->addr)); functions = Core()->cmdj("agJ " + RzAddressString(fcn->addr));
functions = functionsDoc.array();
} }
disassembly_blocks.clear(); disassembly_blocks.clear();
@ -198,7 +197,7 @@ void DisassemblerGraphView::loadCurrentGraph()
highlight_token = nullptr; highlight_token = nullptr;
} }
emptyGraph = functions.isEmpty(); emptyGraph = !functions.size();
if (emptyGraph) { if (emptyGraph) {
// If there's no function to print, just add a message // If there's no function to print, just add a message
if (!emptyText) { if (!emptyText) {
@ -215,8 +214,7 @@ void DisassemblerGraphView::loadCurrentGraph()
// Refresh global "empty graph" variable so other widget know there is nothing to show here // Refresh global "empty graph" variable so other widget know there is nothing to show here
Core()->setGraphEmpty(emptyGraph); Core()->setGraphEmpty(emptyGraph);
QJsonValue funcRef = functions.first(); CutterJson func = functions.first();
QJsonObject func = funcRef.toObject();
windowTitle = tr("Graph"); windowTitle = tr("Graph");
QString funcName = func["name"].toString().trimmed(); QString funcName = func["name"].toString().trimmed();
@ -227,15 +225,14 @@ void DisassemblerGraphView::loadCurrentGraph()
} }
emit nameChanged(windowTitle); emit nameChanged(windowTitle);
RVA entry = func["offset"].toVariant().toULongLong(); RVA entry = func["offset"].toRVA();
setEntry(entry); setEntry(entry);
for (const QJsonValueRef &value : func["blocks"].toArray()) { for (CutterJson block : func["blocks"]) {
QJsonObject block = value.toObject(); RVA block_entry = block["offset"].toRVA();
RVA block_entry = block["offset"].toVariant().toULongLong(); RVA block_size = block["size"].toRVA();
RVA block_size = block["size"].toVariant().toULongLong(); RVA block_fail = block["fail"].toRVA();
RVA block_fail = block["fail"].toVariant().toULongLong(); RVA block_jump = block["jump"].toRVA();
RVA block_jump = block["jump"].toVariant().toULongLong();
DisassemblyBlock db; DisassemblyBlock db;
GraphBlock gb; GraphBlock gb;
@ -259,30 +256,29 @@ void DisassemblerGraphView::loadCurrentGraph()
gb.edges.emplace_back(block_jump); gb.edges.emplace_back(block_jump);
} }
QJsonObject switchOp = block["switchop"].toObject(); CutterJson switchOp = block["switchop"];
if (!switchOp.isEmpty()) { if (switchOp.size()) {
QJsonArray caseArray = switchOp["cases"].toArray(); for (CutterJson caseOp : switchOp["cases"]) {
for (QJsonValue caseOpValue : caseArray) { RVA caseJump = caseOp["jump"].toRVA();
QJsonObject caseOp = caseOpValue.toObject(); if (caseJump == RVA_INVALID) {
bool ok;
RVA caseJump = caseOp["jump"].toVariant().toULongLong(&ok);
if (!ok) {
continue; continue;
} }
gb.edges.emplace_back(caseJump); gb.edges.emplace_back(caseJump);
} }
} }
QJsonArray opArray = block["ops"].toArray(); CutterJson opArray = block["ops"];
for (int opIndex = 0; opIndex < opArray.size(); opIndex++) { CutterJson::iterator iterator = opArray.begin();
QJsonObject op = opArray[opIndex].toObject(); while (iterator != opArray.end()) {
CutterJson op = *iterator;
Instr i; Instr i;
i.addr = op["offset"].toVariant().toULongLong(); i.addr = op["offset"].toUt64();
if (opIndex < opArray.size() - 1) { ++iterator;
if (iterator != opArray.end()) {
// get instruction size from distance to next instruction ... // get instruction size from distance to next instruction ...
RVA nextOffset = RVA nextOffset = (*iterator)["offset"].toRVA();
opArray[opIndex + 1].toObject()["offset"].toVariant().toULongLong();
i.size = nextOffset - i.addr; i.size = nextOffset - i.addr;
} else { } else {
// or to the end of the block. // or to the end of the block.
@ -314,7 +310,7 @@ void DisassemblerGraphView::loadCurrentGraph()
} }
cleanupEdges(blocks); cleanupEdges(blocks);
if (!func["blocks"].toArray().isEmpty()) { if (func["blocks"].size()) {
computeGraphPlacement(); computeGraphPlacement();
} }
} }

View File

@ -562,7 +562,7 @@ void FunctionsWidget::refreshTree()
importAddresses.insert(import.plt); importAddresses.insert(import.plt);
} }
mainAdress = (ut64)Core()->cmdj("iMj").object()["vaddr"].toInt(); mainAdress = (ut64)Core()->cmdj("iMj")["vaddr"].toUt64();
functionModel->updateCurrentIndex(); functionModel->updateCurrentIndex();
functionModel->endResetModel(); functionModel->endResetModel();

View File

@ -106,14 +106,12 @@ QString ProcessesWidget::translateStatus(QString status)
void ProcessesWidget::setProcessesGrid() void ProcessesWidget::setProcessesGrid()
{ {
QJsonArray processesValues = Core()->getChildProcesses(DEBUGGED_PID).array();
int i = 0; int i = 0;
QFont font; QFont font;
for (const QJsonValue &value : processesValues) { for (CutterJson processesItem : Core()->getChildProcesses(DEBUGGED_PID)) {
QJsonObject processesItem = value.toObject(); st64 pid = processesItem["pid"].toSt64();
int pid = processesItem["pid"].toVariant().toInt(); st64 uid = processesItem["uid"].toSt64();
int uid = processesItem["uid"].toVariant().toInt();
QString status = translateStatus(processesItem["status"].toString()); QString status = translateStatus(processesItem["status"].toString());
QString path = processesItem["path"].toString(); QString path = processesItem["path"].toString();
bool current = processesItem["current"].toBool(); bool current = processesItem["current"].toBool();
@ -162,10 +160,9 @@ void ProcessesWidget::onActivated(const QModelIndex &index)
// Verify that the selected pid is still in the processes list since dp= will // Verify that the selected pid is still in the processes list since dp= will
// attach to any given id. If it isn't found simply update the UI. // attach to any given id. If it isn't found simply update the UI.
QJsonArray processesValues = Core()->getChildProcesses(DEBUGGED_PID).array(); for (CutterJson value : Core()->getChildProcesses(DEBUGGED_PID)) {
for (QJsonValue value : processesValues) { QString status = value["status"].toString();
QString status = value.toObject()["status"].toString(); if (pid == value["pid"].toSt64()) {
if (pid == value.toObject()["pid"].toInt()) {
if (QString(QChar(RZ_DBG_PROC_ZOMBIE)) == status if (QString(QChar(RZ_DBG_PROC_ZOMBIE)) == status
|| QString(QChar(RZ_DBG_PROC_DEAD)) == status) { || QString(QChar(RZ_DBG_PROC_DEAD)) == status) {
QMessageBox msgBox; QMessageBox msgBox;

View File

@ -184,14 +184,13 @@ void RegisterRefsWidget::refreshRegisterRef()
registerRefModel->beginResetModel(); registerRefModel->beginResetModel();
QList<QJsonObject> regRefs = Core()->getRegisterRefs();
registerRefs.clear(); registerRefs.clear();
for (const QJsonObject &reg : regRefs) { for (const RegisterRef &reg : Core()->getRegisterRefs()) {
RegisterRefDescription desc; RegisterRefDescription desc;
desc.value = RzAddressString(reg["value"].toVariant().toULongLong()); desc.value = RzAddressString(reg.value);
desc.reg = reg["name"].toVariant().toString(); desc.reg = reg.name;
desc.refDesc = Core()->formatRefDesc(reg["ref"].toObject()); desc.refDesc = Core()->formatRefDesc(reg.ref);
registerRefs.push_back(desc); registerRefs.push_back(desc);
} }

View File

@ -96,12 +96,11 @@ void GenericRizinGraphView::loadCurrentGraph()
return; return;
} }
QJsonDocument functionsDoc = Core()->cmdj(QString("%1j").arg(graphCommand)); CutterJson functionsDoc = Core()->cmdj(QString("%1j").arg(graphCommand));
auto nodes = functionsDoc.object()["nodes"].toArray(); auto nodes = functionsDoc["nodes"];
for (const QJsonValueRef &value : nodes) { for (CutterJson block : nodes) {
QJsonObject block = value.toObject(); uint64_t id = block["id"].toUt64();
uint64_t id = block["id"].toVariant().toULongLong();
QString content; QString content;
QString title = block["title"].toString(); QString title = block["title"].toString();
@ -112,11 +111,11 @@ void GenericRizinGraphView::loadCurrentGraph()
content = title + body; content = title + body;
} }
auto edges = block["out_nodes"].toArray(); auto edges = block["out_nodes"];
GraphLayout::GraphBlock layoutBlock; GraphLayout::GraphBlock layoutBlock;
layoutBlock.entry = id; layoutBlock.entry = id;
for (auto edge : edges) { for (auto edge : edges) {
auto targetId = edge.toVariant().toULongLong(); auto targetId = edge.toUt64();
layoutBlock.edges.emplace_back(targetId); layoutBlock.edges.emplace_back(targetId);
} }

View File

@ -145,16 +145,16 @@ StackModel::StackModel(QObject *parent) : QAbstractTableModel(parent) {}
void StackModel::reload() void StackModel::reload()
{ {
QList<QJsonObject> stackItems = Core()->getStack(); QList<AddrRefs> stackItems = Core()->getStack();
beginResetModel(); beginResetModel();
values.clear(); values.clear();
for (const QJsonObject &stackItem : stackItems) { for (const AddrRefs &stackItem : stackItems) {
Item item; Item item;
item.offset = stackItem["addr"].toVariant().toULongLong(); item.offset = stackItem.addr;
item.value = RzAddressString(stackItem["value"].toVariant().toULongLong()); item.value = RzAddressString(stackItem.value);
item.refDesc = Core()->formatRefDesc(stackItem["ref"].toObject()); item.refDesc = Core()->formatRefDesc(*stackItem.ref);
values.push_back(item); values.push_back(item);
} }

View File

@ -104,13 +104,11 @@ QString ThreadsWidget::translateStatus(QString status)
void ThreadsWidget::setThreadsGrid() void ThreadsWidget::setThreadsGrid()
{ {
QJsonArray threadsValues = Core()->getProcessThreads(DEBUGGED_PID).array();
int i = 0; int i = 0;
QFont font; QFont font;
for (const QJsonValue &value : threadsValues) { for (CutterJson threadsItem : Core()->getProcessThreads(DEBUGGED_PID)) {
QJsonObject threadsItem = value.toObject(); st64 pid = threadsItem["pid"].toSt64();
int pid = threadsItem["pid"].toVariant().toInt();
QString status = translateStatus(threadsItem["status"].toString()); QString status = translateStatus(threadsItem["status"].toString());
QString path = threadsItem["path"].toString(); QString path = threadsItem["path"].toString();
bool current = threadsItem["current"].toBool(); bool current = threadsItem["current"].toBool();
@ -152,9 +150,8 @@ void ThreadsWidget::onActivated(const QModelIndex &index)
// Verify that the selected tid is still in the threads list since dpt= will // Verify that the selected tid is still in the threads list since dpt= will
// attach to any given id. If it isn't found simply update the UI. // attach to any given id. If it isn't found simply update the UI.
QJsonArray threadsValues = Core()->getProcessThreads(DEBUGGED_PID).array(); for (CutterJson value : Core()->getProcessThreads(DEBUGGED_PID)) {
for (QJsonValue value : threadsValues) { if (tid == value["pid"].toSt64()) {
if (tid == value.toObject()["pid"].toInt()) {
Core()->setCurrentDebugThread(tid); Core()->setCurrentDebugThread(tid);
break; break;
} }