cutter/src/widgets/memwidget/memorywidget.cpp
2017-03-30 17:12:41 +02:00

1691 lines
59 KiB
C++

#include "memorywidget.h"
#include "ui_memorywidget.h"
#include "mainwindow.h"
#include "dialogs/xrefsdialog.h"
#include "dialogs/renamedialog.h"
#include "dialogs/commentsdialog.h"
#include <QTemporaryFile>
#include <QFontDialog>
#include <QScrollBar>
#include <QClipboard>
#include <QShortcut>
#include <QWebFrame>
#include <QMenu>
#include <QFont>
#include <QUrl>
MemoryWidget::MemoryWidget(MainWindow *main, QWidget *parent) :
QDockWidget(parent),
ui(new Ui::MemoryWidget)
{
ui->setupUi(this);
// Radare core found in:
this->main = main;
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";
// 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);
// Hide graph webview scrollbars
ui->graphWebView->page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
ui->graphWebView->page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
// Add margin to function name line edit
ui->fcnNameEdit->setTextMargins(5, 0, 0, 0);
// Normalize fonts for other OS
QHelpers *help = new QHelpers();
help->normalizeFont(this->disasTextEdit);
help->normalizeEditFont(this->hexOffsetText);
help->normalizeEditFont(this->hexHexText);
help->normalizeEditFont(this->hexASCIIText);
// Popup menu on Settings toolbutton
QMenu *memMenu = new QMenu();
ui->memSettingsButton_2->addAction(ui->actionSettings_menu_1);
memMenu->addAction(ui->actionSettings_menu_1);
QMenu* hideSide = memMenu->addMenu("Show/Hide");
hideSide->addAction(ui->actionDisas_ShowHideBytes);
hideSide->addAction(ui->actionSeparate_bytes);
hideSide->addAction(ui->actionRight_align_bytes);
hideSide->addSeparator();
hideSide->addAction(ui->actionDisasSwitch_case);
hideSide->addAction(ui->actionSyntax_AT_T_Intel);
hideSide->addAction(ui->actionSeparate_disasm_calls);
hideSide->addAction(ui->actionShow_stack_pointer);
ui->memSettingsButton_2->setMenu(memMenu);
// Disable bytes options by default as bytes are not shown
ui->actionSeparate_bytes->setDisabled(true);
ui->actionRight_align_bytes->setDisabled(true);
// Resize eventfilter
this->installEventFilter(this);
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)));
// X to show hexdump
QShortcut* hexdump_shortcut = new QShortcut(QKeySequence(Qt::Key_X), this->main);
connect(hexdump_shortcut, SIGNAL(activated()), this, SLOT(showHexdump()));
// Space to switch between disassembly and graph
QShortcut* graph_shortcut = new QShortcut(QKeySequence(Qt::Key_Space), this->main);
connect(graph_shortcut, SIGNAL(activated()), this, SLOT(cycleViews()));
// Semicolon to add comment
QShortcut* comment_shortcut = new QShortcut(QKeySequence(Qt::Key_Semicolon), ui->disasTextEdit_2);
connect(comment_shortcut, SIGNAL(activated()), this, SLOT(on_actionDisasAdd_comment_triggered()));
// N to rename function
QShortcut* rename_shortcut = new QShortcut(QKeySequence(Qt::Key_N), ui->disasTextEdit_2);
connect(rename_shortcut, SIGNAL(activated()), this, SLOT(on_actionFunctionsRename_triggered()));
// R to show XRefs
QShortcut* xrefs_shortcut = new QShortcut(QKeySequence(Qt::Key_R), ui->disasTextEdit_2);
connect(xrefs_shortcut, SIGNAL(activated()), this, SLOT(on_actionXRefs_triggered()));
// 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()));
}
/*
* Text highlight functions
*/
void MemoryWidget::highlightDisasms()
{
// Syntax Highliting
highlighter = new Highlighter(this->main, ui->disasTextEdit_2->document());
highlighter_5 = new Highlighter(this->main, ui->hexDisasTextEdit_2->document());
ascii_highlighter = new AsciiHighlighter(ui->hexASCIIText_2->document());
hex_highlighter = new HexHighlighter(ui->hexHexText_2->document());
preview_highlighter = new Highlighter(this->main, ui->previewTextEdit->document());
deco_highlighter = new Highlighter(this->main, ui->decoTextEdit->document());
}
void MemoryWidget::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
// Highlight the current line in yellow
if (ui->disasTextEdit_2->isReadOnly()) {
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);
while (!highlightSelection.cursor.isNull() && !highlightSelection.cursor.atEnd()) {
highlightSelection.cursor = document->find(searchString, highlightSelection.cursor, QTextDocument::FindWholeWords);
if (!highlightSelection.cursor.isNull()) {
highlightSelection.cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
extraSelections.append(highlightSelection);
}
}
cursor2.endEditBlock();
ui->disasTextEdit_2->setExtraSelections(extraSelections);
}
void MemoryWidget::highlightHexCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
if (!ui->hexHexText_2->isReadOnly()) {
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());
}
void MemoryWidget::highlightHexWords(QString str)
{
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);
while (!highlightCursor.isNull() && !highlightCursor.atEnd()) {
highlightCursor = document->find(searchString, highlightCursor, QTextDocument::FindWholeWords);
if (!highlightCursor.isNull()) {
highlightCursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
highlightCursor.mergeCharFormat(colorFormat);
}
}
cursor.endEditBlock();
}
void MemoryWidget::highlightPreviewCurrentLine() {
QList<QTextEdit::ExtraSelection> extraSelections;
if (ui->previewTextEdit->toPlainText() != "") {
if (ui->previewTextEdit->isReadOnly()) {
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);
}
void MemoryWidget::highlightDecoCurrentLine() {
QList<QTextEdit::ExtraSelection> extraSelections;
if (ui->decoTextEdit->toPlainText() != "") {
if (ui->decoTextEdit->isReadOnly()) {
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);
}
MemoryWidget::~MemoryWidget()
{
delete ui;
}
/*
* Content management functions
*/
void MemoryWidget::fillPlugins(QStringList plugins) {
// Fill the plugins combo for the hexdump sidebar
ui->hexArchComboBox_2->insertItems(0, plugins);
}
void MemoryWidget::addTextDisasm(QString txt) {
QTextDocument *document = ui->disasTextEdit_2->document();
//document->undo();
ui->disasTextEdit_2->appendPlainText(txt);
}
void MemoryWidget::replaceTextDisasm(QString txt) {
QTextDocument *document = ui->disasTextEdit_2->document();
ui->disasTextEdit_2->clear();
//document->undo();
ui->disasTextEdit_2->setPlainText(txt);
}
void MemoryWidget::disasmScrolled()
{
/*
* 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
*/
// Disconnect scroll signals to add more content
disconnect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
QScrollBar *sb = this->disasTextEdit->verticalScrollBar();
if ( sb->value() > sb->maximum() - 10 ) {
//this->main->add_debug_output("End is coming");
QTextCursor tc = this->disasTextEdit->textCursor();
tc.movePosition( QTextCursor::End );
tc.select( QTextCursor::LineUnderCursor );
QString lastline = tc.selectedText();
QString ele = lastline.split(" ", QString::SkipEmptyParts)[0];
if (ele.contains("0x")) {
this->main->core->cmd("ss " + ele);
QString raw = this->main->core->cmd("pd 200");
QString txt = raw.section("\n", 1, -1);
//this->disasTextEdit->appendPlainText(" ;\n ; New content here\n ;\n " + txt.trimmed());
this->disasTextEdit->appendPlainText(txt.trimmed());
} else {
tc.movePosition( QTextCursor::End );
tc.select( QTextCursor::LineUnderCursor );
QString lastline = tc.selectedText();
this->main->add_debug_output("Last line: " + lastline);
}
// 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();
this->main->core->cmd("ss " + ele);
this->main->core->cmd("so -50");
QString raw = this->main->core->cmd("pd 50");
//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()));
}
void MemoryWidget::refreshDisasm(QString off = "") {
// we must store those ranges somewhere, to handle scroll
ut64 addr = this->main->core->core->offset;
int length = this->main->core->core->num->value;
// Prevent further scroll
disconnect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
// Get disas at offset
if (off != "") {
this->main->core->cmd("s " + off);
}
QString txt2 = this->main->core->cmd("pd 100");
this->disasTextEdit->setPlainText(txt2.trimmed());
// TODO: Fixx this ugly code
//QString temp_seek = this->main->core->cmd("s").split("0x")[1].trimmed();
QString s = this->normalize_addr(this->main->core->cmd("s"));
//this->main->add_debug_output("Offset to search: " + s);
this->disasTextEdit->ensureCursorVisible();
this->disasTextEdit->moveCursor(QTextCursor::End);
while ( this->disasTextEdit->find(QRegExp("^" + s), QTextDocument::FindBackward) ); {
this->disasTextEdit->moveCursor(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
}
connect(this->disasTextEdit->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(disasmScrolled()));
// Gett ALL disasm, dissabled
/*
int size;
QString txt;
size = main->core->get_size();
QList<QList<QString>> sections = main->core->get_exec_sections();
foreach (QList<QString> section, sections) {
// TODO: Remove later this check and add all sections
if (section[2].contains(".text")) {
this->main->core->cmd("s section." + section[2]);
this->main->core->cmd("b " + section[1]);
txt.append( this->main->core->cmd("pD") );
}
}
*/
}
void MemoryWidget::refreshHexdump(QString where)
{
// 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;
int cols = this->main->core->core->print->cols;
int bsize = 128 * cols;
if (hexdumpBottomOffset < bsize)
{
hexdumpBottomOffset = 0;
hexdumpLength = bsize;//-hexdumpBottomOffset;
} else
{
hexdumpLength = bsize;
}
//int size;
//size = main->core->get_size();
QString s = "";
if (where != "") {
this->main->core->cmd("ss " + where);
}
// Add first the hexdump at block size --
this->main->core->cmd ("ss -" + this->main->core->itoa(hexdumpLength));
//s = this->normalize_addr(this->main->core->cmd("s"));
QList<QString> ret = this->get_hexdump("");
hexdumpBottomOffset = this->main->core->core->offset;
this->hexOffsetText->setPlainText(ret[0]);
this->hexHexText->setPlainText(ret[1]);
this->hexASCIIText->setPlainText(ret[2]);
this->resizeHexdump();
// Add then the hexdump at block size ++
this->main->core->cmd ("ss +" + this->main->core->itoa(hexdumpLength));
// Get address to move cursor to later
//QString s = "0x0" + this->main->core->cmd("s").split("0x")[1].trimmed();
s = this->normalize_addr(this->main->core->cmd("s"));
ret = this->get_hexdump("");
hexdumpBottomOffset = this->main->core->core->offset;
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()));
}
QList<QString> MemoryWidget::get_hexdump(QString off = "") {
QList<QString> ret;
QString hexdump;
int hexdumpLength;
int cols = this->main->core->core->print->cols;
int bsize = 128 * cols;
if (hexdumpBottomOffset < bsize)
{
hexdumpBottomOffset = 0;
hexdumpLength = bsize;
//-hexdumpBottomOffset;
} else
{
hexdumpLength = bsize;
}
//this->main->add_debug_output("BSize: " + this->main->core->itoa(hexdumpLength, 10));
if (off == "" ) {
hexdump = this->main->core->cmd ("px " + this->main->core->itoa(hexdumpLength, 10));
} else {
hexdump = this->main->core->cmd ("px " + this->main->core->itoa(hexdumpLength, 10) + " @ " + off);
}
//QString hexdump = this->main->core->cmd ("px 0x" + this->main->core->itoa(size) + " @ 0x0");
// TODO: use pxl to simplify
QString offset = QString("");
QString hex = QString("");
QString ascii = QString ("");
int ln = 0;
for (const QString line : hexdump.split ("\n"))
{
if (ln++==0)
{
continue;
}
int wc = 0;
for (const QString a : line.split(" "))
{
switch (wc++)
{
case 0: offset += a+"\n"; break;
case 1: {
hex += a.trimmed()+"\n";
} break;
case 2: ascii += a+"\n";
break;
}
}
}
ret << offset.trimmed();
ret << hex.trimmed();
ret << ascii.trimmed();
return ret;
}
void MemoryWidget::seek_to(QString offset) {
this->disasTextEdit->moveCursor(QTextCursor::End);
int pos = this->disasTextEdit->find(offset, QTextDocument::FindBackward);
this->disasTextEdit->moveCursor(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
//this->main->add_debug_output("OFFSET: " + offset);
}
void MemoryWidget::resizeHexdump() {
//qDebug() << "size: " << ui->hexHexText->document()->size().width();
this->hexOffsetText->setMinimumWidth( this->hexOffsetText->document()->size().width() );
this->hexHexText->setMinimumWidth( this->hexHexText->document()->size().width() );
this->hexASCIIText->setMinimumWidth( this->hexASCIIText->document()->size().width() );
}
void MemoryWidget::hexScrolled()
{
QScrollBar *sb = this->hexASCIIText->verticalScrollBar();
if ( sb->value() > sb->maximum() -10 ) {
this->main->add_debug_output("End is coming");
QTextCursor tc = this->hexOffsetText->textCursor();
tc.movePosition( QTextCursor::End );
tc.select( QTextCursor::LineUnderCursor );
QString lastline = tc.selectedText();
//this->main->add_debug_output("Last Offset/VA: " + lastline);
//refreshHexdump(2);
QList<QString> ret = this->get_hexdump(lastline);
this->hexOffsetText->append(ret[0]);
this->hexHexText->append(ret[1]);
this->hexASCIIText->append(ret[2]);
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)
} else if (sb->value() < sb->minimum() + 10) {
//this->main->add_debug_output("Begining is coming");
QTextCursor tc = this->hexOffsetText->textCursor();
tc.movePosition( QTextCursor::Start );
tc.select( QTextCursor::LineUnderCursor );
QString firstline = tc.selectedText();
//disathis->main->add_debug_output("First Offset/VA: " + firstline);
//refreshHexdump(1);
int cols = this->main->core->core->print->cols;
// px bsize @ addr
//int bsize = 128 * cols;
int bsize = 800;
QString s = QString::number(bsize);
// s = 2048.. sigh...
QString kk = this->main->core->cmd("? " + firstline + " - " + s);
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
int z = c -b;
// 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());
if (sel_text == "") {
this->hexDisasTextEdit->setPlainText("");
ui->bytesEntropy->setText("");
ui->bytesMD5->setText("");
ui->bytesSHA1->setText("");
} else {
if (parsing == "Dissasembly") {
// Get selected combos
QString arch = ui->hexArchComboBox_2->currentText();
QString bits = ui->hexBitsComboBox_2->currentText();
QString oarch = this->main->core->config("asm.arch");
QString obits = this->main->core->config("asm.bits");
this->main->core->config("asm.arch" , arch);
this->main->core->config("asm.bits" , bits);
QString str = this->main->core->cmd("pad " + sel_text);
this->hexDisasTextEdit->setPlainText(str);
this->main->core->config("asm.arch" , oarch);
this->main->core->config("asm.bits" , obits);
//qDebug() << "Selected Arch: " << arch;
//qDebug() << "Selected Bits: " << bits;
//qDebug() << "Selected Text: " << sel_text;
}
// TODO: update on selection changes.. use cmd("pc "+len+"@"+off)
else if (parsing == "C byte array") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pc@x:" + sel_text));
} else if (parsing == "C dword array") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pcw@x:" + sel_text));
} else if (parsing == "C qword array") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pcq@x:" + sel_text));
} else if (parsing == "Assembler") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pca@x:" + sel_text));
} else if (parsing == "String") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pcs@x:" + sel_text));
} else if (parsing == "JSON") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pcj@x:" + sel_text));
} else if (parsing == "Javascript") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pcJ@x:" + sel_text));
} else if (parsing == "Python") {
this->hexDisasTextEdit->setPlainText(this->main->core->cmd("pcp@x:" + sel_text));
}
// Fill the information tab hashes and entropy
ui->bytesMD5->setText( this->main->core->cmd("ph md5@x:" + sel_text).trimmed() );
ui->bytesSHA1->setText( this->main->core->cmd("ph sha1@x:" + sel_text).trimmed() );
ui->bytesEntropy->setText( this->main->core->cmd("ph entropy@x:" + sel_text).trimmed() );
ui->bytesMD5->setCursorPosition(0);
ui->bytesSHA1->setCursorPosition(0);
}
}
void MemoryWidget::on_hexArchComboBox_2_currentTextChanged(const QString &arg1)
{
on_hexHexText_2_selectionChanged();
}
void MemoryWidget::on_hexBitsComboBox_2_currentTextChanged(const QString &arg1)
{
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();
QMenu* colSubmenu = menu->addMenu("Columns");
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();
QMenu* colSubmenu = menu->addMenu("Columns");
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)
{
// Set Disas popup menu
QMenu *menu = ui->disasTextEdit_2->createStandardContextMenu();
QTextCursor cur = ui->disasTextEdit_2->textCursor();
if (cur.hasSelection()) {
menu->addSeparator();
menu->addAction(ui->actionSend_to_Notepad);
ui->disasTextEdit_2->setContextMenuPolicy(Qt::DefaultContextMenu);
} else {
// Add menu actions
menu->clear();
menu->addAction(ui->actionDisasAdd_comment);
menu->addAction(ui->actionFunctionsRename);
menu->addAction(ui->actionFunctionsUndefine);
menu->addSeparator();
menu->addAction(ui->actionXRefs);
menu->addSeparator();
menu->addAction(ui->actionDisas_ShowHideBytes);
menu->addAction(ui->actionSeparate_bytes);
menu->addAction(ui->actionRight_align_bytes);
menu->addSeparator();
menu->addAction(ui->actionDisasSwitch_case);
menu->addAction(ui->actionSyntax_AT_T_Intel);
menu->addAction(ui->actionSeparate_disasm_calls);
menu->addAction(ui->actionShow_stack_pointer);
menu->addSeparator();
menu->addAction(ui->actionDisasCopy_All);
menu->addAction(ui->actionDisasCopy_Bytes);
menu->addAction(ui->actionDisasCopy_Disasm);
ui->disasTextEdit_2->setContextMenuPolicy(Qt::CustomContextMenu);
}
menu->exec(ui->disasTextEdit_2->mapToGlobal(pt));
delete menu;
ui->disasTextEdit_2->setContextMenuPolicy(Qt::CustomContextMenu);
}
void MemoryWidget::on_showInfoButton_2_clicked()
{
if(ui->showInfoButton_2->isChecked())
{
ui->fcnGraphTabWidget->hide();
ui->showInfoButton_2->setArrowType(Qt::RightArrow);
} else {
ui->fcnGraphTabWidget->show();
ui->showInfoButton_2->setArrowType(Qt::DownArrow);
}
}
void MemoryWidget::on_offsetToolButton_clicked()
{
if(ui->offsetToolButton->isChecked())
{
ui->offsetTreeWidget->hide();
ui->offsetToolButton->setArrowType(Qt::RightArrow);
} else {
ui->offsetTreeWidget->show();
ui->offsetToolButton->setArrowType(Qt::DownArrow);
}
}
/*
* Show widgets
*/
void MemoryWidget::showHexdump() {
ui->hexButton_2->setChecked(true);
ui->memTabWidget->setCurrentIndex(1);
ui->memSideTabWidget_2->setCurrentIndex(1);
}
void MemoryWidget::cycleViews() {
if (ui->memTabWidget->currentIndex() == 0) {
// Show graph
ui->graphButton_2->setChecked(true);
ui->memTabWidget->setCurrentIndex(2);
ui->memSideTabWidget_2->setCurrentIndex(0);
} else if (ui->memTabWidget->currentIndex() == 2) {
// Show disasm
ui->disButton_2->setChecked(true);
ui->memTabWidget->setCurrentIndex(0);
ui->memSideTabWidget_2->setCurrentIndex(0);
} else {
// Show disasm
ui->disButton_2->setChecked(true);
ui->memTabWidget->setCurrentIndex(0);
ui->memSideTabWidget_2->setCurrentIndex(0);
}
}
/*
* Actions callback functions
*/
void MemoryWidget::on_actionSettings_menu_1_triggered()
{
bool ok = true;
// QFont font = QFont("Monospace", 8);
QFont font = QFontDialog::getFont( &ok, ui->disasTextEdit_2->font(), this);
setFonts (font);
}
void MemoryWidget::setFonts(QFont font) {
ui->disasTextEdit_2->setFont (font);
// 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);
this->main->notepadDock->setFonts(font);
}
void MemoryWidget::on_actionHideDisasm_side_panel_triggered()
{
if (ui->memSideTabWidget_2->isVisible()) {
ui->memSideTabWidget_2->hide();
} else {
ui->memSideTabWidget_2->show();
}
}
void MemoryWidget::on_actionHideHexdump_side_panel_triggered()
{
if (ui->hexSideTab_2->isVisible()) {
ui->hexSideTab_2->hide();
} else {
ui->hexSideTab_2->show();
}
}
void MemoryWidget::on_actionHideGraph_side_panel_triggered()
{
if (ui->graphTreeWidget_2->isVisible()) {
ui->graphTreeWidget_2->hide();
} else {
ui->graphTreeWidget_2->show();
}
}
/*
* Buttons callback functions
*/
void MemoryWidget::on_disButton_2_clicked()
{
ui->memTabWidget->setCurrentIndex(0);
ui->memSideTabWidget_2->setCurrentIndex(0);
}
void MemoryWidget::on_hexButton_2_clicked()
{
ui->memTabWidget->setCurrentIndex(1);
ui->memSideTabWidget_2->setCurrentIndex(1);
}
void MemoryWidget::on_actionDisas_ShowHideBytes_triggered()
{
this->main->core->cmd ("e!asm.bytes");
if (this->main->core->cmd ("e asm.bytes").trimmed() == "true") {
ui->actionSeparate_bytes->setDisabled(false);
ui->actionRight_align_bytes->setDisabled(false);
this->main->core->config("asm.cmtcol", "100");
} else {
ui->actionSeparate_bytes->setDisabled(true);
ui->actionRight_align_bytes->setDisabled(true);
this->main->core->config("asm.cmtcol", "70");
}
this->refreshDisasm();
}
void MemoryWidget::on_actionDisasSwitch_case_triggered()
{
this->main->core->cmd ("e!asm.ucase");
this->refreshDisasm();
}
void MemoryWidget::on_actionSyntax_AT_T_Intel_triggered()
{
QString syntax = this->main->core->cmd ("e asm.syntax").trimmed();
if (syntax == "intel") {
this->main->core->config("asm.syntax", "att");
} else {
this->main->core->config("asm.syntax", "intel");
}
this->refreshDisasm();
}
void MemoryWidget::on_actionSeparate_bytes_triggered()
{
this->main->core->cmd ("e!asm.bytespace");
this->refreshDisasm();
}
void MemoryWidget::on_actionRight_align_bytes_triggered()
{
this->main->core->cmd ("e!asm.lbytes");
this->refreshDisasm();
}
void MemoryWidget::on_actionSeparate_disasm_calls_triggered()
{
this->main->core->cmd ("e!asm.spacy");
this->refreshDisasm();
}
void MemoryWidget::on_actionShow_stack_pointer_triggered()
{
this->main->core->cmd ("e!asm.stackptr");
this->refreshDisasm();
}
void MemoryWidget::on_graphButton_2_clicked()
{
ui->memTabWidget->setCurrentIndex(2);
ui->memSideTabWidget_2->setCurrentIndex(0);
}
void MemoryWidget::on_actionSend_to_Notepad_triggered()
{
QTextCursor cursor = ui->disasTextEdit_2->textCursor();
QString text = cursor.selectedText();
this->main->send_to_notepad(text);
}
void MemoryWidget::on_actionDisasAdd_comment_triggered()
{
// 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")) {
// Get function for clicked offset
RAnalFunction *fcn = this->main->core->functionAt(ele.toLongLong(0, 16));
CommentsDialog* c = new CommentsDialog(this);
if (c->exec()) {
// Get new function name
QString comment = c->getComment();
//this->main->add_debug_output("Comment: " + comment + " at: " + ele);
// Rename function in r2 core
this->main->core->setComment(ele, comment);
// Seek to new renamed function
this->main->seek(fcn->name);
// TODO: Refresh functions tree widget
}
}
this->main->refreshComments();
}
void MemoryWidget::on_actionFunctionsRename_triggered()
{
// 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")) {
// Get function for clicked offset
RAnalFunction *fcn = this->main->core->functionAt(ele.toLongLong(0, 16));
RenameDialog* r = new RenameDialog(this);
// Get function based on click position
r->setFunctionName(fcn->name);
if (r->exec()) {
// Get new function name
QString new_name = r->getFunctionName();
// Rename function in r2 core
this->main->core->renameFunction(fcn->name, new_name);
// Seek to new renamed function
this->main->seek(new_name);
// TODO: Refresh functions tree widget
}
}
this->main->refreshFunctions();
}
void MemoryWidget::on_action8columns_triggered()
{
this->main->core->config ("hex.cols", "8");
this->refreshHexdump();
}
void MemoryWidget::on_action16columns_triggered()
{
this->main->core->config ("hex.cols", "16");
this->refreshHexdump();
}
void MemoryWidget::on_action4columns_triggered()
{
this->main->core->config ("hex.cols", "4");
this->refreshHexdump();
}
void MemoryWidget::on_action32columns_triggered()
{
this->main->core->config ("hex.cols", "32");
this->refreshHexdump();
}
void MemoryWidget::on_action64columns_triggered()
{
this->main->core->config ("hex.cols", "64");
this->refreshHexdump();
}
void MemoryWidget::on_action2columns_triggered()
{
this->main->core->config ("hex.cols", "2");
this->refreshHexdump();
}
void MemoryWidget::on_action1column_triggered()
{
this->main->core->config ("hex.cols", "1");
this->refreshHexdump();
}
void MemoryWidget::on_xreFromTreeWidget_2_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
QString offset = item->text(0);
RAnalFunction *fcn = this->main->core->functionAt(offset.toLongLong(0, 16));
//this->add_debug_output( fcn->name );
this->main->seek(offset, fcn->name);
}
void MemoryWidget::on_xrefToTreeWidget_2_itemDoubleClicked(QTreeWidgetItem *item, int column)
{
QString offset = item->text(0);
RAnalFunction *fcn = this->main->core->functionAt(offset.toLongLong(0, 16));
//this->add_debug_output( fcn->name );
this->main->seek(offset, fcn->name);
}
void MemoryWidget::on_xrefFromToolButton_2_clicked()
{
if(ui->xrefFromToolButton_2->isChecked())
{
ui->xreFromTreeWidget_2->hide();
ui->xrefFromToolButton_2->setArrowType(Qt::RightArrow);
} else {
ui->xreFromTreeWidget_2->show();
ui->xrefFromToolButton_2->setArrowType(Qt::DownArrow);
}
}
void MemoryWidget::on_xrefToToolButton_2_clicked()
{
if(ui->xrefToToolButton_2->isChecked())
{
ui->xrefToTreeWidget_2->hide();
ui->xrefToToolButton_2->setArrowType(Qt::RightArrow);
} else {
ui->xrefToTreeWidget_2->show();
ui->xrefToToolButton_2->setArrowType(Qt::DownArrow);
}
}
void MemoryWidget::on_codeCombo_2_currentTextChanged(const QString &arg1)
{
if (arg1 == "Dissasembly") {
ui->hexSideFrame_2->show();
ui->hexDisasTextEdit_2->setPlainText(";; Select some bytes on the left\n;; to see them disassembled");
} else {
ui->hexSideFrame_2->hide();
ui->hexDisasTextEdit_2->setPlainText(";; Select some bytes on the left\n;; to see them parsed here");
}
}
void MemoryWidget::get_refs_data(const QString& offset)
{
// Get Refs and Xrefs
bool ok;
QList<QStringList> ret_refs;
QList<QStringList> ret_xrefs;
// refs = calls q hace esa funcion
QList<QString> refs = this->main->core->getFunctionRefs(offset.toLong(&ok, 16), 'C');
if (refs.size() > 0) {
for (int i = 0; i < refs.size(); ++i) {
//this->add_debug_output(refs.at(i));
QStringList retlist = refs.at(i).split(",");
QStringList temp;
QString addr = retlist.at(2);
temp << addr;
QString op = this->main->core->cmd("pi 1 @ " + addr);
temp << op.simplified();
ret_refs << temp;
}
}
// xrefs = calls a esa funcion
//qDebug() << this->main->core->getFunctionXrefs(offset.toLong(&ok, 16));
QList<QString> xrefs = this->main->core->getFunctionXrefs(offset.toLong(&ok, 16));
if (xrefs.size() > 0) {
for (int i = 0; i < xrefs.size(); ++i) {
//this->add_debug_output(xrefs.at(i));
QStringList retlist = xrefs.at(i).split(",");
QStringList temp;
QString addr = retlist.at(1);
temp << addr;
QString op = this->main->core->cmd("pi 1 @ " + addr);
temp << op.simplified();
ret_xrefs << temp;
}
}
// Data for the disasm side graph
QList<int> data;
//qDebug() << "Refs:" << refs.size();
data << refs.size();
//qDebug() << "XRefs:" << xrefs.size();
data << xrefs.size();
//qDebug() << "CC: " << this->main->core->fcnCyclomaticComplexity(offset.toLong(&ok, 16));
//data << this->main->core->fcnCyclomaticComplexity(offset.toLong(&ok, 16));
data << this->main->core->getCycloComplex(offset.toLong(&ok, 16));
//qDebug() << "BB: " << this->main->core->fcnBasicBlockCount(offset.toLong(&ok, 16));
data << this->main->core->fcnBasicBlockCount(offset.toLong(&ok, 16));
data << this->main->core->fcnEndBbs(offset);
//qDebug() << "MEOW: " + this->main->core->fcnEndBbs(offset);
// Update disasm side bar
this->fill_refs(ret_refs, ret_xrefs, data);
}
void MemoryWidget::fill_refs(QList<QStringList> refs, QList<QStringList> xrefs, QList<int> graph_data)
{
this->xreFromTreeWidget_2->clear();
for (int i = 0; i < refs.size(); ++i) {
//this->add_debug_output(refs.at(i).at(0) + " " + refs.at(i).at(1));
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
tempItem->setText(0, refs.at(i).at(0));
tempItem->setText(1, refs.at(i).at(1));
tempItem->setToolTip( 0, this->main->core->cmd("pdi 10 @ " + refs.at(i).at(0)).trimmed() );
tempItem->setToolTip( 1, this->main->core->cmd("pdi 10 @ " + refs.at(i).at(0)).trimmed() );
this->xreFromTreeWidget_2->insertTopLevelItem(0, tempItem);
}
// Adjust columns to content
int count = this->xreFromTreeWidget_2->columnCount();
for (int i = 0; i != count; ++i) {
this->xreFromTreeWidget_2->resizeColumnToContents(i);
}
this->xrefToTreeWidget_2->clear();
for (int i = 0; i < xrefs.size(); ++i) {
//this->add_debug_output(xrefs.at(i).at(0) + " " + xrefs.at(i).at(1));
QTreeWidgetItem *tempItem = new QTreeWidgetItem();
tempItem->setText(0, xrefs.at(i).at(0));
tempItem->setText(1, xrefs.at(i).at(1));
tempItem->setToolTip( 0, this->main->core->cmd("pdi 10 @ " + xrefs.at(i).at(0)).trimmed() );
tempItem->setToolTip( 1, this->main->core->cmd("pdi 10 @ " + xrefs.at(i).at(0)).trimmed() );
this->xrefToTreeWidget_2->insertTopLevelItem(0, tempItem);
}
// Adjust columns to content
int count2 = this->xrefToTreeWidget_2->columnCount();
for (int i = 0; i != count2; ++i) {
this->xrefToTreeWidget_2->resizeColumnToContents(i);
}
// Add data to HTML Polar functions graph
QFile html(":/html/fcn_graph.html");
if(!html.open(QIODevice::ReadOnly)) {
QMessageBox::information(0,"error",html.errorString());
}
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");
if(!html2.open(QIODevice::ReadOnly)) {
QMessageBox::information(0,"error",html.errorString());
}
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);
}
void MemoryWidget::fillOffsetInfo( QString off) {
ui->offsetTreeWidget->clear();
QString raw = "";
raw = this->main->core->getOffsetInfo(off);
QList<QString> lines = raw.split("\n", QString::SkipEmptyParts);
foreach(QString line, lines) {
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();
for (int i = 0; i != count; ++i) {
ui->offsetTreeWidget->resizeColumnToContents(i);
}
// Add opcode description
QStringList description = this->main->core->cmd("?d. @ " + off).split(": ");
if(description.length() >= 2) {
ui->opcodeDescText->setPlainText("# " + description[0] + ":\n" + description[1]);
}
}
void MemoryWidget::create_graph(QString off) {
ui->graphWebView->setZoomFactor(0.85);
//this->main->add_debug_output("Graph Offset: '" + off + "'");
if (off == "") {
off = "0x0" + this->main->core->cmd("s").split("0x")[1].trimmed();
}
QString fcn = this->main->core->cmdFunctionAt(off);
//this->main->add_debug_output("Graph Fcn: " + fcn);
ui->graphWebView->load(QUrl("qrc:/graph/html/graph/index.html#" + off));
}
QString MemoryWidget::normalize_addr(QString addr) {
QString base = this->main->core->cmd("s").split("0x")[1].trimmed();
int len = base.length();
if (len < 8) {
int padding = 8 - len;
QString zero = "0";
QString zeroes = zero.repeated(padding);
QString s = "0x" + zeroes + base;
return s;
} else {
return addr;
}
}
void MemoryWidget::setFcnName(QString addr) {
RAnalFunction *fcn;
bool ok;
// TDOD: FIX ME, ugly
if (addr.contains("0x")) {
fcn = this->main->core->functionAt(addr.toULongLong(&ok, 16));
if (ok && fcn && fcn->name != "") {
QString segment = this->main->core->cmd("S. @ " + addr).split(" ").last();
addr = segment.trimmed() + ":"+ fcn->name;
}
}
ui->fcnNameEdit->setText(addr);
}
void MemoryWidget::on_disasTextEdit_2_cursorPositionChanged()
{
// Get current offset
QTextCursor tc = this->disasTextEdit->textCursor();
tc.select( QTextCursor::LineUnderCursor );
QString lastline = tc.selectedText().trimmed();
QString ele = lastline.split(" ", QString::SkipEmptyParts)[0];
if (ele.contains("0x")) {
this->fillOffsetInfo(ele);
QString at = this->main->core->cmdFunctionAt(ele);
QString deco = this->main->core->getDecompiledCode(at);
if (deco != "") {
ui->decoTextEdit->setPlainText(deco);
} else {
ui->decoTextEdit->setPlainText("");
}
// Get jump information to fill the preview
QString jump = "";
jump = this->main->core->getOffsetJump(ele);
if (jump != "") {
// Fill the preview
QString jump_code = this->main->core->cmd("pdf @ " + jump);
ui->previewTextEdit->setPlainText(jump_code.trimmed());
ui->previewTextEdit->moveCursor(QTextCursor::End);
int pos = ui->previewTextEdit->find( jump.trimmed(), QTextDocument::FindBackward);
ui->previewTextEdit->moveCursor(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
} else {
ui->previewTextEdit->setPlainText("");
}
//this->main->add_debug_output("Fcn at: '" + at + "'");
if (this->last_fcn != at) {
this->last_fcn = at;
//this->main->add_debug_output("New Fcn: '" + this->last_fcn + "'");
// Refresh function information at sidebar
ui->fcnNameEdit->setText(at);
this->main->memoryDock->setWindowTitle(at);
this->main->memoryDock->get_refs_data(ele);
this->main->memoryDock->create_graph(ele);
this->setMiniGraph(at);
}
}
}
QString MemoryWidget::normalizeAddr(QString addr) {
QString base = addr.split("0x")[1].trimmed();
int len = base.length();
if (len < 8) {
int padding = 8 - len;
QString zero = "0";
QString zeroes = zero.repeated(padding);
QString s = "0x" + zeroes + base;
return s;
} else {
return addr;
}
}
void MemoryWidget::setMiniGraph(QString at) {
QString dot = this->main->core->getSimpleGraph(at);
//QString dot = this->main->core->cmd("agc " + at);
// Add data to HTML Polar functions graph
QFile html(":/html/graph.html");
if(!html.open(QIODevice::ReadOnly)) {
QMessageBox::information(0,"error",html.errorString());
}
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);
}
void MemoryWidget::on_hexSideTab_2_currentChanged(int index)
{
/*
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()
{
if (ui->memSideToolButton->isChecked()) {
ui->memSideTabWidget_2->hide();
ui->hexSideTab_2->hide();
ui->memSideToolButton->setIcon(QIcon(":/new/prefix1/img/icons/left.png"));
} else {
ui->memSideTabWidget_2->show();
ui->hexSideTab_2->show();
ui->memSideToolButton->setIcon(QIcon(":/new/prefix1/img/icons/right.png"));
}
}
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()
{
if (ui->previewToolButton_2->isChecked()) {
ui->frame_3->setVisible(true);
} else {
ui->frame_3->setVisible(false);
}
}
bool MemoryWidget::eventFilter(QObject *obj, QEvent *event) {
if (event->type() == QEvent::Resize && obj == this && this->isVisible()) {
if (this->main->responsive) {
QResizeEvent *resizeEvent = static_cast<QResizeEvent*>(event);
//qDebug("Dock Resized (New Size) - Width: %d Height: %d",
// resizeEvent->size().width(),
// resizeEvent->size().height());
if (resizeEvent->size().width() <= 1150) {
ui->frame_3->setVisible(false);
ui->memPreviewTab->setVisible(false);
ui->previewToolButton_2->setChecked(false);
if (resizeEvent->size().width() <= 950) {
ui->memSideTabWidget_2->hide();
ui->hexSideTab_2->hide();
ui->memSideToolButton->setChecked(true);
} else {
ui->memSideTabWidget_2->show();
ui->hexSideTab_2->show();
ui->memSideToolButton->setChecked(false);
}
} else {
ui->frame_3->setVisible(true);
ui->memPreviewTab->setVisible(true);
ui->previewToolButton_2->setChecked(true);
}
}
} else if ((obj == ui->disasTextEdit_2 || obj==ui->disasTextEdit_2->viewport()) && event->type() == QEvent::MouseButtonDblClick) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
//qDebug()<<QString("Click location: (%1,%2)").arg(mouseEvent->x()).arg(mouseEvent->y());
QTextCursor cursor = ui->disasTextEdit_2->cursorForPosition( QPoint(mouseEvent->x(), mouseEvent->y()) );
cursor.select( QTextCursor::LineUnderCursor );
QString lastline = cursor.selectedText();
QString ele = lastline.split(" ", QString::SkipEmptyParts)[0];
if (ele.contains("0x")) {
QString jump = "";
jump = this->main->core->getOffsetJump(ele);
if (jump != "") {
if (jump.contains("0x")) {
RAnalFunction *fcn = this->main->core->functionAt(jump.toLongLong(0, 16));
this->main->seek(jump, fcn->name);
} else {
this->main->seek(this->main->core->cmd("?v " + jump), jump);
}
}
}
}
return false; //allow the event to be handled further
}
void MemoryWidget::on_actionXRefs_triggered()
{
// 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")) {
// Get function for clicked offset
RAnalFunction *fcn = this->main->core->functionAt(ele.toLongLong(0, 16));
XrefsDialog* x = new XrefsDialog(this->main, this);
x->setWindowTitle("X-Refs for function " + QString::fromUtf8(fcn->name));
// Get Refs and Xrefs
bool ok;
QList<QStringList> ret_refs;
QList<QStringList> ret_xrefs;
// refs = calls q hace esa funcion
QList<QString> refs = this->main->core->getFunctionRefs(fcn->addr, 'C');
if (refs.size() > 0) {
for (int i = 0; i < refs.size(); ++i) {
//this->main->add_debug_output(refs.at(i));
QStringList retlist = refs.at(i).split(",");
QStringList temp;
QString addr = retlist.at(2);
temp << addr;
QString op = this->main->core->cmd("pi 1 @ " + addr);
temp << op.simplified();
ret_refs << temp;
}
}
// xrefs = calls a esa funcion
//qDebug() << this->main->core->getFunctionXrefs(offset.toLong(&ok, 16));
QList<QString> xrefs = this->main->core->getFunctionXrefs(fcn->addr);
if (xrefs.size() > 0) {
for (int i = 0; i < xrefs.size(); ++i) {
//this->main->add_debug_output(xrefs.at(i));
QStringList retlist = xrefs.at(i).split(",");
QStringList temp;
QString addr = retlist.at(1);
temp << addr;
QString op = this->main->core->cmd("pi 1 @ " + addr);
temp << op.simplified();
ret_xrefs << temp;
}
}
x->fillRefs(ret_refs, ret_xrefs);
x->exec();
}
}
void MemoryWidget::on_copyMD5_clicked()
{
QString md5 = ui->bytesMD5->text();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(md5);
this->main->add_output("MD5 copied to clipboard: " + md5);
}
void MemoryWidget::on_copySHA1_clicked()
{
QString sha1 = ui->bytesSHA1->text();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(sha1);
this->main->add_output("SHA1 copied to clipboard: " + sha1);
}
void MemoryWidget::switchTheme(bool dark) {
if (dark) {
ui->webSimpleGraph->setStyleSheet("background-color: rgb(64, 64, 64);");
} else {
ui->webSimpleGraph->setStyleSheet("");
}
}
void MemoryWidget::on_opcodeDescButton_clicked()
{
if(ui->opcodeDescButton->isChecked())
{
ui->opcodeDescText->hide();
ui->opcodeDescButton->setArrowType(Qt::RightArrow);
} else {
ui->opcodeDescText->show();
ui->opcodeDescButton->setArrowType(Qt::DownArrow);
}
}
void MemoryWidget::selectHexPreview() {
// Pre-select arch and bits in the hexdump sidebar
QString arch = this->main->core->cmd("e asm.arch").trimmed();
QString bits = this->main->core->cmd("e asm.bits").trimmed();
//int arch_index = ui->hexArchComboBox_2->findText(arch);
if (ui->hexArchComboBox_2->findText(arch) != -1) {
ui->hexArchComboBox_2->setCurrentIndex(ui->hexArchComboBox_2->findText(arch));
}
//int bits_index = ui->hexBitsComboBox_2->findText(bits);
if (ui->hexBitsComboBox_2->findText(bits) != -1) {
ui->hexBitsComboBox_2->setCurrentIndex(ui->hexBitsComboBox_2->findText(bits));
}
}