Files
seer/src/SeerAsmWidget.cpp
T
2025-08-26 17:26:05 -05:00

120 lines
4.2 KiB
C++

// SPDX-FileCopyrightText: 2021 Ernie Pasveer <epasveer@att.net>
//
// SPDX-License-Identifier: GPL-3.0-or-later
#include "SeerAsmWidget.h"
#include "SeerUtl.h"
#include <QtCore/QDebug>
#include <algorithm>
SeerAsmWidget::SeerAsmWidget(QWidget* parent) : QWidget(parent) {
// Construct the UI.
setupUi(this);
// Setup the widgets
QFont font;
font.setFamily("monospace [Consolas]");
font.setFixedPitch(true);
font.setStyleHint(QFont::TypeWriter);
plainTextEdit->setFont(font);
plainTextEdit->setFocusPolicy(Qt::StrongFocus);
plainTextEdit->setTextInteractionFlags(Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse);
plainTextEdit->setWordWrapMode(QTextOption::NoWrap);
// Set text formats.
_defaultFormat = plainTextEdit->currentCharFormat();
_grayFormat = _defaultFormat;
_grayFormat.setBackground(QBrush(Qt::lightGray));
// Connect things.
}
SeerAsmWidget::~SeerAsmWidget() {
}
QTextDocument* SeerAsmWidget::document () {
return plainTextEdit->document();
}
QString SeerAsmWidget::toPlainText () {
return plainTextEdit->toPlainText();
}
void SeerAsmWidget::setData (const QString& data) {
// ^done,asm_insns=[
// {address="0x000000000040093c",func-name="main()",offset="362",inst="mov $0x400aa9,%edi"},
// {address="0x0000000000400941",func-name="main()",offset="367",inst="call 0x400680 <puts@plt>"},
// {address="0x0000000000400946",func-name="main()",offset="372",inst="mov -0x30(%rbp),%rax"}
// ]
// Clear the document.
plainTextEdit->clear();
// Get a cursor
QTextCursor cursor(plainTextEdit->textCursor());
cursor.movePosition(QTextCursor::Start);
// Prepare the 'data' for parsing.
QString asm_insns_text = Seer::parseFirst(data, "asm_insns=", '[', ']', false);
QStringList asm_list = Seer::parse(asm_insns_text, "", '{', '}', false);
// Loop through the asm list to get maximum field widths.
int address_width = QString("Address").length();
int opcode_width = QString("Opcode").length();
int inst_width = QString("Assembly").length();
for ( const auto& asm_text : asm_list ) {
QString address_text = Seer::parseFirst(asm_text, "address=", '"', '"', false);
QString opcodes_text = Seer::parseFirst(asm_text, "opcodes=", '"', '"', false);
QString inst_text = Seer::parseFirst(asm_text, "inst=", '"', '"', false);
address_width = std::max((qsizetype)address_width, (qsizetype)address_text.length());
opcode_width = std::max((qsizetype)opcode_width, (qsizetype)opcodes_text.length());
inst_width = std::max((qsizetype)inst_width, (qsizetype)inst_text.length());
}
// Write header.
cursor.insertText (QString("Address").leftJustified(address_width, ' ', true), _grayFormat);
cursor.insertText (QString(" "), _defaultFormat);
cursor.insertText (QString("Opcodes").leftJustified(opcode_width, ' ', true), _defaultFormat);
cursor.insertText (QString(" | "), _defaultFormat);
cursor.insertText (QString("Assembly"), _defaultFormat);
cursor.insertText (QString("\n"), _defaultFormat);
// Loop through the asm list and print each line.
for ( const auto& asm_text : asm_list ) {
// Get the strings, with padding.
QString address_text = Seer::parseFirst(asm_text, "address=", '"', '"', false).leftJustified(address_width, ' ', true);
QString opcodes_text = Seer::parseFirst(asm_text, "opcodes=", '"', '"', false).leftJustified(opcode_width, ' ', true);
QString inst_text = Seer::parseFirst(asm_text, "inst=", '"', '"', false).leftJustified(inst_width, ' ', true);
// Write the text, with spacers.
cursor.insertText (address_text, _grayFormat);
cursor.insertText (QString(" "), _defaultFormat);
cursor.insertText (opcodes_text, _defaultFormat);
cursor.insertText (QString(" | "), _defaultFormat);
cursor.insertText (inst_text, _defaultFormat);
// Write eol to document.
cursor.insertText (QString("\n"), _defaultFormat);
}
// Move to the start of the document.
cursor.movePosition(QTextCursor::Start);
plainTextEdit->setTextCursor(cursor);
}