2017-10-01 19:09:42 +00:00
|
|
|
#include "XrefsDialog.h"
|
|
|
|
#include "ui_XrefsDialog.h"
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2018-10-17 07:55:53 +00:00
|
|
|
#include "common/TempConfig.h"
|
|
|
|
#include "common/Helpers.h"
|
2017-11-20 20:11:56 +00:00
|
|
|
|
2017-10-01 19:09:42 +00:00
|
|
|
#include "MainWindow.h"
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
#include <QJsonArray>
|
|
|
|
|
2017-10-10 10:17:05 +00:00
|
|
|
XrefsDialog::XrefsDialog(QWidget *parent) :
|
2017-03-29 10:18:37 +00:00
|
|
|
QDialog(parent),
|
2017-10-01 18:08:12 +00:00
|
|
|
addr(0),
|
|
|
|
func_name(QString::null),
|
|
|
|
ui(new Ui::XrefsDialog),
|
2018-04-12 06:33:30 +00:00
|
|
|
core(Core())
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
2017-03-31 00:51:14 +00:00
|
|
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2019-01-02 19:58:02 +00:00
|
|
|
// Modify the splitter's location to show more Disassembly instead of empty space. Not possible via Designer
|
|
|
|
ui->splitter->setSizes(QList<int>() << 100 << 200);
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Increase asm text edit margin
|
|
|
|
QTextDocument *asm_docu = ui->previewTextEdit->document();
|
|
|
|
asm_docu->setDocumentMargin(10);
|
|
|
|
|
2017-11-20 20:11:56 +00:00
|
|
|
setupPreviewFont();
|
|
|
|
setupPreviewColors();
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Highlight current line
|
|
|
|
connect(ui->previewTextEdit, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
|
2017-11-20 20:11:56 +00:00
|
|
|
|
|
|
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(setupPreviewFont()));
|
|
|
|
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(setupPreviewColors()));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 09:41:28 +00:00
|
|
|
XrefsDialog::~XrefsDialog() {}
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
void XrefsDialog::fillRefs(QList<XrefDescription> refs, QList<XrefDescription> xrefs)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-11-27 11:18:47 +00:00
|
|
|
/* Fill refs */
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->fromTreeWidget->clear();
|
2018-03-21 20:32:32 +00:00
|
|
|
for (int i = 0; i < refs.size(); ++i) {
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = refs[i];
|
2017-06-07 15:48:36 +00:00
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
2017-11-27 16:05:10 +00:00
|
|
|
tempItem->setText(0, xref.to_str);
|
2017-11-28 11:22:48 +00:00
|
|
|
tempItem->setText(1, core->disassembleSingleInstruction(xref.to));
|
2017-11-27 11:18:47 +00:00
|
|
|
tempItem->setText(2, xrefTypeString(xref.type));
|
2017-11-28 11:26:52 +00:00
|
|
|
tempItem->setData(0, Qt::UserRole, QVariant::fromValue(xref));
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->fromTreeWidget->insertTopLevelItem(0, tempItem);
|
|
|
|
}
|
|
|
|
// Adjust columns to content
|
2018-04-01 08:25:31 +00:00
|
|
|
qhelpers::adjustColumns(ui->fromTreeWidget, 0);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-11-27 11:18:47 +00:00
|
|
|
/* Fill Xrefs */
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->toTreeWidget->clear();
|
2018-03-21 20:32:32 +00:00
|
|
|
for (int i = 0; i < xrefs.size(); ++i) {
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = xrefs[i];
|
2017-06-07 15:48:36 +00:00
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
2017-11-27 16:05:10 +00:00
|
|
|
tempItem->setText(0, xref.from_str);
|
2017-10-09 18:08:35 +00:00
|
|
|
tempItem->setText(1, core->disassembleSingleInstruction(xref.from));
|
2017-11-27 11:18:47 +00:00
|
|
|
tempItem->setText(2, xrefTypeString(xref.type));
|
2017-11-28 11:26:52 +00:00
|
|
|
tempItem->setData(0, Qt::UserRole, QVariant::fromValue(xref));
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->toTreeWidget->insertTopLevelItem(0, tempItem);
|
|
|
|
}
|
|
|
|
// Adjust columns to content
|
2018-04-01 08:25:31 +00:00
|
|
|
qhelpers::adjustColumns(ui->toTreeWidget, 0);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XrefsDialog::on_fromTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
|
|
|
|
{
|
2017-10-01 18:08:12 +00:00
|
|
|
Q_UNUSED(column);
|
2017-04-09 17:09:35 +00:00
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
2017-10-22 07:31:30 +00:00
|
|
|
Core()->seek(xref.to);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void XrefsDialog::on_toTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column)
|
|
|
|
{
|
2017-10-01 18:08:12 +00:00
|
|
|
Q_UNUSED(column);
|
2017-04-09 17:09:35 +00:00
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
2017-10-22 07:31:30 +00:00
|
|
|
Core()->seek(xref.from);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->close();
|
|
|
|
}
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
QString XrefsDialog::normalizeAddr(const QString &addr) const
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-11-27 11:18:47 +00:00
|
|
|
QString r = addr;
|
2017-03-29 10:18:37 +00:00
|
|
|
QString base = addr.split("0x")[1].trimmed();
|
|
|
|
int len = base.length();
|
2018-03-21 20:32:32 +00:00
|
|
|
if (len < 8) {
|
2017-03-29 10:18:37 +00:00
|
|
|
int padding = 8 - len;
|
|
|
|
QString zero = "0";
|
|
|
|
QString zeroes = zero.repeated(padding);
|
2017-11-27 11:18:47 +00:00
|
|
|
r = "0x" + zeroes + base;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-11-27 11:18:47 +00:00
|
|
|
|
|
|
|
return r;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-11-20 20:11:56 +00:00
|
|
|
void XrefsDialog::setupPreviewFont()
|
|
|
|
{
|
|
|
|
ui->previewTextEdit->setFont(Config()->getFont());
|
|
|
|
}
|
|
|
|
|
|
|
|
void XrefsDialog::setupPreviewColors()
|
|
|
|
{
|
|
|
|
ui->previewTextEdit->setStyleSheet(QString("QPlainTextEdit { background-color: %1; color: %2; }")
|
2018-03-21 20:32:32 +00:00
|
|
|
.arg(ConfigColor("gui.background").name())
|
|
|
|
.arg(ConfigColor("btext").name()));
|
2017-11-20 20:11:56 +00:00
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void XrefsDialog::highlightCurrentLine()
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
|
|
|
|
2018-03-21 20:32:32 +00:00
|
|
|
if (ui->previewTextEdit->isReadOnly()) {
|
2017-03-29 10:18:37 +00:00
|
|
|
QTextEdit::ExtraSelection selection;
|
|
|
|
|
2018-07-02 09:11:06 +00:00
|
|
|
selection.format.setBackground(ConfigColor("highlight"));
|
2017-03-29 10:18:37 +00:00
|
|
|
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
|
|
|
selection.cursor = ui->previewTextEdit->textCursor();
|
|
|
|
selection.cursor.clearSelection();
|
|
|
|
extraSelections.append(selection);
|
|
|
|
|
|
|
|
ui->previewTextEdit->setExtraSelections(extraSelections);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void XrefsDialog::on_fromTreeWidget_itemSelectionChanged()
|
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
if (ui->fromTreeWidget->selectedItems().isEmpty())
|
|
|
|
return;
|
|
|
|
ui->toTreeWidget->clearSelection();
|
2017-03-29 10:18:37 +00:00
|
|
|
QTreeWidgetItem *item = ui->fromTreeWidget->currentItem();
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
|
|
|
updatePreview(xref.to);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XrefsDialog::on_toTreeWidget_itemSelectionChanged()
|
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
if (ui->toTreeWidget->selectedItems().isEmpty())
|
|
|
|
return;
|
|
|
|
ui->fromTreeWidget->clearSelection();
|
2017-03-29 10:18:37 +00:00
|
|
|
QTreeWidgetItem *item = ui->toTreeWidget->currentItem();
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
|
|
|
updatePreview(xref.from);
|
|
|
|
}
|
|
|
|
|
|
|
|
void XrefsDialog::updatePreview(RVA addr)
|
|
|
|
{
|
2017-11-20 20:11:56 +00:00
|
|
|
// is the address part of a function, so we can use pdf?
|
|
|
|
bool isFunction = !core->cmdj("afij@" + QString::number(addr)).array().isEmpty();
|
|
|
|
|
|
|
|
TempConfig tempConfig;
|
|
|
|
tempConfig.set("scr.html", true);
|
2018-03-01 16:06:13 +00:00
|
|
|
tempConfig.set("scr.color", COLOR_MODE_16M);
|
2017-11-20 20:11:56 +00:00
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
QString disass;
|
|
|
|
|
2017-11-20 20:11:56 +00:00
|
|
|
if (isFunction)
|
2017-10-09 18:08:35 +00:00
|
|
|
disass = core->cmd("pdf @ " + QString::number(addr));
|
2017-06-07 19:35:38 +00:00
|
|
|
else
|
2017-10-09 18:08:35 +00:00
|
|
|
disass = core->cmd("pd 10 @ " + QString::number(addr));
|
2017-06-07 19:35:38 +00:00
|
|
|
|
2017-11-20 20:11:56 +00:00
|
|
|
ui->previewTextEdit->document()->setHtml(disass);
|
2017-06-07 19:35:38 +00:00
|
|
|
|
|
|
|
// Does it make any sense?
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->previewTextEdit->moveCursor(QTextCursor::End);
|
2017-06-07 19:35:38 +00:00
|
|
|
ui->previewTextEdit->find(this->normalizeAddr(RAddressString(addr)), QTextDocument::FindBackward);
|
2017-11-20 20:11:56 +00:00
|
|
|
ui->previewTextEdit->moveCursor(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-04-04 11:19:34 +00:00
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void XrefsDialog::updateLabels(QString name)
|
|
|
|
{
|
2017-11-27 16:05:10 +00:00
|
|
|
ui->label_xTo->setText(tr("X-Refs to %1:").arg(name));
|
|
|
|
ui->label_xFrom->setText(tr("X-Refs from %1:").arg(name));
|
2017-04-04 11:19:34 +00:00
|
|
|
}
|
2017-06-07 15:48:36 +00:00
|
|
|
|
2017-06-08 22:40:43 +00:00
|
|
|
void XrefsDialog::fillRefsForAddress(RVA addr, QString name, bool whole_function)
|
2017-06-07 15:48:36 +00:00
|
|
|
{
|
2017-11-20 20:11:56 +00:00
|
|
|
TempConfig tempConfig;
|
|
|
|
tempConfig.set("scr.html", false);
|
2018-03-01 16:06:13 +00:00
|
|
|
tempConfig.set("scr.color", COLOR_MODE_DISABLED);
|
2017-11-20 20:11:56 +00:00
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
this->addr = addr;
|
|
|
|
this->func_name = func_name;
|
|
|
|
|
2017-06-08 22:40:43 +00:00
|
|
|
setWindowTitle(tr("X-Refs for %1").arg(name));
|
2017-06-07 15:48:36 +00:00
|
|
|
updateLabels(name);
|
|
|
|
// Get Refs and Xrefs
|
|
|
|
|
|
|
|
// refs = calls q hace esa funcion
|
2017-10-09 18:08:35 +00:00
|
|
|
QList<XrefDescription> refs = core->getXRefs(addr, false, whole_function);
|
2017-06-07 15:48:36 +00:00
|
|
|
|
|
|
|
// xrefs = calls a esa funcion
|
2017-10-09 18:08:35 +00:00
|
|
|
QList<XrefDescription> xrefs = core->getXRefs(addr, true, whole_function);
|
2017-06-07 15:48:36 +00:00
|
|
|
|
|
|
|
fillRefs(refs, xrefs);
|
2017-10-01 18:08:12 +00:00
|
|
|
}
|
2017-11-27 11:18:47 +00:00
|
|
|
|
|
|
|
QString XrefsDialog::xrefTypeString(const QString &type)
|
|
|
|
{
|
|
|
|
switch (type.toStdString()[0]) {
|
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
return QString("Call");
|
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
|
|
|
return QString("Code");
|
|
|
|
case R_ANAL_REF_TYPE_DATA:
|
|
|
|
return QString("Data");
|
|
|
|
case R_ANAL_REF_TYPE_NULL:
|
|
|
|
return QString("");
|
|
|
|
case R_ANAL_REF_TYPE_STRING:
|
|
|
|
return QString("String");
|
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|