2017-09-28 21:53:59 +00:00
|
|
|
#include "MemoryWidget.h"
|
|
|
|
#include "ui_MemoryWidget.h"
|
|
|
|
#include "DisassemblerGraphView.h"
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-10-01 19:09:42 +00:00
|
|
|
#include "MainWindow.h"
|
|
|
|
#include "utils/Helpers.h"
|
|
|
|
#include "dialogs/XrefsDialog.h"
|
2017-10-10 10:17:05 +00:00
|
|
|
#include "menus/DisassemblyContextMenu.h"
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
#include <QTemporaryFile>
|
|
|
|
#include <QFontDialog>
|
|
|
|
#include <QScrollBar>
|
|
|
|
#include <QClipboard>
|
|
|
|
#include <QShortcut>
|
2017-04-12 16:49:01 +00:00
|
|
|
#include <QWebEnginePage>
|
2017-03-29 10:18:37 +00:00
|
|
|
#include <QMenu>
|
|
|
|
#include <QFont>
|
|
|
|
#include <QUrl>
|
2017-04-12 16:49:01 +00:00
|
|
|
#include <QWebEngineSettings>
|
2017-04-22 23:29:57 +00:00
|
|
|
#include <QWebEngineProfile>
|
2017-04-13 15:14:02 +00:00
|
|
|
#include <QSettings>
|
|
|
|
|
|
|
|
#include <cassert>
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
MemoryWidget::MemoryWidget() :
|
|
|
|
ui(new Ui::MemoryWidget),
|
|
|
|
core(CutterCore::getInstance())
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
this->disasTextEdit = ui->disasTextEdit_2;
|
|
|
|
this->hexOffsetText = ui->hexOffsetText_2;
|
|
|
|
this->hexHexText = ui->hexHexText_2;
|
|
|
|
this->hexDisasTextEdit = ui->hexDisasTextEdit_2;
|
|
|
|
this->hexASCIIText = ui->hexASCIIText_2;
|
|
|
|
this->xrefToTreeWidget_2 = ui->xrefToTreeWidget_2;
|
|
|
|
this->xreFromTreeWidget_2 = ui->xreFromTreeWidget_2;
|
|
|
|
this->memTabWidget = ui->memTabWidget;
|
|
|
|
|
|
|
|
this->last_fcn = "entry0";
|
2017-04-28 13:09:40 +00:00
|
|
|
this->last_graph_fcn = 0; //"";
|
|
|
|
this->last_hexdump_fcn = 0; //"";
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
disasm_top_offset = 0;
|
|
|
|
next_disasm_top_offset = 0;
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Increase asm text edit margin
|
|
|
|
QTextDocument *asm_docu = this->disasTextEdit->document();
|
|
|
|
asm_docu->setDocumentMargin(10);
|
|
|
|
|
|
|
|
// Setup disasm highlight
|
|
|
|
connect(ui->disasTextEdit_2, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
|
|
|
|
highlightCurrentLine();
|
|
|
|
//this->on_actionSettings_menu_1_triggered();
|
|
|
|
|
|
|
|
// Setup hex highlight
|
|
|
|
//connect(ui->hexHexText, SIGNAL(cursorPositionChanged()), this, SLOT(highlightHexCurrentLine()));
|
|
|
|
//highlightHexCurrentLine();
|
|
|
|
|
|
|
|
// Highlight current line on previews and decompiler
|
|
|
|
connect(ui->previewTextEdit, SIGNAL(cursorPositionChanged()), this, SLOT(highlightPreviewCurrentLine()));
|
|
|
|
connect(ui->decoTextEdit, SIGNAL(cursorPositionChanged()), this, SLOT(highlightDecoCurrentLine()));
|
|
|
|
|
|
|
|
// Hide memview notebooks tabs
|
|
|
|
QTabBar *bar = ui->memTabWidget->tabBar();
|
|
|
|
bar->setVisible(false);
|
|
|
|
QTabBar *sidebar = ui->memSideTabWidget_2->tabBar();
|
|
|
|
sidebar->setVisible(false);
|
|
|
|
QTabBar *preTab = ui->memPreviewTab->tabBar();
|
|
|
|
preTab->setVisible(false);
|
|
|
|
|
|
|
|
// Hide fcn graph notebooks tabs
|
|
|
|
QTabBar *graph_bar = ui->fcnGraphTabWidget->tabBar();
|
|
|
|
graph_bar->setVisible(false);
|
|
|
|
|
2017-04-06 21:55:40 +00:00
|
|
|
// Debug console
|
2017-04-12 16:49:01 +00:00
|
|
|
// For QWebEngine debugging see: https://doc.qt.io/qt-5/qtwebengine-debugging.html
|
|
|
|
//QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Add margin to function name line edit
|
|
|
|
ui->fcnNameEdit->setTextMargins(5, 0, 0, 0);
|
|
|
|
|
|
|
|
// Normalize fonts for other OS
|
2017-04-05 08:56:59 +00:00
|
|
|
qhelpers::normalizeFont(this->disasTextEdit);
|
|
|
|
qhelpers::normalizeEditFont(this->hexOffsetText);
|
|
|
|
qhelpers::normalizeEditFont(this->hexHexText);
|
|
|
|
qhelpers::normalizeEditFont(this->hexASCIIText);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Popup menu on Settings toolbutton
|
|
|
|
QMenu *memMenu = new QMenu();
|
|
|
|
ui->memSettingsButton_2->addAction(ui->actionSettings_menu_1);
|
|
|
|
memMenu->addAction(ui->actionSettings_menu_1);
|
|
|
|
ui->memSettingsButton_2->setMenu(memMenu);
|
|
|
|
|
2017-04-10 12:12:42 +00:00
|
|
|
// Event filter to intercept double clicks in the textbox
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->disasTextEdit_2->viewport()->installEventFilter(this);
|
|
|
|
|
|
|
|
// Set Splitter stretch factor
|
|
|
|
ui->splitter->setStretchFactor(0, 10);
|
|
|
|
ui->splitter->setStretchFactor(1, 1);
|
|
|
|
|
|
|
|
// Set Disas context menu
|
|
|
|
ui->disasTextEdit_2->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(ui->disasTextEdit_2, SIGNAL(customContextMenuRequested(const QPoint &)),
|
|
|
|
this, SLOT(showDisasContextMenu(const QPoint &)));
|
|
|
|
|
|
|
|
// Set hexdump context menu
|
|
|
|
ui->hexHexText_2->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(ui->hexHexText_2, SIGNAL(customContextMenuRequested(const QPoint &)),
|
|
|
|
this, SLOT(showHexdumpContextMenu(const QPoint &)));
|
|
|
|
ui->hexASCIIText_2->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
connect(ui->hexASCIIText_2, SIGNAL(customContextMenuRequested(const QPoint &)),
|
|
|
|
this, SLOT(showHexASCIIContextMenu(const QPoint &)));
|
|
|
|
|
|
|
|
// Syncronize hexdump scrolling
|
|
|
|
connect(ui->hexOffsetText_2->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
ui->hexHexText_2->verticalScrollBar(), SLOT(setValue(int)));
|
|
|
|
connect(ui->hexOffsetText_2->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
ui->hexASCIIText_2->verticalScrollBar(), SLOT(setValue(int)));
|
|
|
|
|
|
|
|
connect(ui->hexHexText_2->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
ui->hexOffsetText_2->verticalScrollBar(), SLOT(setValue(int)));
|
|
|
|
connect(ui->hexHexText_2->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
ui->hexASCIIText_2->verticalScrollBar(), SLOT(setValue(int)));
|
|
|
|
|
|
|
|
connect(ui->hexASCIIText_2->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
ui->hexOffsetText_2->verticalScrollBar(), SLOT(setValue(int)));
|
|
|
|
connect(ui->hexASCIIText_2->verticalScrollBar(), SIGNAL(valueChanged(int)),
|
|
|
|
ui->hexHexText_2->verticalScrollBar(), SLOT(setValue(int)));
|
|
|
|
|
2017-06-08 22:40:43 +00:00
|
|
|
// x or X to show XRefs
|
|
|
|
connect(new QShortcut(QKeySequence(Qt::Key_X), ui->disasTextEdit_2),
|
|
|
|
SIGNAL(activated()), this, SLOT(showXrefsDialog()));
|
|
|
|
connect(new QShortcut(Qt::SHIFT + Qt::Key_X, ui->disasTextEdit_2),
|
|
|
|
SIGNAL(activated()), this, SLOT(showXrefsDialog()));
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Space to switch between disassembly and graph
|
2017-10-09 18:08:35 +00:00
|
|
|
QShortcut *graph_shortcut = new QShortcut(QKeySequence(Qt::Key_Space), this);
|
2017-03-29 10:18:37 +00:00
|
|
|
connect(graph_shortcut, SIGNAL(activated()), this, SLOT(cycleViews()));
|
2017-04-05 09:35:19 +00:00
|
|
|
//graph_shortcut->setContext(Qt::WidgetShortcut);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Semicolon to add comment
|
2017-04-09 19:55:06 +00:00
|
|
|
QShortcut *comment_shortcut = new QShortcut(QKeySequence(Qt::Key_Semicolon), ui->disasTextEdit_2);
|
2017-03-29 10:18:37 +00:00
|
|
|
connect(comment_shortcut, SIGNAL(activated()), this, SLOT(on_actionDisasAdd_comment_triggered()));
|
2017-04-05 09:35:19 +00:00
|
|
|
comment_shortcut->setContext(Qt::WidgetShortcut);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// N to rename function
|
2017-04-09 19:55:06 +00:00
|
|
|
QShortcut *rename_shortcut = new QShortcut(QKeySequence(Qt::Key_N), ui->disasTextEdit_2);
|
2017-03-29 10:18:37 +00:00
|
|
|
connect(rename_shortcut, SIGNAL(activated()), this, SLOT(on_actionFunctionsRename_triggered()));
|
2017-04-05 09:35:19 +00:00
|
|
|
rename_shortcut->setContext(Qt::WidgetShortcut);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-04-05 09:35:19 +00:00
|
|
|
// Esc to seek back
|
2017-04-09 19:55:06 +00:00
|
|
|
QShortcut *back_shortcut = new QShortcut(QKeySequence(Qt::Key_Escape), ui->disasTextEdit_2);
|
2017-04-05 09:35:19 +00:00
|
|
|
connect(back_shortcut, SIGNAL(activated()), this, SLOT(seek_back()));
|
|
|
|
back_shortcut->setContext(Qt::WidgetShortcut);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-04-09 15:37:54 +00:00
|
|
|
// CTRL + R to refresh the disasm
|
2017-04-09 19:55:06 +00:00
|
|
|
QShortcut *refresh_shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_R), ui->disasTextEdit_2);
|
2017-04-09 15:37:54 +00:00
|
|
|
connect(refresh_shortcut, SIGNAL(activated()), this, SLOT(refreshDisasm()));
|
|
|
|
refresh_shortcut->setContext(Qt::WidgetShortcut);
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Control Disasm and Hex scroll to add more contents
|
|
|
|
connect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
|
|
|
|
connect(this->hexASCIIText->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hexScrolled()));
|
2017-04-05 14:03:36 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
connect(core, SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA)));
|
|
|
|
//connect(main, SIGNAL(cursorAddressChanged(RVA)), this, SLOT(on_cursorAddressChanged(RVA)));
|
|
|
|
connect(core, SIGNAL(flagsChanged()), this, SLOT(updateViews()));
|
|
|
|
connect(core, SIGNAL(commentsChanged()), this, SLOT(updateViews()));
|
|
|
|
connect(core, SIGNAL(asmOptionsChanged()), this, SLOT(updateViews()));
|
2017-05-13 18:09:36 +00:00
|
|
|
|
|
|
|
fillPlugins();
|
2017-04-28 13:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-03 18:38:34 +00:00
|
|
|
void MemoryWidget::on_seekChanged(RVA addr)
|
2017-07-11 11:05:42 +00:00
|
|
|
{
|
|
|
|
updateViews(addr);
|
|
|
|
}
|
2017-04-28 13:09:40 +00:00
|
|
|
|
|
|
|
void MemoryWidget::on_cursorAddressChanged(RVA addr)
|
|
|
|
{
|
|
|
|
setFcnName(addr);
|
2017-06-07 19:35:38 +00:00
|
|
|
get_refs_data(addr);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Text highlight functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
void MemoryWidget::highlightDisasms()
|
|
|
|
{
|
|
|
|
// Syntax Highliting
|
2017-10-09 18:08:35 +00:00
|
|
|
highlighter = new Highlighter(ui->disasTextEdit_2->document());
|
|
|
|
highlighter_5 = new Highlighter(ui->hexDisasTextEdit_2->document());
|
2017-03-29 10:18:37 +00:00
|
|
|
ascii_highlighter = new AsciiHighlighter(ui->hexASCIIText_2->document());
|
|
|
|
hex_highlighter = new HexHighlighter(ui->hexHexText_2->document());
|
2017-10-09 18:08:35 +00:00
|
|
|
preview_highlighter = new Highlighter(ui->previewTextEdit->document());
|
|
|
|
deco_highlighter = new Highlighter(ui->decoTextEdit->document());
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::highlightCurrentLine()
|
|
|
|
{
|
|
|
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
|
|
|
|
|
|
|
// Highlight the current line in yellow
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->disasTextEdit_2->isReadOnly())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QTextEdit::ExtraSelection selection;
|
|
|
|
|
|
|
|
QColor lineColor = QColor(190, 144, 212);
|
|
|
|
|
|
|
|
selection.format.setBackground(lineColor);
|
|
|
|
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
|
|
|
selection.cursor = ui->disasTextEdit_2->textCursor();
|
|
|
|
selection.cursor.clearSelection();
|
|
|
|
extraSelections.append(selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Highlight the current word
|
|
|
|
QTextCursor cursor = ui->disasTextEdit_2->textCursor();
|
|
|
|
cursor.select(QTextCursor::WordUnderCursor);
|
|
|
|
|
|
|
|
QTextEdit::ExtraSelection currentWord;
|
|
|
|
|
|
|
|
QColor blueColor = QColor(Qt::blue).lighter(160);
|
|
|
|
currentWord.format.setBackground(blueColor);
|
|
|
|
|
|
|
|
currentWord.cursor = cursor;
|
|
|
|
extraSelections.append(currentWord);
|
|
|
|
currentWord.cursor.clearSelection();
|
|
|
|
|
|
|
|
// Highlight all the words in the document same as the actual one
|
|
|
|
QString searchString = cursor.selectedText();
|
|
|
|
QTextDocument *document = ui->disasTextEdit_2->document();
|
|
|
|
|
|
|
|
//QTextCursor highlightCursor(document);
|
|
|
|
QTextEdit::ExtraSelection highlightSelection;
|
|
|
|
highlightSelection.cursor = cursor;
|
|
|
|
highlightSelection.format.setBackground(blueColor);
|
|
|
|
QTextCursor cursor2(document);
|
|
|
|
|
|
|
|
cursor2.beginEditBlock();
|
|
|
|
|
|
|
|
highlightSelection.cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
2017-04-09 19:55:06 +00:00
|
|
|
while (!highlightSelection.cursor.isNull() && !highlightSelection.cursor.atEnd())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
highlightSelection.cursor = document->find(searchString, highlightSelection.cursor, QTextDocument::FindWholeWords);
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!highlightSelection.cursor.isNull())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
highlightSelection.cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
|
|
|
extraSelections.append(highlightSelection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cursor2.endEditBlock();
|
|
|
|
|
|
|
|
ui->disasTextEdit_2->setExtraSelections(extraSelections);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::highlightHexCurrentLine()
|
|
|
|
{
|
|
|
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!ui->hexHexText_2->isReadOnly())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QTextEdit::ExtraSelection selection;
|
|
|
|
|
|
|
|
QColor lineColor = QColor(190, 144, 212);
|
|
|
|
|
|
|
|
selection.format.setBackground(lineColor);
|
|
|
|
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
|
|
|
selection.cursor = ui->hexHexText_2->textCursor();
|
|
|
|
selection.cursor.clearSelection();
|
|
|
|
extraSelections.append(selection);
|
|
|
|
}
|
|
|
|
|
|
|
|
QTextCursor cursor = ui->hexHexText_2->textCursor();
|
|
|
|
cursor.select(QTextCursor::WordUnderCursor);
|
|
|
|
|
|
|
|
QTextEdit::ExtraSelection currentWord;
|
|
|
|
|
|
|
|
QColor blueColor = QColor(Qt::blue).lighter(160);
|
|
|
|
currentWord.format.setBackground(blueColor);
|
|
|
|
|
|
|
|
currentWord.cursor = cursor;
|
|
|
|
extraSelections.append(currentWord);
|
|
|
|
|
|
|
|
ui->hexHexText_2->setExtraSelections(extraSelections);
|
|
|
|
|
|
|
|
highlightHexWords(cursor.selectedText());
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:38:01 +00:00
|
|
|
void MemoryWidget::highlightHexWords(const QString &str)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
QString searchString = str;
|
|
|
|
QTextDocument *document = ui->hexHexText_2->document();
|
|
|
|
|
|
|
|
document->undo();
|
|
|
|
|
|
|
|
QTextCursor highlightCursor(document);
|
|
|
|
QTextCursor cursor(document);
|
|
|
|
|
|
|
|
cursor.beginEditBlock();
|
|
|
|
|
|
|
|
QColor blueColor = QColor(Qt::blue).lighter(160);
|
|
|
|
|
|
|
|
QTextCharFormat plainFormat(highlightCursor.charFormat());
|
|
|
|
QTextCharFormat colorFormat = plainFormat;
|
|
|
|
colorFormat.setBackground(blueColor);
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
while (!highlightCursor.isNull() && !highlightCursor.atEnd())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
highlightCursor = document->find(searchString, highlightCursor, QTextDocument::FindWholeWords);
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!highlightCursor.isNull())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
highlightCursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
|
|
|
|
highlightCursor.mergeCharFormat(colorFormat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cursor.endEditBlock();
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::highlightPreviewCurrentLine()
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->previewTextEdit->toPlainText() != "")
|
|
|
|
{
|
|
|
|
if (ui->previewTextEdit->isReadOnly())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QTextEdit::ExtraSelection selection;
|
|
|
|
|
|
|
|
QColor lineColor = QColor(190, 144, 212);
|
|
|
|
|
|
|
|
selection.format.setBackground(lineColor);
|
|
|
|
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
|
|
|
selection.cursor = ui->previewTextEdit->textCursor();
|
|
|
|
selection.cursor.clearSelection();
|
|
|
|
extraSelections.append(selection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ui->previewTextEdit->setExtraSelections(extraSelections);
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::highlightDecoCurrentLine()
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
QList<QTextEdit::ExtraSelection> extraSelections;
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->decoTextEdit->toPlainText() != "")
|
|
|
|
{
|
|
|
|
if (ui->decoTextEdit->isReadOnly())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QTextEdit::ExtraSelection selection;
|
|
|
|
|
|
|
|
QColor lineColor = QColor(190, 144, 212);
|
|
|
|
|
|
|
|
selection.format.setBackground(lineColor);
|
|
|
|
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
|
|
|
selection.cursor = ui->decoTextEdit->textCursor();
|
|
|
|
selection.cursor.clearSelection();
|
|
|
|
extraSelections.append(selection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ui->decoTextEdit->setExtraSelections(extraSelections);
|
|
|
|
}
|
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
RVA MemoryWidget::readCurrentDisassemblyOffset()
|
|
|
|
{
|
|
|
|
// TODO: do this in a different way without parsing the disassembly text
|
|
|
|
QTextCursor tc = this->disasTextEdit->textCursor();
|
|
|
|
tc.select(QTextCursor::LineUnderCursor);
|
|
|
|
QString lastline = tc.selectedText();
|
|
|
|
QStringList parts = lastline.split(" ", QString::SkipEmptyParts);
|
|
|
|
|
|
|
|
if (parts.isEmpty())
|
|
|
|
return RVA_INVALID;
|
|
|
|
|
|
|
|
QString ele = parts[0];
|
|
|
|
if (!ele.contains("0x"))
|
|
|
|
return RVA_INVALID;
|
|
|
|
|
|
|
|
return ele.toULongLong(0, 16);
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-10-02 09:41:28 +00:00
|
|
|
MemoryWidget::~MemoryWidget() {}
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-04-13 15:14:02 +00:00
|
|
|
void MemoryWidget::setup()
|
|
|
|
{
|
|
|
|
setScrollMode();
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
const QString off = core->cmd("afo entry0").trimmed();
|
2017-07-11 11:05:42 +00:00
|
|
|
RVA offset = off.toULongLong(0, 16);
|
|
|
|
updateViews(offset);
|
2017-04-13 15:14:02 +00:00
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
//refreshDisasm();
|
|
|
|
//refreshHexdump(off);
|
|
|
|
//create_graph(off);
|
|
|
|
get_refs_data(offset);
|
2017-04-28 13:09:40 +00:00
|
|
|
//setFcnName(off);
|
2017-04-13 15:14:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::refresh()
|
|
|
|
{
|
|
|
|
setScrollMode();
|
|
|
|
|
|
|
|
// TODO: honor the offset
|
2017-10-03 18:38:34 +00:00
|
|
|
updateViews(RVA_INVALID);
|
2017-04-13 15:14:02 +00:00
|
|
|
}
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
/*
|
|
|
|
* Content management functions
|
|
|
|
*/
|
|
|
|
|
2017-05-13 18:09:36 +00:00
|
|
|
void MemoryWidget::fillPlugins()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
// Fill the plugins combo for the hexdump sidebar
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->hexArchComboBox_2->insertItems(0, core->getAsmPluginNames());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::addTextDisasm(QString txt)
|
|
|
|
{
|
2017-04-12 20:44:05 +00:00
|
|
|
//QTextDocument *document = ui->disasTextEdit_2->document();
|
2017-03-29 10:18:37 +00:00
|
|
|
//document->undo();
|
|
|
|
ui->disasTextEdit_2->appendPlainText(txt);
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::replaceTextDisasm(QString txt)
|
|
|
|
{
|
2017-04-12 20:44:05 +00:00
|
|
|
//QTextDocument *document = ui->disasTextEdit_2->document();
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->disasTextEdit_2->clear();
|
|
|
|
//document->undo();
|
|
|
|
ui->disasTextEdit_2->setPlainText(txt);
|
|
|
|
}
|
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
bool MemoryWidget::loadMoreDisassembly()
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
/*
|
2017-10-03 18:38:34 +00:00
|
|
|
* Add more disasm as the user scrolls
|
|
|
|
* Not working properly when scrolling upwards
|
|
|
|
* r2 doesn't handle properly 'pd-' for archs with variable instruction size
|
|
|
|
*/
|
2017-03-29 10:18:37 +00:00
|
|
|
// Disconnect scroll signals to add more content
|
|
|
|
disconnect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
|
|
|
|
|
|
|
|
QScrollBar *sb = this->disasTextEdit->verticalScrollBar();
|
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
bool loaded = false;
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (sb->value() > sb->maximum() - 10)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
//this->main->add_debug_output("End is coming");
|
|
|
|
|
|
|
|
QTextCursor tc = this->disasTextEdit->textCursor();
|
2017-04-09 19:55:06 +00:00
|
|
|
tc.movePosition(QTextCursor::End);
|
2017-07-11 11:05:42 +00:00
|
|
|
RVA offset = readCurrentDisassemblyOffset();
|
|
|
|
|
|
|
|
if (offset != RVA_INVALID)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
core->seek(offset);
|
|
|
|
QString raw = this->core->cmd("pd 200");
|
2017-03-29 10:18:37 +00:00
|
|
|
QString txt = raw.section("\n", 1, -1);
|
|
|
|
//this->disasTextEdit->appendPlainText(" ;\n ; New content here\n ;\n " + txt.trimmed());
|
|
|
|
this->disasTextEdit->appendPlainText(txt.trimmed());
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tc.movePosition(QTextCursor::End);
|
|
|
|
tc.select(QTextCursor::LineUnderCursor);
|
2017-03-29 10:18:37 +00:00
|
|
|
QString lastline = tc.selectedText();
|
2017-10-09 18:08:35 +00:00
|
|
|
//this->main->addDebugOutput("Last line: " + lastline);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-07-11 11:05:42 +00:00
|
|
|
|
|
|
|
loaded = true;
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Code below will be used to append more disasm upwards, one day
|
|
|
|
} /* else if (sb->value() < sb->minimum() + 10) {
|
|
|
|
//this->main->add_debug_output("Begining is coming");
|
|
|
|
|
|
|
|
QTextCursor tc = this->disasTextEdit->textCursor();
|
|
|
|
tc.movePosition( QTextCursor::Start );
|
|
|
|
tc.select( QTextCursor::LineUnderCursor );
|
|
|
|
QString firstline = tc.selectedText();
|
|
|
|
//this->main->add_debug_output("First Line: " + firstline);
|
|
|
|
QString ele = firstline.split(" ", QString::SkipEmptyParts)[0];
|
|
|
|
//this->main->add_debug_output("First Offset: " + ele);
|
|
|
|
if (ele.contains("0x")) {
|
|
|
|
int b = this->disasTextEdit->verticalScrollBar()->maximum();
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->cmd("ss " + ele);
|
|
|
|
this->core->cmd("so -50");
|
|
|
|
QString raw = this->core->cmd("pd 50");
|
2017-03-29 10:18:37 +00:00
|
|
|
//this->main->add_debug_output(raw);
|
|
|
|
//QString txt = raw.section("\n", 1, -1);
|
|
|
|
//this->main->add_debug_output(txt);
|
|
|
|
tc.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
|
|
|
//tc.insertText(raw.trimmed() + "\n ;\n ; New content prepended here\n ;\n");
|
|
|
|
int c = this->disasTextEdit->verticalScrollBar()->maximum();
|
|
|
|
int z = c -b;
|
|
|
|
int a = this->disasTextEdit->verticalScrollBar()->sliderPosition();
|
|
|
|
this->disasTextEdit->verticalScrollBar()->setValue(a + z);
|
|
|
|
} else {
|
|
|
|
tc.movePosition( QTextCursor::Start );
|
|
|
|
tc.select( QTextCursor::LineUnderCursor );
|
|
|
|
QString lastline = tc.selectedText();
|
|
|
|
this->main->add_debug_output("Last line: " + lastline);
|
|
|
|
}
|
|
|
|
} */
|
|
|
|
|
|
|
|
// Reconnect scroll signals
|
|
|
|
connect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
|
2017-07-11 11:05:42 +00:00
|
|
|
|
|
|
|
return loaded;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
|
|
|
|
void MemoryWidget::disasmScrolled()
|
2017-04-09 15:37:54 +00:00
|
|
|
{
|
2017-07-11 11:05:42 +00:00
|
|
|
loadMoreDisassembly();
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
void MemoryWidget::refreshDisasm()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
RCoreLocked lcore = this->core->core();
|
2017-04-28 13:09:40 +00:00
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Prevent further scroll
|
|
|
|
disconnect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
|
2017-04-11 11:41:44 +00:00
|
|
|
disconnect(this->disasTextEdit, SIGNAL(cursorPositionChanged()), this, SLOT(on_disasTextEdit_2_cursorPositionChanged()));
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
RVA offset = next_disasm_top_offset;
|
|
|
|
next_disasm_top_offset = RVA_INVALID;
|
|
|
|
bool offset_changed = offset != RVA_INVALID;
|
|
|
|
|
|
|
|
if (offset_changed) // new offset (seek)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-07-11 11:05:42 +00:00
|
|
|
disasm_top_offset = offset;
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->cmd(QString("s %1").arg(offset));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
2017-07-11 11:05:42 +00:00
|
|
|
else // simple refresh
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
core->cmd(QString("s %1").arg(disasm_top_offset));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
QString txt2 = this->core->cmd("pd 200");
|
2017-07-11 11:05:42 +00:00
|
|
|
|
|
|
|
disasTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
|
|
|
|
|
|
|
// if the offset changed, jump to the top
|
|
|
|
// otherwise try to retain the position
|
|
|
|
int cursor_pos = offset_changed ? 0 : disasTextEdit->textCursor().position();
|
|
|
|
int scroll_pos = offset_changed ? 0 : disasTextEdit->verticalScrollBar()->value();
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
this->disasTextEdit->setPlainText(txt2.trimmed());
|
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
auto cursor = disasTextEdit->textCursor();
|
|
|
|
cursor.setPosition(cursor_pos);
|
|
|
|
disasTextEdit->setTextCursor(cursor);
|
|
|
|
|
|
|
|
disasTextEdit->verticalScrollBar()->setValue(scroll_pos);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
// load more disassembly if necessary
|
|
|
|
static const int load_more_limit = 10; // limit passes, so it can't take forever
|
|
|
|
for (int load_more_i = 0; load_more_i < load_more_limit; load_more_i++)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-07-11 11:05:42 +00:00
|
|
|
if (!loadMoreDisassembly())
|
|
|
|
break;
|
|
|
|
disasTextEdit->verticalScrollBar()->setValue(scroll_pos);
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
connect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
|
2017-04-11 11:41:44 +00:00
|
|
|
connect(this->disasTextEdit, SIGNAL(cursorPositionChanged()), this, SLOT(on_disasTextEdit_2_cursorPositionChanged()));
|
2017-04-12 12:07:43 +00:00
|
|
|
this->on_disasTextEdit_2_cursorPositionChanged();
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::refreshHexdump(const QString &where)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
RCoreLocked lcore = this->core->core();
|
2017-03-29 10:18:37 +00:00
|
|
|
// Prevent further scroll
|
|
|
|
disconnect(this->hexASCIIText->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hexScrolled()));
|
|
|
|
|
|
|
|
// Clear previous content to add new
|
|
|
|
this->hexOffsetText->clear();
|
|
|
|
this->hexHexText->clear();
|
|
|
|
this->hexASCIIText->clear();
|
|
|
|
|
|
|
|
int hexdumpLength;
|
2017-04-09 17:12:36 +00:00
|
|
|
int cols = lcore->print->cols;
|
2017-04-12 20:44:05 +00:00
|
|
|
ut64 bsize = 128 * cols;
|
2017-03-29 10:18:37 +00:00
|
|
|
if (hexdumpBottomOffset < bsize)
|
|
|
|
{
|
|
|
|
hexdumpBottomOffset = 0;
|
|
|
|
hexdumpLength = bsize;//-hexdumpBottomOffset;
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
hexdumpLength = bsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
//int size;
|
2017-10-09 18:08:35 +00:00
|
|
|
//size = core->get_size();
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
QString s = "";
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
if (!where.isEmpty())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->cmd("ss " + where);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-04-12 20:44:05 +00:00
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
// Add first the hexdump at block size --
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->cmd("ss-" + this->core->itoa(hexdumpLength));
|
|
|
|
//s = this->normalize_addr(this->core->cmd("s"));
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> ret = this->get_hexdump("");
|
|
|
|
|
2017-04-09 17:12:36 +00:00
|
|
|
hexdumpBottomOffset = lcore->offset;
|
2017-03-29 10:18:37 +00:00
|
|
|
this->hexOffsetText->setPlainText(ret[0]);
|
|
|
|
this->hexHexText->setPlainText(ret[1]);
|
|
|
|
this->hexASCIIText->setPlainText(ret[2]);
|
|
|
|
this->resizeHexdump();
|
|
|
|
|
|
|
|
// Add then the hexdump at block size ++
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->cmd("ss+" + this->core->itoa(hexdumpLength));
|
2017-03-29 10:18:37 +00:00
|
|
|
// Get address to move cursor to later
|
2017-10-09 18:08:35 +00:00
|
|
|
//QString s = "0x0" + this->core->cmd("s").split("0x")[1].trimmed();
|
|
|
|
s = this->normalize_addr(this->core->cmd("s"));
|
2017-03-29 10:18:37 +00:00
|
|
|
ret = this->get_hexdump("");
|
|
|
|
|
2017-04-09 17:12:36 +00:00
|
|
|
hexdumpBottomOffset = lcore->offset;
|
2017-03-29 10:18:37 +00:00
|
|
|
this->hexOffsetText->append(ret[0]);
|
|
|
|
this->hexHexText->append(ret[1]);
|
|
|
|
this->hexASCIIText->append(ret[2]);
|
|
|
|
this->resizeHexdump();
|
|
|
|
|
|
|
|
// Move cursor to desired address
|
|
|
|
QTextCursor cur = this->hexOffsetText->textCursor();
|
|
|
|
this->hexOffsetText->ensureCursorVisible();
|
|
|
|
this->hexHexText->ensureCursorVisible();
|
|
|
|
this->hexASCIIText->ensureCursorVisible();
|
|
|
|
this->hexOffsetText->moveCursor(QTextCursor::End);
|
|
|
|
this->hexOffsetText->find(s, QTextDocument::FindBackward);
|
|
|
|
this->hexOffsetText->moveCursor(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
|
|
|
|
|
|
|
|
connect(this->hexASCIIText->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hexScrolled()));
|
|
|
|
}
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
QList<QString> MemoryWidget::get_hexdump(const QString &offset)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
RCoreLocked lcore = this->core->core();
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> ret;
|
|
|
|
QString hexdump;
|
|
|
|
|
|
|
|
int hexdumpLength;
|
2017-04-09 17:12:36 +00:00
|
|
|
int cols = lcore->print->cols;
|
2017-04-12 20:44:05 +00:00
|
|
|
ut64 bsize = 128 * cols;
|
2017-03-29 10:18:37 +00:00
|
|
|
if (hexdumpBottomOffset < bsize)
|
|
|
|
{
|
|
|
|
hexdumpBottomOffset = 0;
|
|
|
|
hexdumpLength = bsize;
|
|
|
|
//-hexdumpBottomOffset;
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
hexdumpLength = bsize;
|
|
|
|
}
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
//this->main->add_debug_output("BSize: " + this->core->itoa(hexdumpLength, 10));
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
if (offset.isEmpty())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
hexdump = this->core->cmd("px " + this->core->itoa(hexdumpLength, 10));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
hexdump = this->core->cmd("px " + this->core->itoa(hexdumpLength, 10) + " @ " + offset);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-10-09 18:08:35 +00:00
|
|
|
//QString hexdump = this->core->cmd ("px 0x" + this->core->itoa(size) + " @ 0x0");
|
2017-03-29 10:18:37 +00:00
|
|
|
// TODO: use pxl to simplify
|
2017-04-12 20:44:05 +00:00
|
|
|
QString offsets;
|
|
|
|
QString hex;
|
|
|
|
QString ascii;
|
2017-03-29 10:18:37 +00:00
|
|
|
int ln = 0;
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
for (const QString line : hexdump.split("\n"))
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ln++ == 0)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int wc = 0;
|
|
|
|
for (const QString a : line.split(" "))
|
|
|
|
{
|
|
|
|
switch (wc++)
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
case 0:
|
2017-04-12 20:44:05 +00:00
|
|
|
offsets += a + "\n";
|
2017-04-09 19:55:06 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
hex += a.trimmed() + "\n";
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ascii += a + "\n";
|
2017-03-29 10:18:37 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-12 20:44:05 +00:00
|
|
|
ret << offsets.trimmed();
|
2017-03-29 10:18:37 +00:00
|
|
|
ret << hex.trimmed();
|
|
|
|
ret << ascii.trimmed();
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::seek_to(const QString &offset)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
this->disasTextEdit->moveCursor(QTextCursor::End);
|
2017-04-12 20:44:05 +00:00
|
|
|
this->disasTextEdit->find(offset, QTextDocument::FindBackward);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->disasTextEdit->moveCursor(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::resizeHexdump()
|
|
|
|
{
|
|
|
|
this->hexOffsetText->setMinimumWidth(this->hexOffsetText->document()->size().width());
|
|
|
|
this->hexHexText->setMinimumWidth(this->hexHexText->document()->size().width());
|
|
|
|
this->hexASCIIText->setMinimumWidth(this->hexASCIIText->document()->size().width());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::hexScrolled()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
RCoreLocked lcore = this->core->core();
|
2017-03-29 10:18:37 +00:00
|
|
|
QScrollBar *sb = this->hexASCIIText->verticalScrollBar();
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (sb->value() > sb->maximum() - 10)
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
//this->main->addDebugOutput("End is coming");
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
QTextCursor tc = this->hexOffsetText->textCursor();
|
2017-04-09 19:55:06 +00:00
|
|
|
tc.movePosition(QTextCursor::End);
|
|
|
|
tc.select(QTextCursor::LineUnderCursor);
|
2017-03-29 10:18:37 +00:00
|
|
|
QString lastline = tc.selectedText();
|
|
|
|
//this->main->add_debug_output("Last Offset/VA: " + lastline);
|
|
|
|
//refreshHexdump(2);
|
|
|
|
|
|
|
|
QList<QString> ret = this->get_hexdump(lastline);
|
|
|
|
|
2017-05-13 15:25:36 +00:00
|
|
|
// To prevent recursive calls to hexScrolled (this function) blocks the
|
|
|
|
// scroll bar signals
|
2017-06-03 12:27:23 +00:00
|
|
|
auto appendTextWithoutSignals = [](QTextEdit * edit, const QString & text)
|
2017-05-13 15:25:36 +00:00
|
|
|
{
|
|
|
|
edit->verticalScrollBar()->blockSignals(true);
|
|
|
|
edit->append(text);
|
|
|
|
edit->verticalScrollBar()->blockSignals(false);
|
|
|
|
};
|
|
|
|
|
|
|
|
appendTextWithoutSignals(hexOffsetText, ret[0]);
|
|
|
|
appendTextWithoutSignals(hexHexText, ret[1]);
|
|
|
|
appendTextWithoutSignals(hexASCIIText, ret[2]);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->resizeHexdump();
|
|
|
|
|
|
|
|
// Append more hex text here
|
|
|
|
// ui->disasTextEdit->moveCursor(QTextCursor::Start);
|
|
|
|
// ui->disasTextEdit->insertPlainText(core->cmd("pd@$$-100"));
|
|
|
|
//... same for the other text (offset and hex text edits)
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (sb->value() < sb->minimum() + 10)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
//this->main->add_debug_output("Begining is coming");
|
|
|
|
|
|
|
|
QTextCursor tc = this->hexOffsetText->textCursor();
|
2017-04-09 19:55:06 +00:00
|
|
|
tc.movePosition(QTextCursor::Start);
|
|
|
|
tc.select(QTextCursor::LineUnderCursor);
|
2017-03-29 10:18:37 +00:00
|
|
|
QString firstline = tc.selectedText();
|
|
|
|
//disathis->main->add_debug_output("First Offset/VA: " + firstline);
|
|
|
|
//refreshHexdump(1);
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
//int cols = lcore->print->cols;
|
2017-03-29 10:18:37 +00:00
|
|
|
// px bsize @ addr
|
|
|
|
//int bsize = 128 * cols;
|
|
|
|
int bsize = 800;
|
|
|
|
QString s = QString::number(bsize);
|
|
|
|
// s = 2048.. sigh...
|
2017-10-09 18:08:35 +00:00
|
|
|
QString kk = this->core->cmd("? " + firstline + " - " + s);
|
2017-03-29 10:18:37 +00:00
|
|
|
QString k = kk.split(" ")[1];
|
|
|
|
|
|
|
|
QList<QString> ret = this->get_hexdump(k);
|
|
|
|
|
|
|
|
// Prevent further scroll
|
|
|
|
disconnect(this->hexASCIIText->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hexScrolled()));
|
|
|
|
// Get actual maximum scrolling value
|
|
|
|
int b = this->hexASCIIText->verticalScrollBar()->maximum();
|
|
|
|
|
|
|
|
// Add new offset content
|
|
|
|
QTextDocument *offset_document = this->hexOffsetText->document();
|
|
|
|
QTextCursor offset_cursor(offset_document);
|
|
|
|
offset_cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
|
|
|
offset_cursor.insertText(ret[0] + "\n");
|
|
|
|
|
|
|
|
// Add new hex content
|
|
|
|
QTextDocument *hex_document = this->hexHexText->document();
|
|
|
|
QTextCursor hex_cursor(hex_document);
|
|
|
|
hex_cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
|
|
|
hex_cursor.insertText(ret[1] + "\n");
|
|
|
|
|
|
|
|
// Add new ASCII content
|
|
|
|
QTextDocument *ascii_document = this->hexASCIIText->document();
|
|
|
|
QTextCursor ascii_cursor(ascii_document);
|
|
|
|
ascii_cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
|
|
|
|
ascii_cursor.insertText(ret[2] + "\n");
|
|
|
|
|
|
|
|
// Get new maximum scroll value
|
|
|
|
int c = this->hexASCIIText->verticalScrollBar()->maximum();
|
|
|
|
// Get size of new added content
|
2017-04-09 19:55:06 +00:00
|
|
|
int z = c - b;
|
2017-03-29 10:18:37 +00:00
|
|
|
// Get new slider position
|
|
|
|
int a = this->hexASCIIText->verticalScrollBar()->sliderPosition();
|
|
|
|
// move to previous position
|
|
|
|
this->hexASCIIText->verticalScrollBar()->setValue(a + z);
|
|
|
|
|
|
|
|
this->resizeHexdump();
|
|
|
|
connect(this->hexASCIIText->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(hexScrolled()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_hexHexText_2_selectionChanged()
|
|
|
|
{
|
|
|
|
// Get selected partsing type
|
|
|
|
QString parsing = ui->codeCombo_2->currentText();
|
|
|
|
// Get selected text
|
|
|
|
QTextCursor cursor(this->hexHexText->textCursor());
|
|
|
|
QString sel_text = cursor.selectedText();
|
|
|
|
|
|
|
|
sel_text = sel_text.simplified().remove(" ");
|
|
|
|
//eprintf ("-- (((%s))) --\n", sel_text.toUtf8().constData());
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (sel_text == "")
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText("");
|
|
|
|
ui->bytesEntropy->setText("");
|
|
|
|
ui->bytesMD5->setText("");
|
|
|
|
ui->bytesSHA1->setText("");
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (parsing == "Dissasembly")
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
// Get selected combos
|
|
|
|
QString arch = ui->hexArchComboBox_2->currentText();
|
|
|
|
QString bits = ui->hexBitsComboBox_2->currentText();
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
QString oarch = this->core->getConfig("asm.arch");
|
|
|
|
QString obits = this->core->getConfig("asm.bits");
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("asm.arch", arch);
|
|
|
|
this->core->setConfig("asm.bits", bits);
|
|
|
|
QString str = this->core->cmd("pad " + sel_text);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(str);
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("asm.arch", oarch);
|
|
|
|
this->core->setConfig("asm.bits", obits);
|
2017-03-29 10:18:37 +00:00
|
|
|
//qDebug() << "Selected Arch: " << arch;
|
|
|
|
//qDebug() << "Selected Bits: " << bits;
|
|
|
|
//qDebug() << "Selected Text: " << sel_text;
|
|
|
|
}
|
|
|
|
// TODO: update on selection changes.. use cmd("pc "+len+"@"+off)
|
2017-04-09 19:55:06 +00:00
|
|
|
else if (parsing == "C byte array")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pc@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "C dword array")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pcw@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "C qword array")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pcq@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "Assembler")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pca@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "String")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pcs@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "JSON")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pcj@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "Javascript")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pcJ@x:" + sel_text));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else if (parsing == "Python")
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->hexDisasTextEdit->setPlainText(this->core->cmd("pcp@x:" + sel_text));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fill the information tab hashes and entropy
|
2017-10-09 18:08:35 +00:00
|
|
|
ui->bytesMD5->setText(this->core->cmd("ph md5@x:" + sel_text).trimmed());
|
|
|
|
ui->bytesSHA1->setText(this->core->cmd("ph sha1@x:" + sel_text).trimmed());
|
|
|
|
ui->bytesEntropy->setText(this->core->cmd("ph entropy@x:" + sel_text).trimmed());
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->bytesMD5->setCursorPosition(0);
|
|
|
|
ui->bytesSHA1->setCursorPosition(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::on_hexArchComboBox_2_currentTextChanged(const QString &/*arg1*/)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
on_hexHexText_2_selectionChanged();
|
|
|
|
}
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::on_hexBitsComboBox_2_currentTextChanged(const QString &/*arg1*/)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
on_hexHexText_2_selectionChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Context menu functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
void MemoryWidget::showHexdumpContextMenu(const QPoint &pt)
|
|
|
|
{
|
|
|
|
// Set Hexdump popup menu
|
|
|
|
QMenu *menu = ui->hexHexText_2->createStandardContextMenu();
|
|
|
|
menu->clear();
|
|
|
|
menu->addAction(ui->actionHexCopy_Hexpair);
|
|
|
|
menu->addAction(ui->actionHexCopy_ASCII);
|
|
|
|
menu->addAction(ui->actionHexCopy_Text);
|
|
|
|
menu->addSeparator();
|
2017-04-09 19:55:06 +00:00
|
|
|
QMenu *colSubmenu = menu->addMenu("Columns");
|
2017-03-29 10:18:37 +00:00
|
|
|
colSubmenu->addAction(ui->action4columns);
|
|
|
|
colSubmenu->addAction(ui->action8columns);
|
|
|
|
colSubmenu->addAction(ui->action16columns);
|
|
|
|
colSubmenu->addAction(ui->action32columns);
|
|
|
|
menu->addSeparator();
|
|
|
|
menu->addAction(ui->actionHexEdit);
|
|
|
|
menu->addAction(ui->actionHexPaste);
|
|
|
|
menu->addSeparator();
|
|
|
|
menu->addAction(ui->actionHexInsert_Hex);
|
|
|
|
menu->addAction(ui->actionHexInsert_String);
|
|
|
|
|
|
|
|
ui->hexHexText_2->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
|
|
|
|
menu->exec(ui->hexHexText_2->mapToGlobal(pt));
|
|
|
|
delete menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::showHexASCIIContextMenu(const QPoint &pt)
|
|
|
|
{
|
|
|
|
// Set Hex ASCII popup menu
|
|
|
|
QMenu *menu = ui->hexASCIIText_2->createStandardContextMenu();
|
|
|
|
menu->clear();
|
|
|
|
menu->addAction(ui->actionHexCopy_Hexpair);
|
|
|
|
menu->addAction(ui->actionHexCopy_ASCII);
|
|
|
|
menu->addAction(ui->actionHexCopy_Text);
|
|
|
|
menu->addSeparator();
|
2017-04-09 19:55:06 +00:00
|
|
|
QMenu *colSubmenu = menu->addMenu("Columns");
|
2017-03-29 10:18:37 +00:00
|
|
|
colSubmenu->addAction(ui->action4columns);
|
|
|
|
colSubmenu->addAction(ui->action8columns);
|
|
|
|
colSubmenu->addAction(ui->action16columns);
|
|
|
|
colSubmenu->addAction(ui->action32columns);
|
|
|
|
menu->addSeparator();
|
|
|
|
menu->addAction(ui->actionHexEdit);
|
|
|
|
menu->addAction(ui->actionHexPaste);
|
|
|
|
menu->addSeparator();
|
|
|
|
menu->addAction(ui->actionHexInsert_Hex);
|
|
|
|
menu->addAction(ui->actionHexInsert_String);
|
|
|
|
|
|
|
|
ui->hexASCIIText_2->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
|
|
|
|
|
|
menu->exec(ui->hexASCIIText_2->mapToGlobal(pt));
|
|
|
|
delete menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::showDisasContextMenu(const QPoint &pt)
|
|
|
|
{
|
2017-10-10 10:17:05 +00:00
|
|
|
DisassemblyContextMenu menu(this->readCurrentDisassemblyOffset(), ui->disasTextEdit_2);
|
|
|
|
menu.exec(ui->disasTextEdit_2->mapToGlobal(pt));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_showInfoButton_2_clicked()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->showInfoButton_2->isChecked())
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->fcnGraphTabWidget->hide();
|
|
|
|
ui->showInfoButton_2->setArrowType(Qt::RightArrow);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->fcnGraphTabWidget->show();
|
|
|
|
ui->showInfoButton_2->setArrowType(Qt::DownArrow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_offsetToolButton_clicked()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->offsetToolButton->isChecked())
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->offsetTreeWidget->hide();
|
|
|
|
ui->offsetToolButton->setArrowType(Qt::RightArrow);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->offsetTreeWidget->show();
|
|
|
|
ui->offsetToolButton->setArrowType(Qt::DownArrow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-08 22:40:43 +00:00
|
|
|
void MemoryWidget::showXrefsDialog()
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-06-08 22:40:43 +00:00
|
|
|
// Get current offset
|
|
|
|
QTextCursor tc = this->disasTextEdit->textCursor();
|
|
|
|
tc.select(QTextCursor::LineUnderCursor);
|
|
|
|
QString lastline = tc.selectedText();
|
|
|
|
QString ele = lastline.split(" ", QString::SkipEmptyParts)[0];
|
|
|
|
if (ele.contains("0x"))
|
|
|
|
{
|
2017-10-10 10:17:05 +00:00
|
|
|
RVA addr = ele.toLongLong(0, 16);
|
|
|
|
XrefsDialog *x = new XrefsDialog(this);
|
2017-06-08 22:40:43 +00:00
|
|
|
x->fillRefsForAddress(addr, RAddressString(addr), false);
|
|
|
|
x->exec();
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-06-08 22:40:43 +00:00
|
|
|
/*
|
|
|
|
* Show widgets
|
|
|
|
*/
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::cycleViews()
|
|
|
|
{
|
2017-06-08 22:40:43 +00:00
|
|
|
switch (ui->memTabWidget->currentIndex())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-06-08 22:40:43 +00:00
|
|
|
case 0:
|
|
|
|
// Show hexdump
|
2017-10-01 22:25:33 +00:00
|
|
|
ui->hexButton->setChecked(true);
|
|
|
|
on_hexButton_clicked();
|
2017-06-08 22:40:43 +00:00
|
|
|
break;
|
2017-10-11 11:22:30 +00:00
|
|
|
case 1:
|
2017-03-29 10:18:37 +00:00
|
|
|
// Show disasm
|
2017-10-01 22:25:33 +00:00
|
|
|
ui->disasButton->setChecked(true);
|
|
|
|
on_disasButton_clicked();
|
2017-06-08 22:40:43 +00:00
|
|
|
break;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Actions callback functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
void MemoryWidget::on_actionSettings_menu_1_triggered()
|
|
|
|
{
|
|
|
|
bool ok = true;
|
|
|
|
|
2017-04-09 17:09:52 +00:00
|
|
|
// QFont font = QFont("Monospace", 8);
|
2017-09-28 21:53:59 +00:00
|
|
|
// TODO Use global configuration
|
2017-04-09 19:55:06 +00:00
|
|
|
QFont font = QFontDialog::getFont(&ok, ui->disasTextEdit_2->font(), this);
|
2017-04-13 15:14:02 +00:00
|
|
|
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
setFonts(font);
|
|
|
|
|
|
|
|
emit fontChanged(font);
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::setFonts(QFont font)
|
|
|
|
{
|
|
|
|
ui->disasTextEdit_2->setFont(font);
|
2017-03-29 10:18:37 +00:00
|
|
|
// the user clicked OK and font is set to the font the user selected
|
|
|
|
ui->disasTextEdit_2->setFont(font);
|
|
|
|
ui->hexOffsetText_2->setFont(font);
|
|
|
|
ui->hexHexText_2->setFont(font);
|
|
|
|
ui->hexASCIIText_2->setFont(font);
|
|
|
|
ui->previewTextEdit->setFont(font);
|
|
|
|
ui->decoTextEdit->setFont(font);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_actionHideDisasm_side_panel_triggered()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->memSideTabWidget_2->isVisible())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->memSideTabWidget_2->hide();
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->memSideTabWidget_2->show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_actionHideHexdump_side_panel_triggered()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->hexSideTab_2->isVisible())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hexSideTab_2->hide();
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hexSideTab_2->show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_actionHideGraph_side_panel_triggered()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->graphTreeWidget_2->isVisible())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->graphTreeWidget_2->hide();
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->graphTreeWidget_2->show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Buttons callback functions
|
|
|
|
*/
|
|
|
|
|
2017-10-01 22:25:33 +00:00
|
|
|
void MemoryWidget::on_disasButton_clicked()
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->memTabWidget->setCurrentIndex(0);
|
|
|
|
ui->memSideTabWidget_2->setCurrentIndex(0);
|
|
|
|
}
|
|
|
|
|
2017-10-11 11:22:30 +00:00
|
|
|
void MemoryWidget::on_hexButton_clicked()
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->memTabWidget->setCurrentIndex(1);
|
|
|
|
ui->memSideTabWidget_2->setCurrentIndex(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_actionSend_to_Notepad_triggered()
|
|
|
|
{
|
|
|
|
QTextCursor cursor = ui->disasTextEdit_2->textCursor();
|
|
|
|
QString text = cursor.selectedText();
|
2017-10-09 18:08:35 +00:00
|
|
|
// TODO
|
|
|
|
// this->main->sendToNotepad(text);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action8columns_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 8);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action16columns_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 16);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action4columns_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 4);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action32columns_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 32);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action64columns_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 64);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action2columns_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 2);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_action1column_triggered()
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->setConfig("hex.cols", 1);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->refreshHexdump();
|
|
|
|
}
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::on_xreFromTreeWidget_2_itemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->seek(xref.to);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::on_xrefToTreeWidget_2_itemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->seek(xref.from);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_xrefFromToolButton_2_clicked()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->xrefFromToolButton_2->isChecked())
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->xreFromTreeWidget_2->hide();
|
|
|
|
ui->xrefFromToolButton_2->setArrowType(Qt::RightArrow);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->xreFromTreeWidget_2->show();
|
|
|
|
ui->xrefFromToolButton_2->setArrowType(Qt::DownArrow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_xrefToToolButton_2_clicked()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->xrefToToolButton_2->isChecked())
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
ui->xrefToTreeWidget_2->hide();
|
|
|
|
ui->xrefToToolButton_2->setArrowType(Qt::RightArrow);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->xrefToTreeWidget_2->show();
|
|
|
|
ui->xrefToToolButton_2->setArrowType(Qt::DownArrow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_codeCombo_2_currentTextChanged(const QString &arg1)
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (arg1 == "Dissasembly")
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hexSideFrame_2->show();
|
|
|
|
ui->hexDisasTextEdit_2->setPlainText(";; Select some bytes on the left\n;; to see them disassembled");
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->hexSideFrame_2->hide();
|
|
|
|
ui->hexDisasTextEdit_2->setPlainText(";; Select some bytes on the left\n;; to see them parsed here");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
void MemoryWidget::get_refs_data(RVA addr)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
// refs = calls q hace esa funcion
|
2017-10-09 18:08:35 +00:00
|
|
|
QList<XrefDescription> refs = core->getXRefs(addr, false, false);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// xrefs = calls a esa funcion
|
2017-10-09 18:08:35 +00:00
|
|
|
QList<XrefDescription> xrefs = core->getXRefs(addr, true, false);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Data for the disasm side graph
|
|
|
|
QList<int> data;
|
|
|
|
//qDebug() << "Refs:" << refs.size();
|
|
|
|
data << refs.size();
|
|
|
|
//qDebug() << "XRefs:" << xrefs.size();
|
|
|
|
data << xrefs.size();
|
2017-10-09 18:08:35 +00:00
|
|
|
//qDebug() << "CC: " << this->core->fcnCyclomaticComplexity(offset.toLong(&ok, 16));
|
|
|
|
//data << this->core->fcnCyclomaticComplexity(offset.toLong(&ok, 16));
|
|
|
|
data << this->core->getCycloComplex(addr);
|
|
|
|
//qDebug() << "BB: " << this->core->fcnBasicBlockCount(offset.toLong(&ok, 16));
|
|
|
|
data << this->core->fcnBasicBlockCount(addr);
|
|
|
|
data << this->core->fcnEndBbs(addr);
|
|
|
|
//qDebug() << "MEOW: " + this->core->fcnEndBbs(offset);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
// Update disasm side bar
|
2017-06-07 19:35:38 +00:00
|
|
|
this->fill_refs(refs, xrefs, data);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-06-07 19:35:38 +00:00
|
|
|
void MemoryWidget::fill_refs(QList<XrefDescription> refs, QList<XrefDescription> xrefs, QList<int> graph_data)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
this->xreFromTreeWidget_2->clear();
|
2017-04-09 19:55:06 +00:00
|
|
|
for (int i = 0; i < refs.size(); ++i)
|
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = refs[i];
|
2017-03-29 10:18:37 +00:00
|
|
|
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
2017-06-07 19:35:38 +00:00
|
|
|
tempItem->setText(0, RAddressString(xref.to));
|
2017-10-09 18:08:35 +00:00
|
|
|
tempItem->setText(1, core->disassembleSingleInstruction(xref.from));
|
2017-06-07 19:35:38 +00:00
|
|
|
tempItem->setData(0, Qt::UserRole, QVariant::fromValue(xref));
|
2017-10-09 18:08:35 +00:00
|
|
|
QString tooltip = this->core->cmd("pdi 10 @ " + QString::number(xref.to)).trimmed();
|
2017-06-07 19:35:38 +00:00
|
|
|
tempItem->setToolTip(0, tooltip);
|
|
|
|
tempItem->setToolTip(1, tooltip);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->xreFromTreeWidget_2->insertTopLevelItem(0, tempItem);
|
|
|
|
}
|
|
|
|
// Adjust columns to content
|
|
|
|
int count = this->xreFromTreeWidget_2->columnCount();
|
2017-04-09 19:55:06 +00:00
|
|
|
for (int i = 0; i != count; ++i)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
this->xreFromTreeWidget_2->resizeColumnToContents(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->xrefToTreeWidget_2->clear();
|
2017-04-09 19:55:06 +00:00
|
|
|
for (int i = 0; i < xrefs.size(); ++i)
|
|
|
|
{
|
2017-06-07 19:35:38 +00:00
|
|
|
XrefDescription xref = xrefs[i];
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
2017-06-07 19:35:38 +00:00
|
|
|
tempItem->setText(0, RAddressString(xref.from));
|
2017-10-09 18:08:35 +00:00
|
|
|
tempItem->setText(1, core->disassembleSingleInstruction(xref.from));
|
2017-06-07 19:35:38 +00:00
|
|
|
tempItem->setData(0, Qt::UserRole, QVariant::fromValue(xref));
|
2017-10-09 18:08:35 +00:00
|
|
|
QString tooltip = this->core->cmd("pdi 10 @ " + QString::number(xref.from)).trimmed();
|
|
|
|
tempItem->setToolTip(0, this->core->cmd("pdi 10 @ " + tooltip).trimmed());
|
|
|
|
tempItem->setToolTip(1, this->core->cmd("pdi 10 @ " + tooltip).trimmed());
|
2017-03-29 10:18:37 +00:00
|
|
|
this->xrefToTreeWidget_2->insertTopLevelItem(0, tempItem);
|
|
|
|
}
|
|
|
|
// Adjust columns to content
|
|
|
|
int count2 = this->xrefToTreeWidget_2->columnCount();
|
2017-04-09 19:55:06 +00:00
|
|
|
for (int i = 0; i != count2; ++i)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
this->xrefToTreeWidget_2->resizeColumnToContents(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add data to HTML Polar functions graph
|
|
|
|
QFile html(":/html/fcn_graph.html");
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!html.open(QIODevice::ReadOnly))
|
|
|
|
{
|
2017-04-09 20:36:17 +00:00
|
|
|
QMessageBox::information(this, "error", html.errorString());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
QString code = html.readAll();
|
|
|
|
html.close();
|
|
|
|
|
|
|
|
QString data = QString("\"%1\", \"%2\", \"%3\", \"%4\", \"%5\"").arg(graph_data.at(2)).arg(graph_data.at(0)).arg(graph_data.at(3)).arg(graph_data.at(1)).arg(graph_data.at(4));
|
|
|
|
code.replace("MEOW", data);
|
|
|
|
ui->fcnWebView->setHtml(code);
|
|
|
|
|
|
|
|
// Add data to HTML Radar functions graph
|
|
|
|
QFile html2(":/html/fcn_radar.html");
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!html2.open(QIODevice::ReadOnly))
|
|
|
|
{
|
2017-04-09 20:36:17 +00:00
|
|
|
QMessageBox::information(this, "error", html.errorString());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
QString code2 = html2.readAll();
|
|
|
|
html2.close();
|
|
|
|
|
|
|
|
QString data2 = QString("%1, %2, %3, %4, %5").arg(graph_data.at(2)).arg(graph_data.at(0)).arg(graph_data.at(3)).arg(graph_data.at(1)).arg(graph_data.at(4));
|
|
|
|
code2.replace("MEOW", data2);
|
|
|
|
ui->radarGraphWebView->setHtml(code2);
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::fillOffsetInfo(QString off)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->offsetTreeWidget->clear();
|
2017-10-09 18:08:35 +00:00
|
|
|
QString raw = this->core->getOffsetInfo(off);
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> lines = raw.split("\n", QString::SkipEmptyParts);
|
2017-04-09 19:55:06 +00:00
|
|
|
foreach (QString line, lines)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QList<QString> eles = line.split(":", QString::SkipEmptyParts);
|
|
|
|
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
|
|
|
|
tempItem->setText(0, eles.at(0).toUpper());
|
|
|
|
tempItem->setText(1, eles.at(1));
|
|
|
|
ui->offsetTreeWidget->insertTopLevelItem(0, tempItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adjust column to contents
|
|
|
|
int count = ui->offsetTreeWidget->columnCount();
|
2017-04-09 19:55:06 +00:00
|
|
|
for (int i = 0; i != count; ++i)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->offsetTreeWidget->resizeColumnToContents(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add opcode description
|
2017-10-09 18:08:35 +00:00
|
|
|
QStringList description = this->core->cmd("?d. @ " + off).split(": ");
|
2017-04-09 19:55:06 +00:00
|
|
|
if (description.length() >= 2)
|
|
|
|
{
|
2017-03-30 02:49:04 +00:00
|
|
|
ui->opcodeDescText->setPlainText("# " + description[0] + ":\n" + description[1]);
|
|
|
|
}
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
QString MemoryWidget::normalize_addr(QString addr)
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
QString base = this->core->cmd("s").split("0x")[1].trimmed();
|
2017-03-29 10:18:37 +00:00
|
|
|
int len = base.length();
|
2017-04-09 19:55:06 +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);
|
|
|
|
QString s = "0x" + zeroes + base;
|
|
|
|
return s;
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-04-24 06:49:35 +00:00
|
|
|
return addr.trimmed();
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-28 13:09:40 +00:00
|
|
|
void MemoryWidget::setFcnName(RVA addr)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-28 13:09:40 +00:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
QString addr_string;
|
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
fcn = this->core->functionAt(addr);
|
2017-04-28 13:38:01 +00:00
|
|
|
if (fcn)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
QString segment = this->core->cmd("S. @ " + QString::number(addr)).split(" ").last();
|
2017-04-28 13:09:40 +00:00
|
|
|
addr_string = segment.trimmed() + ":" + fcn->name;
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
2017-04-28 13:09:40 +00:00
|
|
|
else
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
addr_string = core->cmdFunctionAt(addr);
|
2017-04-28 13:09:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ui->fcnNameEdit->setText(addr_string);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_disasTextEdit_2_cursorPositionChanged()
|
|
|
|
{
|
|
|
|
// Get current offset
|
|
|
|
QTextCursor tc = this->disasTextEdit->textCursor();
|
2017-04-09 19:55:06 +00:00
|
|
|
tc.select(QTextCursor::LineUnderCursor);
|
2017-03-29 10:18:37 +00:00
|
|
|
QString lastline = tc.selectedText().trimmed();
|
2017-04-28 10:47:55 +00:00
|
|
|
QList<QString> words = lastline.split(" ", QString::SkipEmptyParts);
|
2017-06-03 12:27:23 +00:00
|
|
|
if (words.length() == 0)
|
|
|
|
{
|
2017-04-28 10:47:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
QString ele = words[0];
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ele.contains("0x"))
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
this->fillOffsetInfo(ele);
|
2017-10-09 18:08:35 +00:00
|
|
|
QString at = this->core->cmdFunctionAt(ele);
|
|
|
|
QString deco = this->core->getDecompiledCode(at);
|
2017-03-29 10:18:37 +00:00
|
|
|
|
2017-04-28 13:09:40 +00:00
|
|
|
|
|
|
|
RVA addr = ele.midRef(2).toULongLong(0, 16);
|
2017-10-09 18:08:35 +00:00
|
|
|
// FIXME per widget CursorAddress no?
|
|
|
|
// this->main->setCursorAddress(addr);
|
2017-04-28 13:09:40 +00:00
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
if (deco != "")
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->decoTextEdit->setPlainText(deco);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->decoTextEdit->setPlainText("");
|
|
|
|
}
|
|
|
|
// Get jump information to fill the preview
|
2017-10-09 18:08:35 +00:00
|
|
|
QString jump = this->core->getOffsetJump(ele);
|
2017-04-12 20:44:05 +00:00
|
|
|
if (!jump.isEmpty())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
// Fill the preview
|
2017-10-09 18:08:35 +00:00
|
|
|
QString jump_code = this->core->cmd("pdf @ " + jump);
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->previewTextEdit->setPlainText(jump_code.trimmed());
|
|
|
|
ui->previewTextEdit->moveCursor(QTextCursor::End);
|
2017-04-12 20:44:05 +00:00
|
|
|
ui->previewTextEdit->find(jump.trimmed(), QTextDocument::FindBackward);
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->previewTextEdit->moveCursor(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->previewTextEdit->setPlainText("");
|
|
|
|
}
|
|
|
|
//this->main->add_debug_output("Fcn at: '" + at + "'");
|
2017-04-09 19:55:06 +00:00
|
|
|
if (this->last_fcn != at)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
this->last_fcn = at;
|
|
|
|
//this->main->add_debug_output("New Fcn: '" + this->last_fcn + "'");
|
|
|
|
// Refresh function information at sidebar
|
|
|
|
ui->fcnNameEdit->setText(at);
|
2017-10-09 18:08:35 +00:00
|
|
|
// FIXME TITLE?
|
|
|
|
// this->main->memoryDock->setWindowTitle(at);
|
2017-04-11 11:41:44 +00:00
|
|
|
//this->main->memoryDock->create_graph(ele);
|
2017-03-29 10:18:37 +00:00
|
|
|
this->setMiniGraph(at);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
QString MemoryWidget::normalizeAddr(QString addr)
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
QString base = addr.split("0x")[1].trimmed();
|
|
|
|
int len = base.length();
|
2017-04-09 19:55:06 +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);
|
|
|
|
QString s = "0x" + zeroes + base;
|
|
|
|
return s;
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::setMiniGraph(QString at)
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
QString dot = this->core->getSimpleGraph(at);
|
|
|
|
//QString dot = this->core->cmd("agc " + at);
|
2017-03-29 10:18:37 +00:00
|
|
|
// Add data to HTML Polar functions graph
|
|
|
|
QFile html(":/html/graph.html");
|
2017-04-09 19:55:06 +00:00
|
|
|
if (!html.open(QIODevice::ReadOnly))
|
|
|
|
{
|
2017-04-09 20:36:17 +00:00
|
|
|
QMessageBox::information(this, "error", html.errorString());
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
QString code = html.readAll();
|
|
|
|
html.close();
|
|
|
|
|
|
|
|
code.replace("MEOW", dot);
|
|
|
|
ui->webSimpleGraph->setHtml(code);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_polarToolButton_clicked()
|
|
|
|
{
|
|
|
|
ui->radarToolButton->setChecked(false);
|
|
|
|
ui->fcnGraphTabWidget->setCurrentIndex(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_radarToolButton_clicked()
|
|
|
|
{
|
|
|
|
ui->polarToolButton->setChecked(false);
|
|
|
|
ui->fcnGraphTabWidget->setCurrentIndex(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::on_hexSideTab_2_currentChanged(int /*index*/)
|
2017-03-29 10:18:37 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
if (index == 2) {
|
|
|
|
// Add data to HTML Polar functions graph
|
|
|
|
QFile html(":/html/bar.html");
|
|
|
|
if(!html.open(QIODevice::ReadOnly)) {
|
|
|
|
QMessageBox::information(0,"error",html.errorString());
|
|
|
|
}
|
|
|
|
QString code = html.readAll();
|
|
|
|
html.close();
|
|
|
|
this->histoWebView->setHtml(code);
|
|
|
|
this->histoWebView->show();
|
|
|
|
} else {
|
|
|
|
this->histoWebView->hide();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_memSideToolButton_clicked()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->memSideToolButton->isChecked())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->memSideTabWidget_2->hide();
|
|
|
|
ui->hexSideTab_2->hide();
|
2017-06-15 09:53:10 +00:00
|
|
|
ui->memSideToolButton->setIcon(QIcon(":/img/icons/left_light.svg"));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->memSideTabWidget_2->show();
|
|
|
|
ui->hexSideTab_2->show();
|
2017-06-15 09:53:10 +00:00
|
|
|
ui->memSideToolButton->setIcon(QIcon(":/img/icons/right_light.svg"));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_previewToolButton_clicked()
|
|
|
|
{
|
|
|
|
ui->memPreviewTab->setCurrentIndex(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_decoToolButton_clicked()
|
|
|
|
{
|
|
|
|
ui->memPreviewTab->setCurrentIndex(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_simpleGrapgToolButton_clicked()
|
|
|
|
{
|
|
|
|
ui->memPreviewTab->setCurrentIndex(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_previewToolButton_2_clicked()
|
|
|
|
{
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->previewToolButton_2->isChecked())
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->frame_3->setVisible(true);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-29 10:18:37 +00:00
|
|
|
ui->frame_3->setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-10 10:25:33 +00:00
|
|
|
void MemoryWidget::resizeEvent(QResizeEvent *event)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
// FIXME
|
|
|
|
/*
|
2017-04-13 15:51:58 +00:00
|
|
|
if (main->responsive && isVisible())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-10 10:25:33 +00:00
|
|
|
if (event->size().width() <= 1150)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-10 10:25:33 +00:00
|
|
|
ui->frame_3->setVisible(false);
|
|
|
|
ui->memPreviewTab->setVisible(false);
|
|
|
|
ui->previewToolButton_2->setChecked(false);
|
|
|
|
if (event->size().width() <= 950)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-04-10 10:25:33 +00:00
|
|
|
ui->memSideTabWidget_2->hide();
|
|
|
|
ui->hexSideTab_2->hide();
|
|
|
|
ui->memSideToolButton->setChecked(true);
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-04-10 10:25:33 +00:00
|
|
|
ui->memSideTabWidget_2->show();
|
|
|
|
ui->hexSideTab_2->show();
|
|
|
|
ui->memSideToolButton->setChecked(false);
|
2017-04-09 17:09:52 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-10 10:25:33 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
ui->frame_3->setVisible(true);
|
|
|
|
ui->memPreviewTab->setVisible(true);
|
|
|
|
ui->previewToolButton_2->setChecked(true);
|
|
|
|
}
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
2017-10-09 18:08:35 +00:00
|
|
|
*/
|
2017-04-10 10:25:33 +00:00
|
|
|
QDockWidget::resizeEvent(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemoryWidget::eventFilter(QObject *obj, QEvent *event)
|
|
|
|
{
|
|
|
|
if ((obj == ui->disasTextEdit_2 || obj == ui->disasTextEdit_2->viewport()) && event->type() == QEvent::MouseButtonDblClick)
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
|
|
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
2017-04-11 11:41:44 +00:00
|
|
|
//qDebug()<<QString("Click location: (%1,%2)").arg(mouseEvent->x()).arg(mouseEvent->y());
|
2017-04-09 19:55:06 +00:00
|
|
|
QTextCursor cursor = ui->disasTextEdit_2->cursorForPosition(QPoint(mouseEvent->x(), mouseEvent->y()));
|
|
|
|
cursor.select(QTextCursor::LineUnderCursor);
|
2017-04-09 17:09:52 +00:00
|
|
|
QString lastline = cursor.selectedText();
|
2017-04-10 12:12:42 +00:00
|
|
|
auto eles = lastline.split(" ", QString::SkipEmptyParts);
|
|
|
|
QString ele = eles.isEmpty() ? "" : eles[0];
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ele.contains("0x"))
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
QString jump = this->core->getOffsetJump(ele);
|
2017-04-13 15:01:18 +00:00
|
|
|
if (!jump.isEmpty())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
|
|
|
if (jump.contains("0x"))
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
QString fcn = this->core->cmdFunctionAt(jump);
|
2017-04-13 15:01:18 +00:00
|
|
|
if (!fcn.isEmpty())
|
2017-04-09 19:55:06 +00:00
|
|
|
{
|
2017-10-03 18:38:34 +00:00
|
|
|
RVA addr = jump.trimmed().toULongLong(0, 16);
|
2017-10-09 18:08:35 +00:00
|
|
|
this->core->seek(addr);
|
2017-04-09 17:09:52 +00:00
|
|
|
}
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-10-09 18:08:35 +00:00
|
|
|
RVA addr = this->core->cmd("?v " + jump).toULongLong(0, 16);
|
|
|
|
this->core->seek(addr);
|
2017-04-09 17:09:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QDockWidget::eventFilter(obj, event);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-04-13 15:14:02 +00:00
|
|
|
void MemoryWidget::setScrollMode()
|
|
|
|
{
|
|
|
|
qhelpers::setVerticalScrollMode(ui->xreFromTreeWidget_2);
|
|
|
|
qhelpers::setVerticalScrollMode(ui->xrefToTreeWidget_2);
|
|
|
|
}
|
|
|
|
|
2017-03-29 10:18:37 +00:00
|
|
|
|
|
|
|
void MemoryWidget::on_copyMD5_clicked()
|
|
|
|
{
|
|
|
|
QString md5 = ui->bytesMD5->text();
|
|
|
|
QClipboard *clipboard = QApplication::clipboard();
|
|
|
|
clipboard->setText(md5);
|
2017-10-09 18:08:35 +00:00
|
|
|
// FIXME
|
|
|
|
// this->main->addOutput("MD5 copied to clipboard: " + md5);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MemoryWidget::on_copySHA1_clicked()
|
|
|
|
{
|
|
|
|
QString sha1 = ui->bytesSHA1->text();
|
|
|
|
QClipboard *clipboard = QApplication::clipboard();
|
|
|
|
clipboard->setText(sha1);
|
2017-10-09 18:08:35 +00:00
|
|
|
// FIXME
|
|
|
|
// this->main->addOutput("SHA1 copied to clipboard: " + sha1);
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::switchTheme(bool dark)
|
|
|
|
{
|
|
|
|
if (dark)
|
|
|
|
{
|
2017-04-12 17:06:29 +00:00
|
|
|
ui->webSimpleGraph->page()->setBackgroundColor(QColor(64, 64, 64));
|
2017-04-09 19:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-04-12 17:06:29 +00:00
|
|
|
ui->webSimpleGraph->page()->setBackgroundColor(QColor(255, 255, 255));
|
2017-03-29 10:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::selectHexPreview()
|
|
|
|
{
|
2017-03-30 09:27:43 +00:00
|
|
|
// Pre-select arch and bits in the hexdump sidebar
|
2017-10-09 18:08:35 +00:00
|
|
|
QString arch = this->core->cmd("e asm.arch").trimmed();
|
|
|
|
QString bits = this->core->cmd("e asm.bits").trimmed();
|
2017-03-30 09:27:43 +00:00
|
|
|
|
|
|
|
//int arch_index = ui->hexArchComboBox_2->findText(arch);
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->hexArchComboBox_2->findText(arch) != -1)
|
|
|
|
{
|
2017-03-30 09:27:43 +00:00
|
|
|
ui->hexArchComboBox_2->setCurrentIndex(ui->hexArchComboBox_2->findText(arch));
|
|
|
|
}
|
|
|
|
|
|
|
|
//int bits_index = ui->hexBitsComboBox_2->findText(bits);
|
2017-04-09 19:55:06 +00:00
|
|
|
if (ui->hexBitsComboBox_2->findText(bits) != -1)
|
|
|
|
{
|
2017-03-30 09:27:43 +00:00
|
|
|
ui->hexBitsComboBox_2->setCurrentIndex(ui->hexBitsComboBox_2->findText(bits));
|
|
|
|
}
|
|
|
|
}
|
2017-04-05 09:35:19 +00:00
|
|
|
|
2017-04-09 19:55:06 +00:00
|
|
|
void MemoryWidget::seek_back()
|
|
|
|
{
|
2017-04-05 09:35:19 +00:00
|
|
|
//this->main->add_debug_output("Back!");
|
2017-10-09 18:08:35 +00:00
|
|
|
// FIXME
|
|
|
|
// this->main->backButton_clicked();
|
2017-04-05 09:35:19 +00:00
|
|
|
}
|
2017-04-05 14:03:36 +00:00
|
|
|
|
2017-04-12 20:44:05 +00:00
|
|
|
void MemoryWidget::on_memTabWidget_currentChanged(int /*index*/)
|
2017-04-11 11:41:44 +00:00
|
|
|
{
|
2017-04-28 13:09:40 +00:00
|
|
|
/*this->main->add_debug_output("Update index: " + QString::number(index) + " to function: " + RAddressString(main->getCursorAddress()));
|
|
|
|
this->main->add_debug_output("Last disasm: " + RAddressString(this->last_disasm_fcn));
|
|
|
|
this->main->add_debug_output("Last graph: " + RAddressString(this->last_graph_fcn));
|
|
|
|
this->main->add_debug_output("Last hexdump: " + RAddressString(this->last_hexdump_fcn));*/
|
2017-10-03 18:38:34 +00:00
|
|
|
this->updateViews(RVA_INVALID);
|
2017-04-11 11:41:44 +00:00
|
|
|
}
|
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
void MemoryWidget::updateViews(RVA offset)
|
2017-04-13 15:51:58 +00:00
|
|
|
{
|
2017-04-11 11:41:44 +00:00
|
|
|
// Update only the selected view to improve performance
|
|
|
|
|
|
|
|
int index = ui->memTabWidget->tabBar()->currentIndex();
|
2017-04-28 13:09:40 +00:00
|
|
|
|
2017-10-09 18:08:35 +00:00
|
|
|
// Anyway updateViews will die after break this widget.
|
|
|
|
// FIXME? One cursor per widget ? (if not synced)
|
|
|
|
// RVA cursor_addr = main->getCursorAddress();
|
|
|
|
// QString cursor_addr_string = RAddressString(cursor_addr);
|
|
|
|
QString cursor_addr_string = core->cmd("s");
|
|
|
|
RVA cursor_addr = cursor_addr_string.toULongLong();
|
2017-04-28 13:09:40 +00:00
|
|
|
|
2017-07-11 11:05:42 +00:00
|
|
|
if (offset != RVA_INVALID)
|
|
|
|
next_disasm_top_offset = offset;
|
|
|
|
|
2017-04-13 15:51:58 +00:00
|
|
|
if (index == 0)
|
|
|
|
{
|
2017-04-11 11:41:44 +00:00
|
|
|
// Disasm
|
2017-07-11 11:05:42 +00:00
|
|
|
this->refreshDisasm();
|
2017-04-13 15:51:58 +00:00
|
|
|
}
|
|
|
|
else if (index == 1)
|
|
|
|
{
|
2017-04-11 11:41:44 +00:00
|
|
|
// Hex
|
2017-04-28 13:09:40 +00:00
|
|
|
if (this->last_hexdump_fcn != cursor_addr)
|
2017-04-13 15:51:58 +00:00
|
|
|
{
|
2017-04-28 13:09:40 +00:00
|
|
|
this->refreshHexdump(cursor_addr_string);
|
|
|
|
this->last_hexdump_fcn = cursor_addr;
|
2017-04-11 11:41:44 +00:00
|
|
|
}
|
2017-04-13 15:51:58 +00:00
|
|
|
}
|
2017-10-01 22:25:33 +00:00
|
|
|
// TODO WTF
|
2017-04-11 11:41:44 +00:00
|
|
|
}
|
2017-09-01 13:03:35 +00:00
|
|
|
|
2017-09-27 20:23:18 +00:00
|
|
|
void MemoryWidget::showOffsets(bool show)
|
|
|
|
{
|
|
|
|
if (show)
|
|
|
|
{
|
2017-09-01 13:03:35 +00:00
|
|
|
this->hexOffsetText->show();
|
2017-10-09 18:08:35 +00:00
|
|
|
core->setConfig("asm.offset", 1);
|
2017-09-27 20:23:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-09-01 13:03:35 +00:00
|
|
|
this->hexOffsetText->hide();
|
2017-10-09 18:08:35 +00:00
|
|
|
core->setConfig("asm.offset", 0);
|
2017-09-01 13:03:35 +00:00
|
|
|
}
|
|
|
|
}
|