WingHexAsm/winghexasm.cpp

256 lines
6.4 KiB
C++

#include "winghexasm.h"
#include <QApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QMessageBox>
#include <QMetaEnum>
#include <QPushButton>
#include <QSettings>
#include <QVBoxLayout>
#define ICONRES(name) QIcon(":/WingHexAsm/img/" name ".png")
#define HOSTICONRES(name) QIcon(HOSTRESPIMG(name))
WingHexAsm::WingHexAsm(QObject *parent) { Q_UNUSED(parent) }
bool WingHexAsm::init(QList<WingPluginInfo> loadedplugin) {
Q_UNUSED(loadedplugin);
if (SDKVERSION < 8) {
QMessageBox::critical(nullptr, "Error",
"UnSupported Plugin System Version!",
QMessageBox::Ok);
return false;
}
auto translator = new QTranslator(this);
auto s = GETPLUGINQM("WingHexAsm.qm");
if (!translator->load(s) || !QApplication::installTranslator(translator)) {
QMessageBox::critical(nullptr, "Error", "Error Loading Translation File!",
QMessageBox::Ok);
return false;
}
w = new QWidget;
auto vlayout = new QVBoxLayout(w);
auto hlayout = new QHBoxLayout(w);
hlayout->addWidget(new QLabel(tr("Arch :"), w));
hlayout->addSpacing(10);
// 默认 x86_64 64 位指令
arch = new QComboBox(w);
QStringList archs(
{"ARM", "ARM64", "MIPS", "X86_64", "PPC", "SPARC", "EVM", "MOS65XX"});
arch->addItems(archs);
arch->setCurrentIndex(3);
void (QComboBox::*indexChanged)(int index) = &QComboBox::currentIndexChanged;
connect(arch, indexChanged, [=](int index) {
switch (index) {
case 0:
karch = ks_arch::KS_ARCH_ARM;
break;
case 1:
karch = ks_arch::KS_ARCH_ARM64;
break;
case 2:
karch = ks_arch::KS_ARCH_MIPS;
break;
case 3:
karch = ks_arch::KS_ARCH_X86;
break;
case 4:
karch = ks_arch::KS_ARCH_PPC;
break;
case 5:
karch = ks_arch::KS_ARCH_SPARC;
break;
case 6:
karch = ks_arch::KS_ARCH_EVM;
break;
}
});
hlayout->addWidget(arch);
hlayout->addSpacing(30);
hlayout->addWidget(new QLabel(tr("Mode :"), w));
hlayout->addSpacing(10);
mode = new QComboBox(w);
QStringList modes({"x16", "x32", "x64", "THUMB", "MIPS32", "MIPS64"});
mode->addItems(modes);
mode->setCurrentIndex(2);
connect(mode, indexChanged, [=](int index) {
switch (index) {
case 0:
kmode = ks_mode::KS_MODE_16;
break;
case 1:
kmode = ks_mode::KS_MODE_32;
break;
case 2:
kmode = ks_mode::KS_MODE_64;
break;
case 3:
kmode = ks_mode::KS_MODE_THUMB;
break;
case 4:
kmode = ks_mode::KS_MODE_MIPS32;
break;
case 5:
kmode = ks_mode::KS_MODE_MIPS64;
break;
}
});
hlayout->addWidget(mode);
hlayout->addSpacing(10);
cbintel = new QCheckBox("Intel", w);
cbintel->setChecked(true);
hlayout->addWidget(cbintel);
hlayout->addStretch();
vlayout->addSpacing(10);
txtAsm = new QTextBrowser(w);
txtAsm->setReadOnly(false);
vlayout->addItem(hlayout);
vlayout->addWidget(txtAsm);
vlayout->addSpacing(10);
auto asmbtn = new QPushButton(tr("AsmCode"), w);
connect(asmbtn, &QPushButton::clicked, this, [=] {
auto txt = txtAsm->toPlainText();
if (txt.length()) {
this->asmCode(txt);
} else {
this->toast(ICONRES("icon"), tr("No Asm"));
}
});
vlayout->addWidget(asmbtn);
PluginDockWidgetInit(dw, w, tr("AsmWindow"), "AsmWindow");
PluginMenuInitBegin(menu, tr("WingHexAsm")) {
menu->setIcon(ICONRES("icon"));
PluginMenuAddItemIconLamba(menu, tr("AsmWindow"), ICONRES("icon"), [=] {
dw->show();
dw->raise();
});
PluginMenuAddItemIconLamba(menu, tr("Author"), HOSTICONRES("author"), [=] {
auto authord =
newAboutDialog(QPixmap(), {":/WingHexAsm", ":/WingHexAsm/img"});
authord->exec();
delete authord;
});
PluginMenuAddItemIconLamba(menu, tr("Sponsor"), HOSTICONRES("sponsor"),
[=] {
auto sponsor = newSponsorDialog();
sponsor->exec();
delete sponsor;
});
}
PluginMenuInitEnd();
tbtn = new QToolButton;
tbtn->setIcon(ICONRES("icon"));
connect(tbtn, &QToolButton::clicked, this, [=] {
dw->show();
dw->raise();
});
return true;
}
WingHexAsm::~WingHexAsm() {}
void WingHexAsm::unload() {}
int WingHexAsm::sdkVersion() { return SDKVERSION; }
QMenu *WingHexAsm::registerMenu() { return menu; }
QToolButton *WingHexAsm::registerToolButton() { return tbtn; }
void WingHexAsm::registerDockWidget(
QMap<QDockWidget *, Qt::DockWidgetArea> &rdw) {
rdw.insert(dw, Qt::DockWidgetArea::BottomDockWidgetArea);
}
QString WingHexAsm::pluginName() { return tr("WingHexAsm"); }
QString WingHexAsm::pluginAuthor() { return WINGSUMMER; }
uint WingHexAsm::pluginVersion() { return 1; }
QString WingHexAsm::signature() { return WINGSUMMER; }
QString WingHexAsm::pluginComment() {
return tr("A small assembly plugin for WingHexExplorer.");
}
void WingHexAsm::plugin2MessagePipe(WingPluginMessage type,
QList<QVariant> msg) {
Q_UNUSED(type);
Q_UNUSED(msg);
}
void WingHexAsm::asmCode(QString code) {
ks_engine *ks;
ks_err err;
size_t count;
unsigned char *encode;
size_t size;
QIcon icon = ICONRES("icon");
err = ks_open(karch, kmode, &ks);
if (err != KS_ERR_OK) {
toast(icon, tr("ERROR: failed on ks_open()"));
return;
}
if (cbintel->isChecked()) {
ks_option(ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_INTEL);
} else {
ks_option(ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_ATT);
}
if (ks_asm(ks, code.toUtf8().constData(), 0, &encode, &size, &count)) {
toast(icon, tr("ERROR: failed on ks_asm() with count = %1, error code = %2")
.arg(count)
.arg(ks_errno(ks)));
} else {
QByteArray buffer(reinterpret_cast<char *>(encode), int(size));
if (reader.currentDoc() < 0) {
USINGCONTROL({
controller.newFile();
controller.insert(0, buffer); // 直接使用 insert 会比 append 更高效一点
});
} else {
USINGCONTROL({
auto pos = reader.currentOffset();
controller.insert(qint64(pos), buffer);
});
}
toast(icon, tr("ASMSuccessfully"));
}
// NOTE: free encode after usage to avoid leaking memory
ks_free(encode);
// close Keystone instance when done
ks_close(ks);
}
#if QT_VERSION < 0x050000
Q_EXPORT_PLUGIN2(WingHexAsm, WingHexAsm)
#endif // QT_VERSION < 0x050000