Skip to content

Commit d3f9ade

Browse files
committed
feat: graph debugging dialog for unit-testing, code cleanup
1 parent f1a214f commit d3f9ade

26 files changed

Lines changed: 346 additions & 59 deletions

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ target_sources(${PROJECT_NAME}
3838
src/dialogs/analyzer.cpp
3939
src/dialogs/decoder.cpp
4040
src/dialogs/detail.cpp
41+
src/dialogs/devgraphs.cpp
4142
src/dialogs/flc.cpp
4243
src/dialogs/goto.cpp
4344
src/dialogs/loader.cpp
@@ -80,6 +81,8 @@ target_sources(${PROJECT_NAME}
8081
src/views/dashboard.cpp
8182
src/views/log.cpp
8283
src/views/welcome.cpp
84+
src/widgets/feedbackpushbutton.cpp
85+
src/widgets/feedbacktoolbutton.cpp
8386
src/main.cpp
8487
src/mainwindow.cpp
8588
src/statusbar.cpp

src/dialogs/devgraphs.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "devgraphs.h"
2+
#include "support/surfacerenderer.h"
3+
#include "support/utils.h"
4+
#include <QApplication>
5+
#include <QClipboard>
6+
#include <QHeaderView>
7+
8+
DevGraphsDialog::DevGraphsDialog(RDContext* ctx, QWidget* parent)
9+
: QDialog{parent}, m_ui{this}, m_context{ctx} {
10+
11+
m_ui.ftbcopyhash->setEnabled(false);
12+
m_ui.ftbcopygraph->setEnabled(false);
13+
14+
m_functionsmodel = new FunctionsModel(ctx, m_ui.tvfunctions);
15+
m_ui.tvfunctions->setModel(m_functionsmodel);
16+
17+
m_ui.ptedot->setFont(surface_renderer::get_font());
18+
m_ui.ptedot->setTabStopDistance(4 * surface_renderer::cell_width());
19+
20+
QHeaderView* hdrview = m_ui.tvfunctions->header();
21+
hdrview->setSectionResizeMode(0, QHeaderView::ResizeToContents);
22+
hdrview->setSectionResizeMode(1, QHeaderView::Stretch);
23+
24+
this->setFocus(); // don't focus function list
25+
26+
connect(m_ui.tvfunctions, &QTreeView::clicked, this,
27+
&DevGraphsDialog::show_dot);
28+
29+
connect(m_ui.ftbcopytests, &FeedbackPushButton::feedback, this,
30+
&DevGraphsDialog::copy_tests);
31+
32+
connect(m_ui.ftbcopygraph, &FeedbackPushButton::feedback, this,
33+
[&]() { qApp->clipboard()->setText(m_currentgraph); });
34+
35+
connect(m_ui.ftbcopyhash, &FeedbackPushButton::feedback, this, [&]() {
36+
qApp->clipboard()->setText(
37+
QString{"0x%1"}.arg(utils::to_hex(m_currenthash)));
38+
});
39+
}
40+
41+
void DevGraphsDialog::copy_tests() {
42+
QString s = "{\n";
43+
44+
for(int i = 0; i < m_functionsmodel->rowCount({}); i++) {
45+
QModelIndex index = m_functionsmodel->index(i);
46+
RDAddress address = m_functionsmodel->address(index);
47+
const RDFunction* f = rd_find_function(m_context, address);
48+
Q_ASSERT(f);
49+
u32 hash = rd_function_get_hash(f);
50+
51+
s.append(QString{" {0x%1, 0x%2},\n"}
52+
.arg(utils::to_hex(address))
53+
.arg(utils::to_hex(hash)));
54+
}
55+
56+
s.append("};");
57+
qApp->clipboard()->setText(s);
58+
}
59+
60+
void DevGraphsDialog::show_dot(const QModelIndex& index) {
61+
m_currentgraph = {};
62+
m_currenthash = {};
63+
m_ui.ptedot->clear();
64+
65+
RDAddress address = m_functionsmodel->address(index);
66+
const char* dot = nullptr;
67+
68+
const RDFunction* f = rd_find_function(m_context, address);
69+
if(!f) goto fail;
70+
71+
dot = rd_function_generate_dot(f);
72+
if(!dot) goto fail;
73+
74+
m_currenthash = rd_function_get_hash(f);
75+
m_currentgraph = QString::fromUtf8(dot);
76+
77+
m_ui.ptedot->setPlainText(m_currentgraph);
78+
m_ui.ftbcopyhash->setEnabled(true);
79+
m_ui.ftbcopygraph->setEnabled(true);
80+
return;
81+
82+
fail:
83+
m_ui.ftbcopyhash->setEnabled(false);
84+
m_ui.ftbcopygraph->setEnabled(false);
85+
}

src/dialogs/devgraphs.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "models/functions.h"
4+
#include "ui/devgraphsdialog.h"
5+
#include <redasm/redasm.h>
6+
7+
class DevGraphsDialog: public QDialog {
8+
Q_OBJECT
9+
10+
public:
11+
explicit DevGraphsDialog(RDContext* ctx, QWidget* parent = nullptr);
12+
13+
private Q_SLOTS:
14+
void show_dot(const QModelIndex& index);
15+
void copy_tests();
16+
17+
private:
18+
ui::DevGraphsDialog m_ui;
19+
RDContext* m_context;
20+
FunctionsModel* m_functionsmodel;
21+
QString m_currentgraph{};
22+
u32 m_currenthash{};
23+
};

src/dialogs/memorymap.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ MemoryMapDialog::MemoryMapDialog(const RDContext* ctx, QWidget* parent)
1515

1616
for(usize i = 0; i < rd_slice_length(segments); i++) {
1717
const RDSegment* s = rd_slice_at(segments, i);
18-
QString startaddr = utils::to_hex_addr(s->start_address, s);
19-
QString endaddr = utils::to_hex_addr(s->end_address, s);
18+
QString startaddr = utils::to_hex(s->start_address, s);
19+
QString endaddr = utils::to_hex(s->end_address, s);
2020

2121
m_ui.cbsegments->addItem(
2222
QString{"%1 (%2 - %3)"}.arg(s->name).arg(startaddr).arg(endaddr));

src/mainwindow.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "mainwindow.h"
22
#include "dialogs/analyzer.h"
33
#include "dialogs/decoder.h"
4+
#include "dialogs/devgraphs.h"
45
#include "dialogs/flc.h"
56
#include "dialogs/loader.h"
67
#include "dialogs/memorymap.h"
@@ -75,11 +76,18 @@ MainWindow::MainWindow(QWidget* parent): QMainWindow{parent}, m_ui{this} {
7576
dlgflc->show();
7677
});
7778

78-
connect(m_ui.acttoolsdecoder, &QAction::triggered, this, [&]() {
79+
connect(m_ui.actdevdecoder, &QAction::triggered, this, [&]() {
7980
auto* dlgdecoder = new DecoderDialog(this);
8081
dlgdecoder->show();
8182
});
8283

84+
connect(m_ui.actdevgraphs, &QAction::triggered, this, [&]() {
85+
ContextView* ctxview = this->context_view();
86+
if(!ctxview) return;
87+
auto* dlggraphdots = new DevGraphsDialog(ctxview->context(), this);
88+
dlggraphdots->show();
89+
});
90+
8391
connect(m_ui.acttoolsproblems, &QAction::triggered, this,
8492
&MainWindow::show_problems);
8593

@@ -261,9 +269,11 @@ void MainWindow::enable_context_actions(bool e) { // NOLINT
261269

262270
m_ui.acttbseparator1->setVisible(e);
263271
m_ui.acttbseparator2->setVisible(e);
272+
m_ui.acttbseparator3->setVisible(e);
264273

265274
m_ui.acttoolsflc->setVisible(e);
266275
m_ui.acttoolsproblems->setVisible(e);
276+
m_ui.actdevgraphs->setVisible(e);
267277
m_ui.actviewexported->setVisible(e);
268278
m_ui.actviewsegmentregs->setVisible(e);
269279
m_ui.actviewsegments->setVisible(e);

src/models/exported.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ QVariant ExportedModel::data(const QModelIndex& index, int role) const {
1616
const RDSegment* seg = rd_find_segment(m_context, addr);
1717

1818
switch(index.column()) {
19-
case 0: return utils::to_hex_addr(addr, seg);
19+
case 0: return utils::to_hex(addr, seg);
2020
case 1: return rd_get_name(m_context, addr);
2121

2222
case 2: {

src/models/functions.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ QVariant FunctionsModel::data(const QModelIndex& index, int role) const {
2222
RDAddress addr = rd_function_get_address(f);
2323

2424
switch(index.column()) {
25-
case 0: return rd_get_name(m_context, addr);
25+
case 0: return QString::fromUtf8(rd_to_hexaddr(m_context, addr));
26+
case 1: return QString::fromUtf8(rd_get_name(m_context, addr));
2627
default: break;
2728
}
2829
}
@@ -37,14 +38,15 @@ QVariant FunctionsModel::headerData(int section, Qt::Orientation orientation,
3738
if(orientation == Qt::Vertical || role != Qt::DisplayRole) return {};
3839

3940
switch(section) {
40-
case 0: return "Functions";
41+
case 0: return "Address";
42+
case 1: return "Functions";
4143
default: break;
4244
}
4345

4446
return {};
4547
}
4648

47-
int FunctionsModel::columnCount(const QModelIndex&) const { return 1; }
49+
int FunctionsModel::columnCount(const QModelIndex&) const { return 2; }
4850

4951
int FunctionsModel::rowCount(const QModelIndex&) const {
5052
return static_cast<int>(rd_slice_length(m_functions));

src/models/imported.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ QVariant ImportedModel::data(const QModelIndex& index, int role) const {
1919
bool ok = rd_get_imported(m_context, addr, &imp);
2020

2121
switch(index.column()) {
22-
case 0: return utils::to_hex_addr(addr, seg);
22+
case 0: return utils::to_hex(addr, seg);
2323

2424
case 1:
2525
return ok && imp.ordinal.has_value

src/models/mappings.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ QVariant MappingsModel::data(const QModelIndex& index, int role) const {
1515
RDInputMapping m = rd_slice_at(m_mappings, index.row());
1616

1717
switch(index.column()) {
18-
case 0: return utils::to_hex_addr(m.offset);
19-
case 1: return utils::to_hex_addr(m.start_address);
20-
case 2: return utils::to_hex_addr(m.end_address);
18+
case 0: return utils::to_hex(m.offset);
19+
case 1: return utils::to_hex(m.start_address);
20+
case 2: return utils::to_hex(m.end_address);
2121
default: break;
2222
}
2323
}

src/models/problems.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ QVariant ProblemsModel::data(const QModelIndex& index, int role) const {
2121
const RDSegment* toseg = rd_find_segment(m_context, p->address);
2222

2323
switch(index.column()) {
24-
case 0: return utils::to_hex_addr(p->from_address, fromseg);
25-
case 1: return utils::to_hex_addr(p->address, toseg);
24+
case 0: return utils::to_hex(p->from_address, fromseg);
25+
case 1: return utils::to_hex(p->address, toseg);
2626
case 2: return QString::fromUtf8(p->message);
2727
default: break;
2828
}

0 commit comments

Comments
 (0)