From 150769cd6b383da6061c7406cdc983daa24cab85 Mon Sep 17 00:00:00 2001 From: billow Date: Sat, 28 May 2022 16:09:00 +0800 Subject: [PATCH] Convert Rizin commands to the API calls (#2948) Including wx wr wd ws ww wz ahi ahb aec aecu aecc aecs aes aesb aets+ aets- afc afcl omfg+w oo+ oo p8 aei aeim aeip aecb aeso dbs avj --- rizin | 2 +- src/core/Cutter.cpp | 194 ++++++++++++++++++--------- src/dialogs/WriteCommandsDialogs.cpp | 10 +- src/menus/DisassemblyContextMenu.cpp | 24 +++- src/widgets/HexWidget.cpp | 156 ++++++++++++--------- 5 files changed, 247 insertions(+), 139 deletions(-) diff --git a/rizin b/rizin index f2a1e5e0..24524f26 160000 --- a/rizin +++ b/rizin @@ -1 +1 @@ -Subproject commit f2a1e5e09087550e70122c3a2bedd4e2a02f77f1 +Subproject commit 24524f26b5e4db58a736f702a77e79245148c559 diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index 3858b88b..40cd43ff 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -656,7 +656,10 @@ bool CutterCore::loadFile(QString path, ut64 baddr, ut64 mapaddr, int perms, int } if (perms & RZ_PERM_W) { - rz_core_cmd0(core, "omfg+w"); + RzPVector *maps = rz_io_maps(core->io); + for (auto map : CutterPVector(maps)) { + map->perm |= RZ_PERM_W; + } } fflush(stdout); @@ -802,7 +805,8 @@ void CutterCore::jmpReverse(RVA addr) void CutterCore::editBytes(RVA addr, const QString &bytes) { - cmdRawAt(QString("wx %1").arg(bytes), addr); + CORE_LOCK(); + rz_core_write_hexpair(core, addr, bytes.toUtf8().constData()); emit instructionChanged(addr); } @@ -935,8 +939,9 @@ void CutterCore::setImmediateBase(const QString &rzBaseName, RVA offset) if (offset == RVA_INVALID) { offset = getOffset(); } - - this->cmdRawAt(QString("ahi %1").arg(rzBaseName), offset); + CORE_LOCK(); + int base = (int)rz_num_base_of_string(core->num, rzBaseName.toUtf8().constData()); + rz_analysis_hint_set_immbase(core->analysis, offset, base); emit instructionChanged(offset); } @@ -946,7 +951,8 @@ void CutterCore::setCurrentBits(int bits, RVA offset) offset = getOffset(); } - this->cmdRawAt(QString("ahb %1").arg(bits), offset); + CORE_LOCK(); + rz_analysis_hint_set_bits(core->analysis, offset, bits); emit instructionChanged(offset); } @@ -1950,7 +1956,7 @@ void CutterCore::startDebug() if (!asyncTask( [](RzCore *core) { rz_core_file_reopen_debug(core, ""); - return (void *)nullptr; + return nullptr; }, debugTask)) { return; @@ -1991,14 +1997,19 @@ void CutterCore::startEmulation() } // clear registers, init esil state, stack, progcounter at current seek - asyncCmd("aei; aeim; aeip", debugTask); + asyncTask( + [&](RzCore *core) { + rz_core_analysis_esil_reinit(core); + rz_core_analysis_esil_init_mem(core, NULL, UT64_MAX, UT32_MAX); + rz_core_analysis_esil_init_regs(core); + return nullptr; + }, + debugTask); emit debugTaskStateChanged(); connect(debugTask.data(), &RizinTask::finished, this, [this]() { - if (debugTaskDialog) { - delete debugTaskDialog; - } + delete debugTaskDialog; debugTask.clear(); if (!currentlyDebugging || !currentlyEmulating) { @@ -2105,9 +2116,7 @@ void CutterCore::attachDebug(int pid) emit debugTaskStateChanged(); connect(debugTask.data(), &RizinTask::finished, this, [this, pid]() { - if (debugTaskDialog) { - delete debugTaskDialog; - } + delete debugTaskDialog; debugTask.clear(); syncAndSeekProgramCounter(); @@ -2184,14 +2193,20 @@ void CutterCore::continueDebug() } if (currentlyEmulating) { - if (!asyncCmdEsil("aec", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_esil_step(core, UT64_MAX, "0", NULL, false); + rz_core_reg_update_flags(core); + return nullptr; + }, + debugTask)) { return; } } else { if (!asyncTask( [](RzCore *core) { rz_debug_continue(core->dbg); - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2216,14 +2231,20 @@ void CutterCore::continueBackDebug() } if (currentlyEmulating) { - if (!asyncCmdEsil("aecb", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_esil_continue_back(core); + rz_core_reg_update_flags(core); + return nullptr; + }, + debugTask)) { return; } } else { if (!asyncTask( [](RzCore *core) { rz_debug_continue_back(core->dbg); - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2248,14 +2269,20 @@ void CutterCore::continueUntilDebug(ut64 offset) } if (currentlyEmulating) { - if (!asyncCmdEsil("aecu " + QString::number(offset), debugTask)) { + if (!asyncTask( + [=](RzCore *core) { + rz_core_esil_step(core, offset, NULL, NULL, false); + rz_core_reg_update_flags(core); + return nullptr; + }, + debugTask)) { return; } } else { if (!asyncTask( [=](RzCore *core) { rz_core_debug_continue_until(core, offset, offset); - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2278,14 +2305,19 @@ void CutterCore::continueUntilCall() } if (currentlyEmulating) { - if (!asyncCmdEsil("aecc", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_analysis_continue_until_call(core); + return nullptr; + }, + debugTask)) { return; } } else { if (!asyncTask( [](RzCore *core) { rz_core_debug_step_one(core, 0); - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2310,7 +2342,12 @@ void CutterCore::continueUntilSyscall() } if (currentlyEmulating) { - if (!asyncCmdEsil("aecs", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_analysis_continue_until_syscall(core); + return nullptr; + }, + debugTask)) { return; } } else { @@ -2346,14 +2383,20 @@ void CutterCore::stepDebug() } if (currentlyEmulating) { - if (!asyncCmdEsil("aes", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_esil_step(core, UT64_MAX, NULL, NULL, false); + rz_core_reg_update_flags(core); + return nullptr; + }, + debugTask)) { return; } } else { if (!asyncTask( [](RzCore *core) { rz_core_debug_step_one(core, 1); - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2378,7 +2421,12 @@ void CutterCore::stepOverDebug() } if (currentlyEmulating) { - if (!asyncCmdEsil("aeso", debugTask)) { + if (!asyncTask( + [&](RzCore *core) { + rz_core_analysis_esil_step_over(core); + return nullptr; + }, + debugTask)) { return; } } else { @@ -2442,7 +2490,13 @@ void CutterCore::stepBackDebug() } if (currentlyEmulating) { - if (!asyncCmdEsil("aesb", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_esil_step_back(core); + rz_core_reg_update_flags(core); + return nullptr; + }, + debugTask)) { return; } } else { @@ -2499,7 +2553,12 @@ void CutterCore::startTraceSession() } if (currentlyEmulating) { - if (!asyncCmdEsil("aets+", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_analysis_esil_trace_start(core); + return nullptr; + }, + debugTask)) { return; } } else { @@ -2507,7 +2566,7 @@ void CutterCore::startTraceSession() [](RzCore *core) { core->dbg->session = rz_debug_session_new(); rz_debug_add_checkpoint(core->dbg); - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2516,9 +2575,7 @@ void CutterCore::startTraceSession() emit debugTaskStateChanged(); connect(debugTask.data(), &RizinTask::finished, this, [this]() { - if (debugTaskDialog) { - delete debugTaskDialog; - } + delete debugTaskDialog; debugTask.clear(); currentlyTracing = true; @@ -2541,7 +2598,12 @@ void CutterCore::stopTraceSession() } if (currentlyEmulating) { - if (!asyncCmdEsil("aets-", debugTask)) { + if (!asyncTask( + [](RzCore *core) { + rz_core_analysis_esil_trace_stop(core); + return nullptr; + }, + debugTask)) { return; } } else { @@ -2549,7 +2611,7 @@ void CutterCore::stopTraceSession() [](RzCore *core) { rz_debug_session_free(core->dbg->session); core->dbg->session = NULL; - return (void *)NULL; + return nullptr; }, debugTask)) { return; @@ -2558,9 +2620,7 @@ void CutterCore::stopTraceSession() emit debugTaskStateChanged(); connect(debugTask.data(), &RizinTask::finished, this, [this]() { - if (debugTaskDialog) { - delete debugTaskDialog; - } + delete debugTaskDialog; debugTask.clear(); currentlyTracing = false; @@ -2578,7 +2638,8 @@ void CutterCore::stopTraceSession() void CutterCore::toggleBreakpoint(RVA addr) { - cmdRaw(QString("dbs %1").arg(addr)); + CORE_LOCK(); + rz_core_debug_breakpoint_toggle(core, addr); emit breakpointsChanged(addr); } @@ -3649,25 +3710,29 @@ QList CutterCore::getAllResources() QList CutterCore::getAllVTables() { CORE_LOCK(); - QList vtables; - - for (CutterJson vTableObject : cmdj("avj")) { - VTableDescription res; - - res.addr = vTableObject[RJsonKey::offset].toRVA(); - - for (CutterJson methodObject : vTableObject[RJsonKey::methods]) { - BinClassMethodDescription method; - - method.addr = methodObject[RJsonKey::offset].toRVA(); - method.name = methodObject[RJsonKey::name].toString(); - - res.methods << method; + QList vtableDescs; + RVTableContext context; + rz_analysis_vtable_begin(core->analysis, &context); + RzList *vtables = rz_analysis_vtable_search(&context); + RzListIter *iter; + RVTableInfo *table; + RVTableMethodInfo *method; + CutterRzListForeach (vtables, iter, RVTableInfo, table) { + VTableDescription tableDesc; + tableDesc.addr = table->saddr; + CutterRzVectorForeach(&table->methods, method, RVTableMethodInfo) + { + BinClassMethodDescription methodDesc; + RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, method->addr, 0); + const char *fname = fcn ? fcn->name : nullptr; + methodDesc.addr = method->addr; + methodDesc.name = fname ? fname : "No Name found"; + tableDesc.methods << methodDesc; } - - vtables << res; + vtableDescs << tableDesc; } - return vtables; + rz_list_free(vtables); + return vtableDescs; } QList CutterCore::getAllTypes() @@ -4226,10 +4291,10 @@ void CutterCore::commitWriteCache() TempConfig tempConfig; tempConfig.set("io.cache", false); if (!isWriteModeEnabled()) { - cmdRaw("oo+"); + rz_core_io_file_reopen(core, core->io->desc->fd, RZ_PERM_RW); rz_io_cache_commit(core->io, 0, UT64_MAX); rz_core_block_read(core); - cmdRaw("oo"); + rz_core_io_file_open(core, core->io->desc->fd); } else { rz_io_cache_commit(core->io, 0, UT64_MAX); rz_core_block_read(core); @@ -4252,17 +4317,22 @@ void CutterCore::setWriteMode(bool enabled) return; } + CORE_LOCK(); // Change from read-only to write-mode - if (enabled && !writeModeState) { - cmdRaw("oo+"); - // Change from write-mode to read-only + if (enabled) { + if (!writeModeState) { + rz_core_io_file_reopen(core, core->io->desc->fd, RZ_PERM_RW); + } } else { - cmdRaw("oo"); + // Change from write-mode to read-only + rz_core_io_file_open(core, core->io->desc->fd); } // Disable cache mode because we specifically set write or // read-only modes. - setIOCache(false); - writeModeChanged(enabled); + if (this->iocache) { + setIOCache(false); + } + emit writeModeChanged(enabled); emit ioModeChanged(); } diff --git a/src/dialogs/WriteCommandsDialogs.cpp b/src/dialogs/WriteCommandsDialogs.cpp index 5826a9ae..9cd509a3 100644 --- a/src/dialogs/WriteCommandsDialogs.cpp +++ b/src/dialogs/WriteCommandsDialogs.cpp @@ -77,14 +77,12 @@ size_t DuplicateFromOffsetDialog::getNBytes() const void DuplicateFromOffsetDialog::refresh() { - RVA offestFrom = getOffset(); - QSignalBlocker sb(Core()); + RzCoreLocked core(Core()); + auto buf = Core()->ioRead(getOffset(), (int)getNBytes()); // Add space every two characters for word wrap in hex sequence QRegularExpression re { "(.{2})" }; - QString bytes = Core()->cmdRawAt(QString("p8 %1").arg(QString::number(getNBytes())), offestFrom) - .replace(re, "\\1 "); - - ui->bytesLabel->setText(bytes.trimmed()); + auto bytes = QString(buf).replace(re, "\\1 ").trimmed(); + ui->bytesLabel->setText(bytes); } diff --git a/src/menus/DisassemblyContextMenu.cpp b/src/menus/DisassemblyContextMenu.cpp index 2f6c6d66..a60e2196 100644 --- a/src/menus/DisassemblyContextMenu.cpp +++ b/src/menus/DisassemblyContextMenu.cpp @@ -1014,8 +1014,18 @@ void DisassemblyContextMenu::on_actionEditFunction_triggered() dialog.setStackSizeText(QString::number(fcn->stack)); - QStringList callConList = Core()->cmdRaw("afcl").split("\n"); - callConList.removeLast(); + QStringList callConList; + RzList *list = rz_analysis_calling_conventions(core->analysis); + if (!list) { + return; + } + RzListIter *iter; + const char *cc; + CutterRzListForeach (list, iter, const char, cc) { + callConList << cc; + } + rz_list_free(list); + dialog.setCallConList(callConList); dialog.setCallConSelected(fcn->cc); @@ -1026,7 +1036,15 @@ void DisassemblyContextMenu::on_actionEditFunction_triggered() fcn->addr = Core()->math(new_start_addr); QString new_stack_size = dialog.getStackSizeText(); fcn->stack = int(Core()->math(new_stack_size)); - Core()->cmdRaw("afc " + dialog.getCallConSelected()); + + const char *ccSelected = dialog.getCallConSelected().toUtf8().constData(); + if (RZ_STR_ISEMPTY(ccSelected)) { + return; + } + if (rz_analysis_cc_exist(core->analysis, ccSelected)) { + fcn->cc = rz_str_constpool_get(&core->analysis->constpool, ccSelected); + } + emit Core()->functionsChanged(); } } diff --git a/src/widgets/HexWidget.cpp b/src/widgets/HexWidget.cpp index b02a0e12..76cc586a 100644 --- a/src/widgets/HexWidget.cpp +++ b/src/widgets/HexWidget.cpp @@ -131,7 +131,8 @@ HexWidget::HexWidget(QWidget *parent) // delete comment option actionDeleteComment = new QAction(tr("Delete Comment"), this); actionDeleteComment->setShortcutContext(Qt::ShortcutContext::WidgetWithChildrenShortcut); - connect(actionDeleteComment, &QAction::triggered, this, &HexWidget::on_actionDeleteComment_triggered); + connect(actionDeleteComment, &QAction::triggered, this, + &HexWidget::on_actionDeleteComment_triggered); addAction(actionDeleteComment); actionSelectRange = new QAction(tr("Select range"), this); @@ -713,14 +714,14 @@ void HexWidget::copyAddress() clipboard->setText(RzAddressString(addr)); } -//slot for add comment action +// slot for add comment action void HexWidget::on_actionAddComment_triggered() { uint64_t addr = cursor.address; CommentsDialog::addOrEditComment(addr, this); } -//slot for deleting comment action +// slot for deleting comment action void HexWidget::on_actionDeleteComment_triggered() { uint64_t addr = cursor.address; @@ -742,14 +743,16 @@ void HexWidget::w_writeString() return; } bool ok = false; - QInputDialog d; - d.setInputMode(QInputDialog::InputMode::TextInput); - QString str = d.getText(this, tr("Write string"), tr("String:"), QLineEdit::Normal, "", &ok); - if (ok && !str.isEmpty()) { + QString str = QInputDialog::getText(this, tr("Write string"), tr("String:"), QLineEdit::Normal, + "", &ok); + if (!ok || str.isEmpty()) { + return; + } + { RzCoreLocked core(Core()); rz_core_write_string_at(core, getLocationAddress(), str.toUtf8().constData()); - refresh(); } + refresh(); } void HexWidget::w_increaseDecrease() @@ -767,8 +770,10 @@ void HexWidget::w_increaseDecrease() if (d.getMode() == IncrementDecrementDialog::Decrease) { value *= -1; } - RzCoreLocked core(Core()); - rz_core_write_value_inc_at(core, getLocationAddress(), value, sz); + { + RzCoreLocked core(Core()); + rz_core_write_value_inc_at(core, getLocationAddress(), value, sz); + } refresh(); } @@ -784,10 +789,8 @@ void HexWidget::w_writeBytes() size = static_cast(selection.size()); } - QInputDialog d; - d.setInputMode(QInputDialog::InputMode::TextInput); - QByteArray bytes = d.getText(this, tr("Write hex bytes"), tr("Hex byte string:"), - QLineEdit::Normal, "", &ok) + QByteArray bytes = QInputDialog::getText(this, tr("Write hex bytes"), tr("Hex byte string:"), + QLineEdit::Normal, "", &ok) .toUtf8(); const int offset = bytes.startsWith("\\x") ? 2 : 0; const int incr = offset + 2; @@ -795,16 +798,18 @@ void HexWidget::w_writeBytes() if (!ok || !bytes_size) { return; } - uint8_t *buf = (uint8_t *)malloc(static_cast(bytes_size)); - if (!buf) { - return; + { + auto *buf = (uint8_t *)malloc(static_cast(bytes_size)); + if (!buf) { + return; + } + for (int i = 0, j = 0, sz = bytes.size(); i < sz; i += incr, j++) { + buf[j] = static_cast(bytes.mid(i + offset, 2).toInt(nullptr, 16)); + } + RzCoreLocked core(Core()); + rz_core_write_at(core, getLocationAddress(), buf, bytes_size); + free(buf); } - for (int i = 0, j = 0, sz = bytes.size(); i < sz; i += incr, j++) { - buf[j] = static_cast(bytes.mid(i + offset, 2).toInt(nullptr, 16)); - } - RzCoreLocked core(Core()); - rz_core_write_at(core, getLocationAddress(), buf, bytes_size); - free(buf); refresh(); } @@ -813,24 +818,25 @@ void HexWidget::w_writeZeros() if (!ioModesController.prepareForWriting()) { return; } - bool ok = false; - QInputDialog d; int size = 1; if (!selection.isEmpty() && selection.size() <= INT_MAX) { size = static_cast(selection.size()); } - int len = - d.getInt(this, tr("Write zeros"), tr("Number of zeros:"), size, 1, 0x7FFFFFFF, 1, &ok); - if (ok) { + bool ok = false; + int len = QInputDialog::getInt(this, tr("Write zeros"), tr("Number of zeros:"), size, 1, + 0x7FFFFFFF, 1, &ok); + if (!ok) { + return; + } + { RzCoreLocked core(Core()); - uint8_t *buf = (uint8_t *)calloc(len, sizeof(uint8_t)); + auto *buf = (uint8_t *)calloc(len, sizeof(uint8_t)); rz_core_write_at(core, getLocationAddress(), buf, len); free(buf); - - refresh(); } + refresh(); } void HexWidget::w_write64() @@ -855,11 +861,13 @@ void HexWidget::w_write64() return; } - RzCoreLocked core(Core()); - if (d.getMode() == Base64EnDecodedWriteDialog::Encode) { - rz_core_write_base64_at(core, getLocationAddress(), str.toHex().constData()); - } else { - rz_core_write_base64d_at(core, getLocationAddress(), str.constData()); + { + RzCoreLocked core(Core()); + if (d.getMode() == Base64EnDecodedWriteDialog::Encode) { + rz_core_write_base64_at(core, getLocationAddress(), str.toHex().constData()); + } else { + rz_core_write_base64d_at(core, getLocationAddress(), str.constData()); + } } refresh(); } @@ -869,19 +877,24 @@ void HexWidget::w_writeRandom() if (!ioModesController.prepareForWriting()) { return; } - bool ok = false; - QInputDialog d; int size = 1; if (!selection.isEmpty() && selection.size() <= INT_MAX) { size = static_cast(selection.size()); } - QString nbytes = QString::number(d.getInt(this, tr("Write random"), tr("Number of bytes:"), - size, 1, 0x7FFFFFFF, 1, &ok)); - if (ok && !nbytes.isEmpty()) { - Core()->cmdRawAt(QString("wr %1").arg(nbytes), getLocationAddress()); - refresh(); + + bool ok = false; + int nbytes = QInputDialog::getInt(this, tr("Write random"), tr("Number of bytes:"), size, 1, + 0x7FFFFFFF, 1, &ok); + if (!ok) { + return; } + + { + RzCoreLocked core(Core()); + rz_core_write_random_at(core, getLocationAddress(), nbytes); + } + refresh(); } void HexWidget::w_duplFromOffset() @@ -894,9 +907,12 @@ void HexWidget::w_duplFromOffset() if (ret == QDialog::Rejected) { return; } - RVA copyFrom = d.getOffset(); - QString nBytes = QString::number(d.getNBytes()); - Core()->cmdRawAt(QString("wd %1 %2").arg(copyFrom).arg(nBytes), getLocationAddress()); + RVA src = d.getOffset(); + int len = (int)d.getNBytes(); + { + RzCoreLocked core(Core()); + rz_core_write_duplicate_at(core, getLocationAddress(), src, len); + } refresh(); } @@ -906,14 +922,16 @@ void HexWidget::w_writePascalString() return; } bool ok = false; - QInputDialog d; - d.setInputMode(QInputDialog::InputMode::TextInput); - QString str = - d.getText(this, tr("Write Pascal string"), tr("String:"), QLineEdit::Normal, "", &ok); - if (ok && !str.isEmpty()) { - Core()->cmdRawAt(QString("ws %1").arg(str), getLocationAddress()); - refresh(); + QString str = QInputDialog::getText(this, tr("Write Pascal string"), tr("String:"), + QLineEdit::Normal, "", &ok); + if (!ok || str.isEmpty()) { + return; } + { + RzCoreLocked core(Core()); + rz_core_write_length_string_at(core, getLocationAddress(), str.toUtf8().constData()); + } + refresh(); } void HexWidget::w_writeWideString() @@ -922,14 +940,16 @@ void HexWidget::w_writeWideString() return; } bool ok = false; - QInputDialog d; - d.setInputMode(QInputDialog::InputMode::TextInput); - QString str = - d.getText(this, tr("Write wide string"), tr("String:"), QLineEdit::Normal, "", &ok); - if (ok && !str.isEmpty()) { - Core()->cmdRawAt(QString("ww %1").arg(str), getLocationAddress()); - refresh(); + QString str = QInputDialog::getText(this, tr("Write wide string"), tr("String:"), + QLineEdit::Normal, "", &ok); + if (!ok || str.isEmpty()) { + return; } + { + RzCoreLocked core(Core()); + rz_core_write_string_wide_at(core, getLocationAddress(), str.toUtf8().constData()); + } + refresh(); } void HexWidget::w_writeCString() @@ -938,14 +958,16 @@ void HexWidget::w_writeCString() return; } bool ok = false; - QInputDialog d; - d.setInputMode(QInputDialog::InputMode::TextInput); - QString str = d.getText(this, tr("Write zero-terminated string"), tr("String:"), - QLineEdit::Normal, "", &ok); - if (ok && !str.isEmpty()) { - Core()->cmdRawAt(QString("wz %1").arg(str), getLocationAddress()); - refresh(); + QString str = QInputDialog::getText(this, tr("Write zero-terminated string"), tr("String:"), + QLineEdit::Normal, "", &ok); + if (!ok || str.isEmpty()) { + return; } + { + RzCoreLocked core(Core()); + rz_core_write_string_zero_at(core, getLocationAddress(), str.toUtf8().constData()); + } + refresh(); } void HexWidget::updateItemLength()