From 8ba5b5b647e39ce4b337b6b56a246f293c511954 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Thu, 29 Jan 2015 23:08:56 +0100 Subject: [PATCH] Make link to local functions clickable call instructions now have a clickable target address that gets you to the corresponding function iff this function is local to the object. It still does just nothing on functions that are linked in from shared objects or functionsthat were not created (shouldn't happen right now) This also adds yet another map to the MainWindow with key/value pairs that are not quite semantically nice but made implementation easy. We need to think about how which objects are referenced from ithin the mainwindow some tim in the future. --- src/gui/Mainwindow.cxx | 26 +++++++++++-- src/gui/Mainwindow.hxx | 3 ++ src/gui/widgets/BasicBlockWidget.cxx | 58 +++++++++++++++++----------- src/gui/widgets/BasicBlockWidget.hxx | 8 +++- 4 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/gui/Mainwindow.cxx b/src/gui/Mainwindow.cxx index 8a62ef8..0f2486d 100644 --- a/src/gui/Mainwindow.cxx +++ b/src/gui/Mainwindow.cxx @@ -10,6 +10,7 @@ namespace { BasicBlockWidget * local__add_basic_block(BasicBlock * block, Disassembler * dis, + Mainwindow * mainwindow, std::map& known_blocks, CFGScene * scene, uint64_t starty, uint64_t startx); } @@ -80,6 +81,18 @@ void Mainwindow::open() { manager->reset(fileName.toStdString()); } +void Mainwindow::switchMainPlaneToAddress(uint64_t address) { + if (objects_list_by_address.find(address) != objects_list_by_address.end()) { + LOG4CXX_DEBUG(logger, "Switching to function " << std::hex << address); + QListWidgetItem * item = objects_list_by_address[address]; + listWidget->setCurrentItem(item); + stackedWidget->setCurrentWidget(objects_list[item]); + } else { + LOG4CXX_DEBUG(logger, "No function at " << std::hex << address + << " -- it's probably an imported Symbol"); + } +} + void Mainwindow::switchMainPlane(int index) { stackedWidget->setCurrentWidget(objects_list[listWidget->currentItem()]); } @@ -128,8 +141,8 @@ void Mainwindow::addFunction(Function* fun) { start_address = b.first; } - local__add_basic_block(block, manager->getDisassembler(), blocks, scene, - start_address, 100); + local__add_basic_block(block, manager->getDisassembler(), this, + blocks, scene, start_address, 100); QGraphicsView * view = new QGraphicsView(scene); w->addTab(view, "CFG"); @@ -144,11 +157,15 @@ void Mainwindow::addFunction(Function* fun) { QListWidgetItem * item = new QListWidgetItem(fun->getName().c_str(), listWidget); stackedWidget->addWidget(w); objects_list.insert(std::make_pair(item, w)); + LOG4CXX_DEBUG(logger, "Adding function widget at " << std::hex + << fun->getStartAddress()); + objects_list_by_address.insert(std::make_pair(fun->getStartAddress(), item)); } namespace { BasicBlockWidget * local__add_basic_block(BasicBlock * block, Disassembler * dis, + Mainwindow * mainwindow, std::map& known_blocks, CFGScene * scene, uint64_t starty, uint64_t startx) { @@ -159,7 +176,8 @@ namespace { std::stringstream s; s << "BLOCK_" << std::hex << block->getStartAddress() << "_" << block->getEndAddress(); - BasicBlockWidget * widget = new BasicBlockWidget(s.str().c_str(), block); + BasicBlockWidget * widget = new BasicBlockWidget(s.str().c_str(), + block, mainwindow); known_blocks.insert(std::make_pair(block->getStartAddress(), widget)); @@ -186,6 +204,7 @@ namespace { xshift = 1; tmpblock = dis->getBasicBlock(block->getNextBlock(0)); tmp = local__add_basic_block(tmpblock, dis, + mainwindow, known_blocks, scene, starty, startx+xshift); nextl = tmp; @@ -194,6 +213,7 @@ namespace { if (block->getNextBlock(1) != 0) { tmpblock = dis->getBasicBlock(block->getNextBlock(1)); tmp = local__add_basic_block(tmpblock, dis, + mainwindow, known_blocks, scene, starty, startx-1); nextr = tmp; diff --git a/src/gui/Mainwindow.hxx b/src/gui/Mainwindow.hxx index efc7d99..14d41b3 100644 --- a/src/gui/Mainwindow.hxx +++ b/src/gui/Mainwindow.hxx @@ -41,10 +41,13 @@ private: std::map blocks; std::map objects_list; + std::map objects_list_by_address; std::set functions; InformationManager* manager; log4cxx::LoggerPtr logger; +public Q_SLOTS: + void switchMainPlaneToAddress(uint64_t); private Q_SLOTS: void quit(); void open(); diff --git a/src/gui/widgets/BasicBlockWidget.cxx b/src/gui/widgets/BasicBlockWidget.cxx index 0377be3..2880af3 100644 --- a/src/gui/widgets/BasicBlockWidget.cxx +++ b/src/gui/widgets/BasicBlockWidget.cxx @@ -1,20 +1,15 @@ #include "BasicBlockWidget.hxx" +#include "gui/Mainwindow.hxx" -BasicBlockWidget::BasicBlockWidget(const QString& name, BasicBlock * block) +BasicBlockWidget::BasicBlockWidget(const QString& name, BasicBlock * block, + Mainwindow * mainwindow) : width(270), height(45) - , name(name), block(block) - , _proxy(this) { + , _proxy(this), name(name) + , block(block), mainwindow(mainwindow) { next[0] = NULL; next[1] = NULL; - _widget.setStyleSheet("QTableWidget { background-color : #ddddff; }"); - _widget.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); - _widget.verticalHeader()->setDefaultSectionSize(18); - _widget.setColumnCount(3); - _widget.verticalHeader()->hide(); - _widget.horizontalHeader()->hide(); - _widget.setShowGrid(false); - _widget.setWordWrap(false); - _widget.setMinimumSize(210, 20); - + _widget.setStyleSheet("QWidget { background-color : #ddddff; }"); + _widget.setLayout(&_layout); + _layout.setContentsMargins(0, 0, 0, 0); _proxy.setWidget(&_widget); _proxy.setPos(5, 20); @@ -32,18 +27,37 @@ void BasicBlockWidget::addItem(uint8_t* bytes, size_t num_bytes, bytestring += ' '; } - int current_row = _widget.rowCount(); - _widget.setRowCount(1 + current_row); - _widget.setItem(current_row, 0, new QTableWidgetItem(bytestring)); - _widget.setItem(current_row, 1, new QTableWidgetItem(line.replace('\t', ' '))); -// _widget.setItem(current_row, 2, new QTableWidgetItem(href)); + int current_row = _layout.rowCount(); + QLabel * bytestring_label = new QLabel(bytestring); + bytestring_label->setTextInteractionFlags(Qt::TextSelectableByMouse| + Qt::LinksAccessibleByMouse); + bytestring_label->setWordWrap(false); + _layout.addWidget(bytestring_label, current_row, 0); + bytestring_label->setVisible(true); - _widget.resizeColumnToContents(0); - _widget.resizeColumnToContents(1); - _widget.resizeColumnToContents(2); + line = line.replace('\t', ' ').toHtmlEscaped(); + if (href != "") { + line = "" + line + ""; + } + QLabel * instruction_label = new QLabel(line); + instruction_label->setTextInteractionFlags(Qt::TextSelectableByMouse| + Qt::LinksAccessibleByMouse); + instruction_label->setWordWrap(false); + instruction_label->setFocusPolicy(Qt::StrongFocus); + if (href != "") { + QObject::connect(instruction_label, &QLabel::linkActivated, + [=](QString str) { + if (str.startsWith("function:")) { + QString address = str.remove("function:"); + mainwindow->switchMainPlaneToAddress(address.toInt(NULL, 16)); + } + }); + } + _layout.addWidget(instruction_label, current_row, 1); + instruction_label->setVisible(true); width = 12 + _widget.sizeHint().width(); - height = 25 + _widget.sizeHint().height(); + height = 25 + _widget.childrenRect().height(); if (width < 250) width = 250; _widget.resize(width - 12, height - 25); diff --git a/src/gui/widgets/BasicBlockWidget.hxx b/src/gui/widgets/BasicBlockWidget.hxx index 30f2bab..c351c3a 100644 --- a/src/gui/widgets/BasicBlockWidget.hxx +++ b/src/gui/widgets/BasicBlockWidget.hxx @@ -8,10 +8,12 @@ #include #include +class Mainwindow; + class BasicBlockWidget : public QGraphicsItem { public: - BasicBlockWidget(const QString& name, BasicBlock * block); + BasicBlockWidget(const QString& name, BasicBlock * block, Mainwindow * mainwindow); void addItem(uint8_t* bytes, size_t num_bytes, QString line, const QString& href); @@ -64,9 +66,11 @@ public: private: uint32_t width, height; QGraphicsProxyWidget _proxy; - QTableWidget _widget; + QGridLayout _layout; + QLabel _widget; QString name; BasicBlock * block; + Mainwindow * mainwindow; std::vector previous; BasicBlockWidget* next[2]; }; -- 2.39.2