diff --git a/src/common/AnalysisTask.cpp b/src/common/AnalysisTask.cpp index 75e90395..dc4a5094 100644 --- a/src/common/AnalysisTask.cpp +++ b/src/common/AnalysisTask.cpp @@ -79,14 +79,14 @@ void AnalysisTask::runTask() if (!options.shellcode.isNull() && options.shellcode.size() / 2 > 0) { log(tr("Loading shellcode...")); - Core()->cmdRaw("wx " + options.shellcode); + rz_core_write_hexpair(core, core->offset, options.shellcode.toStdString().c_str()); } if (options.endian != InitialOptions::Endianness::Auto) { Core()->setEndianness(options.endian == InitialOptions::Endianness::Big); } - Core()->cmdRaw("fs *"); + rz_flag_space_set(core->flags, "*"); if (!options.script.isNull()) { log(tr("Executing script...")); diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 5c9ba1d0..4721ab4f 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -408,7 +408,7 @@ bool CutterCore::isDebugTaskInProgress() return false; } -bool CutterCore::asyncCmdEsil(const char *command, QSharedPointer &task) +bool CutterCore::asyncCmdEsil(const char *command, QSharedPointer &task) { asyncCmd(command, task); @@ -417,7 +417,7 @@ bool CutterCore::asyncCmdEsil(const char *command, QSharedPointer } connect(task.data(), &RizinCmdTask::finished, task.data(), [this, task]() { - QString res = task.data()->getResult(); + QString res = qobject_cast(task.data())->getResult(); if (res.contains(QStringLiteral("[ESIL] Stopped execution in an invalid instruction"))) { msgBox.showMessage("Stopped when attempted to run an invalid instruction. You can " @@ -428,7 +428,7 @@ bool CutterCore::asyncCmdEsil(const char *command, QSharedPointer return true; } -bool CutterCore::asyncCmd(const char *str, QSharedPointer &task) +bool CutterCore::asyncCmd(const char *str, QSharedPointer &task) { if (!task.isNull()) { return false; @@ -438,8 +438,28 @@ bool CutterCore::asyncCmd(const char *str, QSharedPointer &task) RVA offset = core->offset; - task = QSharedPointer(new RizinCmdTask(str, true)); - connect(task.data(), &RizinCmdTask::finished, task.data(), [this, offset, task]() { + task = QSharedPointer(new RizinCmdTask(str, true)); + connect(task.data(), &RizinTask::finished, task.data(), [this, offset, task]() { + CORE_LOCK(); + + if (offset != core->offset) { + updateSeek(); + } + }); + + return true; +} + +bool CutterCore::asyncTask(std::function fcn, QSharedPointer &task) +{ + if (!task.isNull()) { + return false; + } + + CORE_LOCK(); + RVA offset = core->offset; + task = QSharedPointer(new RizinFunctionTask(std::move(fcn), true)); + connect(task.data(), &RizinTask::finished, task.data(), [this, offset, task]() { CORE_LOCK(); if (offset != core->offset) { @@ -819,12 +839,23 @@ void CutterCore::removeString(RVA addr) QString CutterCore::getString(RVA addr) { - return cmdRawAt("ps", addr); + CORE_LOCK(); + char *s = (char *)returnAtSeek( + [&]() { + RzStrStringifyOpt opt = { 0 }; + opt.buffer = core->block; + opt.length = core->blocksize; + opt.encoding = rz_str_guess_encoding_from_buffer(core->block, core->blocksize); + return rz_str_stringify_raw_buffer(&opt, NULL); + }, + addr); + return fromOwnedCharPtr(s); } QString CutterCore::getMetaString(RVA addr) { - return cmdRawAt("Cs.", addr); + CORE_LOCK(); + return rz_meta_get_string(core->analysis, RZ_META_TYPE_STRING, addr); } void CutterCore::setToData(RVA addr, int size, int repeat) @@ -1595,16 +1626,6 @@ AddrRefs CutterCore::getAddrRefs(RVA addr, int depth) return refs; } -CutterJson CutterCore::getProcessThreads(int pid) -{ - if (-1 == pid) { - // Return threads list of the currently debugged PID - return cmdj("dptj"); - } else { - return cmdj("dptj " + QString::number(pid)); - } -} - QVector CutterCore::getHeapChunks(RVA arena_addr) { CORE_LOCK(); @@ -1735,16 +1756,6 @@ bool CutterCore::writeHeapChunk(RzHeapChunkSimple *chunk_simple) return rz_heap_write_chunk(core, chunk_simple); } -CutterJson CutterCore::getChildProcesses(int pid) -{ - // Return the currently debugged process and it's children - if (-1 == pid) { - return cmdj("dpj"); - } - // Return the given pid and it's child processes - return cmdj("dpj " + QString::number(pid)); -} - CutterJson CutterCore::getRegisterValues() { return cmdj("drj"); @@ -1831,7 +1842,12 @@ void CutterCore::setRegister(QString regName, QString regValue) void CutterCore::setCurrentDebugThread(int tid) { - if (!asyncCmd("dpt=" + QString::number(tid), debugTask)) { + if (!asyncTask( + [=](RzCore *core) { + rz_debug_select(core->dbg, core->dbg->pid, tid); + return (void *)NULL; + }, + debugTask)) { return; } @@ -1851,7 +1867,14 @@ void CutterCore::setCurrentDebugThread(int tid) void CutterCore::setCurrentDebugProcess(int pid) { - if (!currentlyDebugging || !asyncCmd("dp=" + QString::number(pid), debugTask)) { + if (!currentlyDebugging + || !asyncTask( + [=](RzCore *core) { + rz_debug_select(core->dbg, pid, core->dbg->tid); + core->dbg->main_pid = pid; + return (void *)NULL; + }, + debugTask)) { return; } @@ -1877,7 +1900,12 @@ void CutterCore::startDebug() } currentlyOpenFile = getConfig("file.path"); - if (!asyncCmd("ood", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_file_reopen_debug(core, ""); + return (void *)NULL; + }, + debugTask)) { return; } @@ -1961,7 +1989,15 @@ void CutterCore::attachRemote(const QString &uri) } // connect to a debugger with the given plugin - asyncCmd("e cfg.debug=true; oodf " + uri, debugTask); + if (!asyncTask( + [&](RzCore *core) { + setConfig("cfg.debug", true); + rz_core_file_reopen_remote_debug(core, uri.toStdString().c_str(), 0); + return (void *)NULL; + }, + debugTask)) { + return; + } emit debugTaskStateChanged(); connect(debugTask.data(), &RizinTask::finished, this, [this, uri]() { @@ -2124,7 +2160,12 @@ void CutterCore::continueDebug() return; } } else { - if (!asyncCmd("dc", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_debug_continue(core->dbg); + return (void *)NULL; + }, + debugTask)) { return; } } @@ -2151,7 +2192,12 @@ void CutterCore::continueBackDebug() return; } } else { - if (!asyncCmd("dcb", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_debug_continue_back(core->dbg); + return (void *)NULL; + }, + debugTask)) { return; } } @@ -2167,22 +2213,26 @@ void CutterCore::continueBackDebug() debugTask->startTask(); } -void CutterCore::continueUntilDebug(QString offset) +void CutterCore::continueUntilDebug(ut64 offset) { if (!currentlyDebugging) { return; } if (currentlyEmulating) { - if (!asyncCmdEsil("aecu " + offset, debugTask)) { + if (!asyncCmdEsil("aecu " + QString::number(offset), debugTask)) { return; } } else { - if (!asyncCmd("dcu " + offset, debugTask)) { + if (!asyncTask( + [=](RzCore *core) { + rz_core_debug_continue_until(core, offset, offset); + return (void *)NULL; + }, + debugTask)) { return; } } - emit debugTaskStateChanged(); connect(debugTask.data(), &RizinTask::finished, this, [this]() { debugTask.clear(); @@ -2190,7 +2240,6 @@ void CutterCore::continueUntilDebug(QString offset) emit refreshCodeViews(); emit debugTaskStateChanged(); }); - debugTask->startTask(); } @@ -2205,7 +2254,12 @@ void CutterCore::continueUntilCall() return; } } else { - if (!asyncCmd("dcc", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_debug_step_one(core, 0); + return (void *)NULL; + }, + debugTask)) { return; } } @@ -2259,7 +2313,12 @@ void CutterCore::stepDebug() return; } } else { - if (!asyncCmd("ds", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_debug_step_one(core, 1); + return (void *)NULL; + }, + debugTask)) { return; } } @@ -2383,7 +2442,13 @@ void CutterCore::startTraceSession() return; } } else { - if (!asyncCmd("dts+", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + core->dbg->session = rz_debug_session_new(); + rz_debug_add_checkpoint(core->dbg); + return (void *)NULL; + }, + debugTask)) { return; } } @@ -2419,7 +2484,13 @@ void CutterCore::stopTraceSession() return; } } else { - if (!asyncCmd("dts-", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_debug_session_free(core->dbg->session); + core->dbg->session = NULL; + return (void *)NULL; + }, + debugTask)) { return; } } @@ -2517,25 +2588,29 @@ void CutterCore::updateBreakpoint(int index, const BreakpointDescription &config void CutterCore::delBreakpoint(RVA addr) { - cmdRaw("db- " + RzAddressString(addr)); + CORE_LOCK(); + rz_bp_del(core->dbg->bp, addr); emit breakpointsChanged(addr); } void CutterCore::delAllBreakpoints() { - cmdRaw("db-*"); + CORE_LOCK(); + rz_bp_del_all(core->dbg->bp); emit refreshCodeViews(); } void CutterCore::enableBreakpoint(RVA addr) { - cmdRaw("dbe " + RzAddressString(addr)); + CORE_LOCK(); + rz_bp_enable(core->dbg->bp, addr, true, 1); emit breakpointsChanged(addr); } void CutterCore::disableBreakpoint(RVA addr) { - cmdRaw("dbd " + RzAddressString(addr)); + CORE_LOCK(); + rz_bp_enable(core->dbg->bp, addr, false, 1); emit breakpointsChanged(addr); } @@ -2631,37 +2706,53 @@ CutterJson CutterCore::getBacktrace() return cmdj("dbtj"); } -QList CutterCore::getAllProcesses() +QList CutterCore::getProcessThreads(int pid = -1) { + CORE_LOCK(); + RzList *list = rz_debug_pids(core->dbg, pid != -1 ? pid : core->dbg->pid); + RzListIter *iter; + RzDebugPid *p; QList ret; - for (CutterJson procObject : cmdj("dplj")) { + CutterRzListForeach (list, iter, RzDebugPid, p) { ProcessDescription proc; - proc.pid = procObject[RJsonKey::pid].toSt64(); - proc.uid = procObject[RJsonKey::uid].toSt64(); - proc.status = procObject[RJsonKey::status].toString(); - proc.path = procObject[RJsonKey::path].toString(); + proc.current = core->dbg->pid == p->pid; + proc.ppid = p->ppid; + proc.pid = p->pid; + proc.uid = p->uid; + proc.status = static_cast(p->status); + proc.path = p->path; ret << proc; } - + rz_list_free(list); return ret; } +QList CutterCore::getAllProcesses() +{ + return getProcessThreads(0); +} + QList CutterCore::getMemoryMap() { + CORE_LOCK(); + RzList *list0 = rz_debug_map_list(core->dbg, false); + RzList *list1 = rz_debug_map_list(core->dbg, true); + rz_list_join(list0, list1); QList ret; - - for (CutterJson memMapObject : cmdj("dmj")) { + RzListIter *it; + RzDebugMap *map; + CutterRzListForeach (list0, it, RzDebugMap, map) { MemoryMapDescription memMap; - memMap.name = memMapObject[RJsonKey::name].toString(); - memMap.fileName = memMapObject[RJsonKey::file].toString(); - memMap.addrStart = memMapObject[RJsonKey::addr].toRVA(); - memMap.addrEnd = memMapObject[RJsonKey::addr_end].toRVA(); - memMap.type = memMapObject[RJsonKey::type].toString(); - memMap.permission = memMapObject[RJsonKey::perm].toString(); + memMap.name = map->name; + memMap.fileName = map->file; + memMap.addrStart = map->addr; + memMap.addrEnd = map->addr_end; + memMap.type = map->user ? "u" : "s"; + memMap.permission = rz_str_rwx_i(map->perm); ret << memMap; } diff --git a/src/core/Cutter.h b/src/core/Cutter.h index 249da7ce..4013f39e 100644 --- a/src/core/Cutter.h +++ b/src/core/Cutter.h @@ -24,6 +24,7 @@ class CutterCore; class Decompiler; class RizinTask; class RizinCmdTask; +class RizinFunctionTask; class RizinTaskDialog; #include "common/BasicBlockHighlighter.h" @@ -99,12 +100,19 @@ public: * Once you have setup connections you can start the task with task->startTask() * If you want to seek to an address, you should use CutterCore::seek. */ - bool asyncCmd(const char *str, QSharedPointer &task); - bool asyncCmd(const QString &str, QSharedPointer &task) + bool asyncCmd(const char *str, QSharedPointer &task); + bool asyncCmd(const QString &str, QSharedPointer &task) { return asyncCmd(str.toUtf8().constData(), task); } + /** + * @brief send a task to Rizin + * @param fcn the task you want to execute + * @return execute successful? + */ + bool asyncTask(std::function fcn, QSharedPointer &task); + /** * @brief Execute a Rizin command \a cmd. By nature, the API * is executing raw commands, and thus ignores multiple commands and overcome command @@ -148,6 +156,15 @@ public: seekSilent(oldOffset); } + void *returnAtSeek(std::function fn, RVA address) + { + RVA oldOffset = getOffset(); + seekSilent(address); + void *ret = fn(); + seekSilent(oldOffset); + return ret; + } + CutterJson cmdj(const char *str); CutterJson cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); } CutterJson cmdjAt(const char *str, RVA address); @@ -175,8 +192,8 @@ public: * Once you have setup connections you can start the task with task->startTask() * If you want to seek to an address, you should use CutterCore::seek. */ - bool asyncCmdEsil(const char *command, QSharedPointer &task); - bool asyncCmdEsil(const QString &command, QSharedPointer &task) + bool asyncCmdEsil(const char *command, QSharedPointer &task); + bool asyncCmdEsil(const QString &command, QSharedPointer &task) { return asyncCmdEsil(command.toUtf8().constData(), task); } @@ -431,15 +448,9 @@ public: /** * @brief Get a list of a given process's threads * @param pid The pid of the process, -1 for the currently debugged process - * @return JSON object result of dptj + * @return List of ProcessDescription */ - CutterJson getProcessThreads(int pid); - /** - * @brief Get a list of a given process's child processes - * @param pid The pid of the process, -1 for the currently debugged process - * @return JSON object result of dptj - */ - CutterJson getChildProcesses(int pid); + QList getProcessThreads(int pid); CutterJson getBacktrace(); /** * @brief Get a list of heap chunks @@ -493,7 +504,7 @@ public: void continueBackDebug(); void continueUntilCall(); void continueUntilSyscall(); - void continueUntilDebug(QString offset); + void continueUntilDebug(ut64 offset); void stepDebug(); void stepOverDebug(); void stepOutDebug(); @@ -814,7 +825,7 @@ private: bool iocache = false; BasicInstructionHighlighter biHighlighter; - QSharedPointer debugTask; + QSharedPointer debugTask; RizinTaskDialog *debugTaskDialog; QVector getCutterRCFilePaths() const; diff --git a/src/core/CutterDescriptions.h b/src/core/CutterDescriptions.h index e28894ee..a56f7186 100644 --- a/src/core/CutterDescriptions.h +++ b/src/core/CutterDescriptions.h @@ -339,9 +339,11 @@ struct BreakpointDescription struct ProcessDescription { + bool current; int pid; int uid; - QString status; + int ppid; + RzDebugPidState status; QString path; }; diff --git a/src/dialogs/EditVariablesDialog.cpp b/src/dialogs/EditVariablesDialog.cpp index 6954814a..1f2139ef 100644 --- a/src/dialogs/EditVariablesDialog.cpp +++ b/src/dialogs/EditVariablesDialog.cpp @@ -14,7 +14,8 @@ EditVariablesDialog::EditVariablesDialog(RVA offset, QString initialVar, QWidget connect(ui->dropdownLocalVars, &QComboBox::currentIndexChanged, this, &EditVariablesDialog::updateFields); - QString fcnName = Core()->cmdRawAt("afn.", offset).trimmed(); + RzAnalysisFunction *f = rz_analysis_get_function_at(Core()->core()->analysis, offset); + QString fcnName = f->name; functionAddress = offset; setWindowTitle(tr("Edit Variables in Function: %1").arg(fcnName)); diff --git a/src/menus/DecompilerContextMenu.cpp b/src/menus/DecompilerContextMenu.cpp index d36cf0b7..7113ec68 100644 --- a/src/menus/DecompilerContextMenu.cpp +++ b/src/menus/DecompilerContextMenu.cpp @@ -519,7 +519,7 @@ void DecompilerContextMenu::actionAdvancedBreakpointTriggered() void DecompilerContextMenu::actionContinueUntilTriggered() { - Core()->continueUntilDebug(RzAddressString(offset)); + Core()->continueUntilDebug(offset); } void DecompilerContextMenu::actionSetPCTriggered() diff --git a/src/menus/DisassemblyContextMenu.cpp b/src/menus/DisassemblyContextMenu.cpp index 15e23f8c..f39bbd79 100644 --- a/src/menus/DisassemblyContextMenu.cpp +++ b/src/menus/DisassemblyContextMenu.cpp @@ -777,7 +777,7 @@ void DisassemblyContextMenu::on_actionAdvancedBreakpoint_triggered() void DisassemblyContextMenu::on_actionContinueUntil_triggered() { - Core()->continueUntilDebug(RzAddressString(offset)); + Core()->continueUntilDebug(offset); } void DisassemblyContextMenu::on_actionSetPC_triggered() diff --git a/src/widgets/DebugActions.cpp b/src/widgets/DebugActions.cpp index 3ed1b877..68d0362c 100644 --- a/src/widgets/DebugActions.cpp +++ b/src/widgets/DebugActions.cpp @@ -281,7 +281,7 @@ void DebugActions::continueUntilMain() return; } } - Core()->continueUntilDebug(QString::number(main_flag->offset)); + Core()->continueUntilDebug(main_flag->offset); } void DebugActions::attachRemoteDebugger() diff --git a/src/widgets/ProcessesWidget.cpp b/src/widgets/ProcessesWidget.cpp index b8e12435..2a9477f8 100644 --- a/src/widgets/ProcessesWidget.cpp +++ b/src/widgets/ProcessesWidget.cpp @@ -84,9 +84,9 @@ void ProcessesWidget::updateContents() } } -QString ProcessesWidget::translateStatus(QString status) +QString ProcessesWidget::translateStatus(const char status) { - switch (status.toStdString().c_str()[0]) { + switch (status) { case RZ_DBG_PROC_STOP: return "Stopped"; case RZ_DBG_PROC_RUN: @@ -109,12 +109,12 @@ void ProcessesWidget::setProcessesGrid() int i = 0; QFont font; - for (CutterJson processesItem : Core()->getChildProcesses(DEBUGGED_PID)) { - st64 pid = processesItem["pid"].toSt64(); - st64 uid = processesItem["uid"].toSt64(); - QString status = translateStatus(processesItem["status"].toString()); - QString path = processesItem["path"].toString(); - bool current = processesItem["current"].toBool(); + for (const auto &processesItem : Core()->getProcessThreads(DEBUGGED_PID)) { + st64 pid = processesItem.pid; + st64 uid = processesItem.uid; + QString status = translateStatus(processesItem.status); + QString path = processesItem.path; + bool current = processesItem.current; // Use bold font to highlight active thread font.setBold(current); @@ -143,7 +143,6 @@ void ProcessesWidget::setProcessesGrid() modelFilter->setSourceModel(modelProcesses); ui->viewProcesses->resizeColumnsToContents(); - ; } void ProcessesWidget::fontsUpdatedSlot() @@ -157,24 +156,23 @@ void ProcessesWidget::onActivated(const QModelIndex &index) return; int pid = modelFilter->data(index.sibling(index.row(), COLUMN_PID)).toInt(); - // 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. - for (CutterJson value : Core()->getChildProcesses(DEBUGGED_PID)) { - QString status = value["status"].toString(); - if (pid == value["pid"].toSt64()) { - if (QString(QChar(RZ_DBG_PROC_ZOMBIE)) == status - || QString(QChar(RZ_DBG_PROC_DEAD)) == status) { - QMessageBox msgBox; + for (const auto &value : Core()->getAllProcesses()) { + if (pid == value.pid) { + QMessageBox msgBox; + switch (value.status) { + case RZ_DBG_PROC_ZOMBIE: + case RZ_DBG_PROC_DEAD: msgBox.setText(tr("Unable to switch to the requested process.")); msgBox.exec(); - } else { + break; + default: Core()->setCurrentDebugProcess(pid); + break; } - break; } } - updateContents(); } diff --git a/src/widgets/ProcessesWidget.h b/src/widgets/ProcessesWidget.h index 80e89007..fcc9db80 100644 --- a/src/widgets/ProcessesWidget.h +++ b/src/widgets/ProcessesWidget.h @@ -41,7 +41,7 @@ private slots: void onActivated(const QModelIndex &index); private: - QString translateStatus(QString status); + QString translateStatus(const char status); std::unique_ptr ui; QStandardItemModel *modelProcesses; ProcessesFilterModel *modelFilter; diff --git a/src/widgets/ThreadsWidget.cpp b/src/widgets/ThreadsWidget.cpp index 6cdde089..d9149108 100644 --- a/src/widgets/ThreadsWidget.cpp +++ b/src/widgets/ThreadsWidget.cpp @@ -82,9 +82,9 @@ void ThreadsWidget::updateContents() } } -QString ThreadsWidget::translateStatus(QString status) +QString ThreadsWidget::translateStatus(const char status) { - switch (status.toStdString().c_str()[0]) { + switch (status) { case RZ_DBG_PROC_STOP: return "Stopped"; case RZ_DBG_PROC_RUN: @@ -107,11 +107,11 @@ void ThreadsWidget::setThreadsGrid() int i = 0; QFont font; - for (CutterJson threadsItem : Core()->getProcessThreads(DEBUGGED_PID)) { - st64 pid = threadsItem["pid"].toSt64(); - QString status = translateStatus(threadsItem["status"].toString()); - QString path = threadsItem["path"].toString(); - bool current = threadsItem["current"].toBool(); + for (const auto &threadsItem : Core()->getProcessThreads(DEBUGGED_PID)) { + st64 pid = threadsItem.pid; + QString status = translateStatus(threadsItem.status); + QString path = threadsItem.path; + bool current = threadsItem.current; // Use bold font to highlight active thread font.setBold(current); QStandardItem *rowPid = new QStandardItem(QString::number(pid)); @@ -150,8 +150,8 @@ void ThreadsWidget::onActivated(const QModelIndex &index) // 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. - for (CutterJson value : Core()->getProcessThreads(DEBUGGED_PID)) { - if (tid == value["pid"].toSt64()) { + for (const auto &value : Core()->getProcessThreads(DEBUGGED_PID)) { + if (tid == value.pid) { Core()->setCurrentDebugThread(tid); break; } diff --git a/src/widgets/ThreadsWidget.h b/src/widgets/ThreadsWidget.h index 8d9c6a0e..259c919d 100644 --- a/src/widgets/ThreadsWidget.h +++ b/src/widgets/ThreadsWidget.h @@ -41,7 +41,7 @@ private slots: void onActivated(const QModelIndex &index); private: - QString translateStatus(QString status); + QString translateStatus(const char status); std::unique_ptr ui; QStandardItemModel *modelThreads; ThreadsFilterModel *modelFilter;