diff --git a/notes/README.asm b/notes/README.asm index d7a691e..0505797 100644 --- a/notes/README.asm +++ b/notes/README.asm @@ -198,3 +198,6 @@ ] +^done,asm_insns=[{address="0x08048080",func-name="_start",offset="0",opcodes="ba 0e 00 00 00",inst="mov $0xe,%edx"},{address="0x08048085",func-name="_start",offset="5",opcodes="b9 a4 90 04 08",inst="mov $0x80490a4,%ecx"},{address="0x0804808a",func-name="_start",offset="10",opcodes="bb 01 00 00 00",inst="mov $0x1,%ebx"},{address="0x0804808f",func-name="_start",offset="15",opcodes="b8 04 00 00 00",inst="mov $0x4,%eax"},{address="0x08048094",func-name="_start",offset="20",opcodes="cd 80",inst="int $0x80"},{address="0x08048096",func-name="_start",offset="22",opcodes="bb 00 00 00 00",inst="mov $0x0,%ebx"},{address="0x0804809b",func-name="_start",offset="27",opcodes="b8 01 00 00 00",inst="mov $0x1,%eax"},{address="0x080480a0",func-name="_start",offset="32",opcodes="cd 80",inst="int $0x80"}] + + diff --git a/src/SeerAssemblyConfigPage.cpp b/src/SeerAssemblyConfigPage.cpp index 76fee46..9474212 100644 --- a/src/SeerAssemblyConfigPage.cpp +++ b/src/SeerAssemblyConfigPage.cpp @@ -63,6 +63,11 @@ bool SeerAssemblyConfigPage::showOpcodeColumn () const { return showOpcodeCheckBox->isChecked(); } +bool SeerAssemblyConfigPage::showSourceLines () const { + + return showSourceCheckBox->isChecked(); +} + QString SeerAssemblyConfigPage::registerFormat () const { return registerFormatComboBox->currentText(); @@ -113,6 +118,11 @@ void SeerAssemblyConfigPage::setShowOpcodeColumn (bool flag) { showOpcodeCheckBox->setChecked(flag); } +void SeerAssemblyConfigPage::setShowSourceLines (bool flag) { + + showSourceCheckBox->setChecked(flag); +} + void SeerAssemblyConfigPage::setRegisterFormat (const QString& format) { registerFormatComboBox->setCurrentText(format); @@ -127,6 +137,7 @@ void SeerAssemblyConfigPage::reset () { setShowAddressColumn(true); setShowOffsetColumn(false); setShowOpcodeColumn(false); + setShowSourceLines(false); setRegisterFormat("Natural"); } diff --git a/src/SeerAssemblyConfigPage.h b/src/SeerAssemblyConfigPage.h index 72c7c94..38c3c7f 100644 --- a/src/SeerAssemblyConfigPage.h +++ b/src/SeerAssemblyConfigPage.h @@ -19,6 +19,7 @@ class SeerAssemblyConfigPage : public QWidget, protected Ui::SeerAssemblyConfigP bool showAddressColumn () const; bool showOffsetColumn () const; bool showOpcodeColumn () const; + bool showSourceLines () const; QString registerFormat () const; void setShowAssemblyTabOnStartup (bool flag); @@ -28,6 +29,7 @@ class SeerAssemblyConfigPage : public QWidget, protected Ui::SeerAssemblyConfigP void setShowAddressColumn (bool flag); void setShowOffsetColumn (bool flag); void setShowOpcodeColumn (bool flag); + void setShowSourceLines (bool flag); void setRegisterFormat (const QString& format); void reset (); diff --git a/src/SeerAssemblyConfigPage.ui b/src/SeerAssemblyConfigPage.ui index b2fd349..e65a12c 100644 --- a/src/SeerAssemblyConfigPage.ui +++ b/src/SeerAssemblyConfigPage.ui @@ -26,7 +26,7 @@ Assembly Settings - + Show Assembly tab on Seer startup @@ -46,7 +46,7 @@ - + Keep Assembly tab on top @@ -66,7 +66,7 @@ - + Qt::Vertical @@ -115,7 +115,7 @@ - + intel @@ -200,6 +200,54 @@ + + + + Show Columns in Editor + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Address + + + + + + + Offset + + + + + + + Opcode + + + + + + + Source + + + @@ -223,7 +271,7 @@ - + @@ -273,47 +321,6 @@ - - - - Show Columns in Editor - - - - - - - Address - - - - - - - Offset - - - - - - - Opcode - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -344,7 +351,8 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Monospace';">The Assembly Editor can show different columns along side the assembly. These can be quickly changed in the Assembly Editor using ^F.</span></p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" background-color:transparent;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Address</li> <li style=" background-color:transparent;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Offset</li> -<li style=" background-color:transparent;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Opcode</li></ul> +<li style=" background-color:transparent;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Opcode</li> +<li style=" background-color:transparent;" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Source</li></ul> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" background-color:transparent;">In the Register browser, register values can be shown in various formats:</span></p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style="" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" background-color:transparent;">Natural (A predefined format, based on the register name)</span></li> diff --git a/src/SeerConfigDialog.cpp b/src/SeerConfigDialog.cpp index 4d50907..f8dcf59 100644 --- a/src/SeerConfigDialog.cpp +++ b/src/SeerConfigDialog.cpp @@ -349,6 +349,16 @@ bool SeerConfigDialog::assemblyShowOpcodeColumn () const { return _assemblyConfigPage->showOpcodeColumn(); } +void SeerConfigDialog::setAssemblyShowSourceLines (bool flag) { + + _assemblyConfigPage->setShowSourceLines(flag); +} + +bool SeerConfigDialog::assemblyShowSourceLines () const { + + return _assemblyConfigPage->showSourceLines(); +} + void SeerConfigDialog::setAssemblyRegisterFormat (const QString& format) { _assemblyConfigPage->setRegisterFormat(format); diff --git a/src/SeerConfigDialog.h b/src/SeerConfigDialog.h index 8d74b8c..78b3b4c 100644 --- a/src/SeerConfigDialog.h +++ b/src/SeerConfigDialog.h @@ -101,6 +101,9 @@ class SeerConfigDialog : public QDialog, protected Ui::SeerConfigDialogForm { void setAssemblyShowOpcodeColumn (bool flag); bool assemblyShowOpcodeColumn () const; + void setAssemblyShowSourceLines (bool flag); + bool assemblyShowSourceLines () const; + void setAssemblyRegisterFormat (const QString& format); QString assemblyRegisterFormat () const; diff --git a/src/SeerEditorManagerWidget.cpp b/src/SeerEditorManagerWidget.cpp index 47f6f25..d594da4 100644 --- a/src/SeerEditorManagerWidget.cpp +++ b/src/SeerEditorManagerWidget.cpp @@ -26,6 +26,7 @@ SeerEditorManagerWidget::SeerEditorManagerWidget (QWidget* parent) : QWidget(par _showAddressColumn = true; _showOffsetColumn = false; _showOpcodeColumn = false; + _showSourceLines = false; // Setup UI setupUi(this); @@ -207,6 +208,20 @@ bool SeerEditorManagerWidget::assemblyShowOpcodeColumn () const { return _showOpcodeColumn; } +void SeerEditorManagerWidget::setAssemblyShowSourceLines (bool flag) { + + _showSourceLines = flag; + + if (assemblyWidgetTab() != 0) { + assemblyWidgetTab()->setShowSourceLines(_showSourceLines); + } +} + +bool SeerEditorManagerWidget::assemblyShowSourceLines () const { + + return _showSourceLines; +} + SeerEditorManagerFiles SeerEditorManagerWidget::openedFiles () const { SeerEditorManagerFiles files; @@ -890,6 +905,7 @@ SeerEditorWidgetAssembly* SeerEditorManagerWidget::createAssemblyWidgetTab () { assemblyWidget->setShowAddressColumn(assemblyShowAddressColumn()); assemblyWidget->setShowOffsetColumn(assemblyShowOffsetColumn()); assemblyWidget->setShowOpcodeColumn(assemblyShowOpcodeColumn()); + assemblyWidget->setShowSourceLines(assemblyShowSourceLines()); _assemblyIndex= tabWidget->addTab(assemblyWidget, "Assembly"); diff --git a/src/SeerEditorManagerWidget.h b/src/SeerEditorManagerWidget.h index dafb700..c50c79f 100644 --- a/src/SeerEditorManagerWidget.h +++ b/src/SeerEditorManagerWidget.h @@ -41,6 +41,8 @@ class SeerEditorManagerWidget : public QWidget, protected Ui::SeerEditorManagerW bool assemblyShowOffsetColumn () const; void setAssemblyShowOpcodeColumn (bool flag); bool assemblyShowOpcodeColumn () const; + void setAssemblyShowSourceLines (bool flag); + bool assemblyShowSourceLines () const; SeerEditorManagerFiles openedFiles () const; @@ -131,5 +133,6 @@ class SeerEditorManagerWidget : public QWidget, protected Ui::SeerEditorManagerW bool _showAddressColumn; bool _showOffsetColumn; bool _showOpcodeColumn; + bool _showSourceLines; }; diff --git a/src/SeerEditorWidgetAssembly.cpp b/src/SeerEditorWidgetAssembly.cpp index c933966..089d1b9 100644 --- a/src/SeerEditorWidgetAssembly.cpp +++ b/src/SeerEditorWidgetAssembly.cpp @@ -46,6 +46,7 @@ SeerEditorWidgetAssembly::SeerEditorWidgetAssembly(QWidget* parent) : QWidget(pa QObject::connect(showAddressCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowAddressColumn); QObject::connect(showOffsetCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowOffsetColumn); QObject::connect(showOpcodeCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowOpcodeColumn); + QObject::connect(showSourceCheckBox, &QCheckBox::stateChanged, this, &SeerEditorWidgetAssembly::handleShowSourceLines); QObject::connect(assemblyWidget, &SeerEditorWidgetAssemblyArea::showSearchBar, this, &SeerEditorWidgetAssembly::showSearchBar); QObject::connect(_textSearchShortcut, &QShortcut::activated, this, &SeerEditorWidgetAssembly::handleTextSearchShortcut); @@ -56,6 +57,7 @@ SeerEditorWidgetAssembly::SeerEditorWidgetAssembly(QWidget* parent) : QWidget(pa setShowAddressColumn(true); setShowOffsetColumn(false); setShowOpcodeColumn(false); + setShowSourceLines(false); } SeerEditorWidgetAssembly::~SeerEditorWidgetAssembly () { @@ -91,6 +93,11 @@ bool SeerEditorWidgetAssembly::showOpcodeColumn () const { return showOpcodeCheckBox->isChecked(); } +bool SeerEditorWidgetAssembly::showSourceLines () const { + + return showSourceCheckBox->isChecked(); +} + void SeerEditorWidgetAssembly::setKeySettings (const SeerKeySettings& settings) { _keySettings = settings; @@ -156,6 +163,13 @@ void SeerEditorWidgetAssembly::setShowOpcodeColumn (bool flag) { handleShowOpcodeColumn(); } +void SeerEditorWidgetAssembly::setShowSourceLines (bool flag) { + + showSourceCheckBox->setChecked(flag); + + handleShowSourceLines(); +} + void SeerEditorWidgetAssembly::handleSearchLineNumberLineEdit () { QString address = searchLineNumberLineEdit->text(); @@ -236,3 +250,8 @@ void SeerEditorWidgetAssembly::handleShowOpcodeColumn () { assemblyArea()->enableOpcodeArea(showOpcodeColumn()); } +void SeerEditorWidgetAssembly::handleShowSourceLines () { + + assemblyArea()->enableSourceLines(showSourceLines()); +} + diff --git a/src/SeerEditorWidgetAssembly.h b/src/SeerEditorWidgetAssembly.h index ddd912d..ed64be7 100644 --- a/src/SeerEditorWidgetAssembly.h +++ b/src/SeerEditorWidgetAssembly.h @@ -41,6 +41,9 @@ class SeerEditorWidgetAssemblyArea : public SeerPlainTextEdit { void enableOpcodeArea (bool flag); bool opcodeAreaEnabled () const; + void enableSourceLines (bool flag); + bool sourceLinesEnabled () const; + void enableMiniMapArea (bool flag); bool miniMapAreaEnabled () const; @@ -87,6 +90,8 @@ class SeerEditorWidgetAssemblyArea : public SeerPlainTextEdit { void setHighlighterEnabled (bool flag); bool highlighterEnabled () const; + QString sourceForLine (const QString& fullname, const QString& file, int line); + signals: void insertBreakpoint (QString breakpoint); void insertPrintpoint (QString printpoint); @@ -113,6 +118,7 @@ class SeerEditorWidgetAssemblyArea : public SeerPlainTextEdit { private slots: void refreshExtraSelections (); + void updateTextArea (); void updateMarginAreasWidth (int newBlockCount); void updateLineNumberArea (const QRect& rect, int dy); void updateOffsetArea (const QRect& rect, int dy); @@ -125,12 +131,14 @@ class SeerEditorWidgetAssemblyArea : public SeerPlainTextEdit { bool _enableOffsetArea; bool _enableBreakPointArea; bool _enableOpcodeArea; + bool _enableSourceLines; bool _enableMiniMapArea; QVector _breakpointsNumbers; QVector _breakpointsAddresses; QVector _breakpointsEnableds; QList _findExtraSelections; QList _currentLinesExtraSelections; + QList _sourceLinesExtraSelections; SeerEditorWidgetAssemblyLineNumberArea* _lineNumberArea; SeerEditorWidgetAssemblyOffsetArea* _offsetArea; @@ -148,6 +156,14 @@ class SeerEditorWidgetAssemblyArea : public SeerPlainTextEdit { QMap _lineAddressMap; QMap _lineOffsetMap; QMap _lineOpcodeMap; + + // Text from asm_insns command. + QString _asm_insns_text; + + // Source lines for assembly file. + QStringList _fileLines; + QString _fileFullname; + QString _fileName; }; class SeerEditorWidgetAssemblyLineNumberArea : public QWidget { @@ -267,6 +283,7 @@ class SeerEditorWidgetAssembly : public QWidget, protected Ui::SeerEditorWidgetA bool showAddressColumn () const; bool showOffsetColumn () const; bool showOpcodeColumn () const; + bool showSourceLines () const; void setKeySettings (const SeerKeySettings& settings); const SeerKeySettings& keySettings () const; @@ -278,6 +295,7 @@ class SeerEditorWidgetAssembly : public QWidget, protected Ui::SeerEditorWidgetA void setShowAddressColumn (bool flag); void setShowOffsetColumn (bool flag); void setShowOpcodeColumn (bool flag); + void setShowSourceLines (bool flag); private slots: void handleSearchLineNumberLineEdit (); @@ -289,6 +307,7 @@ class SeerEditorWidgetAssembly : public QWidget, protected Ui::SeerEditorWidgetA void handleShowAddressColumn (); void handleShowOffsetColumn (); void handleShowOpcodeColumn (); + void handleShowSourceLines (); signals: private: diff --git a/src/SeerEditorWidgetAssembly.ui b/src/SeerEditorWidgetAssembly.ui index 597d8f7..830d3cd 100644 --- a/src/SeerEditorWidgetAssembly.ui +++ b/src/SeerEditorWidgetAssembly.ui @@ -166,6 +166,9 @@ + + Show assembly address. + Address @@ -173,6 +176,9 @@ + + Show assembly offset. + Offset @@ -180,11 +186,24 @@ + + Show assembly opcodes. + Opcode + + + + Show original source code. + + + Source + + + @@ -218,6 +237,19 @@
QHistoryLineEdit.h
+ + searchTextLineEdit + matchCaseCheckBox + searchDownToolButton + searchUpToolButton + searchLineNumberLineEdit + searchCloseToolButton + refreshToolButton + showAddressCheckBox + showOffsetCheckBox + showOpcodeCheckBox + showSourceCheckBox + diff --git a/src/SeerEditorWidgetAssemblyAreas.cpp b/src/SeerEditorWidgetAssemblyAreas.cpp index d1e4510..30a65e5 100644 --- a/src/SeerEditorWidgetAssemblyAreas.cpp +++ b/src/SeerEditorWidgetAssemblyAreas.cpp @@ -38,6 +38,8 @@ SeerEditorWidgetAssemblyArea::SeerEditorWidgetAssemblyArea(QWidget* parent) : Se _enableBreakPointArea = false; _enableOpcodeArea = false; _enableMiniMapArea = false; + _enableSourceLines = false; + _addressLineMap.clear(); _offsetLineMap.clear(); _lineAddressMap.clear(); @@ -64,6 +66,7 @@ SeerEditorWidgetAssemblyArea::SeerEditorWidgetAssemblyArea(QWidget* parent) : Se enableBreakPointArea(true); enableOpcodeArea(true); enableMiniMapArea(false); // Doesn't work yet. Need to work on the "mini" part. + enableSourceLines(true); QObject::connect(this, &SeerEditorWidgetAssemblyArea::blockCountChanged, this, &SeerEditorWidgetAssemblyArea::updateMarginAreasWidth); QObject::connect(this, &SeerEditorWidgetAssemblyArea::updateRequest, this, &SeerEditorWidgetAssemblyArea::updateLineNumberArea); @@ -142,6 +145,20 @@ bool SeerEditorWidgetAssemblyArea::opcodeAreaEnabled () const { return _enableOpcodeArea; } +void SeerEditorWidgetAssemblyArea::enableSourceLines (bool flag) { + + _enableSourceLines = flag; + + QString addr = address(); + + setAddress(addr, true); +} + +bool SeerEditorWidgetAssemblyArea::sourceLinesEnabled () const { + + return _enableSourceLines; +} + void SeerEditorWidgetAssemblyArea::enableMiniMapArea (bool flag) { _enableMiniMapArea = flag; @@ -154,6 +171,126 @@ bool SeerEditorWidgetAssemblyArea::miniMapAreaEnabled () const { return _enableMiniMapArea; } +void SeerEditorWidgetAssemblyArea::updateTextArea () { + + // + // ^done,asm_insns=[ + // src_and_asm_line={ + // line="72", + // file="helloarray.cpp", + // fullname="/home/erniep/Development/Peak/src/seer/tests/helloarray/helloarray.cpp", + // line_asm_insn=[ + // {address="0x000000000040093c",func-name="main()",offset="362",opcodes="bf a9 0a 40 00",inst="mov $0x400aa9,%edi"}, + // {address="0x0000000000400941",func-name="main()",offset="367",opcodes="e8 3a fd ff ff",inst="call 0x400680 "} + // ] + // }, + // src_and_asm_line={ + // line="73", + // file="helloarray.cpp", + // fullname="/home/erniep/Development/Peak/src/seer/tests/helloarray/helloarray.cpp", + // line_asm_insn=[ + // ] + // }, + // + + // Clear the existing document. + document()->clear(); + + // Clear mappings. + _addressLineMap.clear(); + _offsetLineMap.clear(); + _lineAddressMap.clear(); + _lineOffsetMap.clear(); + _lineOpcodeMap.clear(); + + // Clear 'source line' selections. + _sourceLinesExtraSelections.clear(); + + // Get the list of source and assembly lines. + QString asm_insns_text = Seer::parseFirst(_asm_insns_text, "asm_insns=", '[', ']', false); + + QStringList src_and_asm_list = Seer::parse(asm_insns_text, "src_and_asm_line=", '{', '}', false); + + // Loop through the asm list and print each line. + int lineno = 1; + + for ( const auto& src_and_asm_text : src_and_asm_list ) { + + // Get the strings, with padding. + QString line_text = Seer::parseFirst(src_and_asm_text, "line=", '"', '"', false); + QString file_text = Seer::parseFirst(src_and_asm_text, "file=", '"', '"', false); + QString fullname_text = Seer::parseFirst(src_and_asm_text, "fullname=", '"', '"', false); + + // Print source line? + if (sourceLinesEnabled() == true) { + + // Get source for 'line' + QString sourceLine = sourceForLine(fullname_text, file_text, line_text.toInt()); + + // Write source line to the document. + appendPlainText(sourceLine); + + // Highlight it. + QTextCharFormat sourceLinesFormat = highlighterSettings().get("Margin"); + + QTextBlock block = document()->findBlockByLineNumber(lineno-1); + QTextCursor cursor = textCursor(); + + cursor.setPosition(block.position()); + setTextCursor(cursor); + + QTextEdit::ExtraSelection selection; + selection.format.setForeground(sourceLinesFormat.foreground()); + selection.format.setBackground(sourceLinesFormat.background()); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + + _sourceLinesExtraSelections.append(selection); + + lineno++; + } + + // Get the list of assembly lines. + QString asm_insns_text = Seer::parseFirst(src_and_asm_text, "line_asm_insn=", '[', ']', false); + + QStringList asm_list = Seer::parse(asm_insns_text, "", '{', '}', false); + + for ( const auto& asm_text : asm_list ) { + + // Get the strings, with padding. + QString address_text = Seer::parseFirst(asm_text, "address=", '"', '"', false); + QString funcname_text = Seer::parseFirst(asm_text, "func-name=", '"', '"', false); + QString offset_num = Seer::parseFirst(asm_text, "offset=", '"', '"', false); + QString opcodes_text = Seer::parseFirst(asm_text, "opcodes=", '"', '"', false); + QString inst_text = Seer::parseFirst(asm_text, "inst=", '"', '"', false); + + //qDebug() << inst_text; + + // Write assembly line to the document. + appendPlainText(inst_text); + + // Add to maps + _addressLineMap.insert(address_text.toULongLong(0,0), lineno); + _offsetLineMap.insert(offset_num.toULongLong(0,0), lineno); + _lineAddressMap.insert(lineno, address_text); + _lineOffsetMap.insert(lineno, offset_num.toULongLong(0,0)); + _lineOpcodeMap.insert(lineno, opcodes_text); + + lineno++; + } + } + + // Refresh all the extra selections. + refreshExtraSelections(); + + // Move to the start of the document as a default. + moveCursor(QTextCursor::Start); + + // Move to the line that has our address. + setCurrentLine(_currentAddress); +} + void SeerEditorWidgetAssemblyArea::updateMarginAreasWidth (int newBlockCount) { Q_UNUSED(newBlockCount); @@ -515,7 +652,7 @@ void SeerEditorWidgetAssemblyArea::opcodeAreaPaintEvent (QPaintEvent* event) { return; } - QTextCharFormat format = highlighterSettings().get("Text"); + QTextCharFormat format = highlighterSettings().get("Margin"); QPainter painter(_opcodeArea); painter.fillRect(event->rect(), format.background().color()); @@ -541,8 +678,6 @@ void SeerEditorWidgetAssemblyArea::opcodeAreaPaintEvent (QPaintEvent* event) { opcode = _lineOpcodeMap[blockNumber+1]; } - //qDebug() << opcode; - painter.drawText(0, top, _opcodeArea->width(), fontMetrics().height(), Qt::AlignLeft, opcode); } @@ -724,6 +859,9 @@ void SeerEditorWidgetAssemblyArea::refreshExtraSelections () { // Create an empty list of selections. QList extraSelections; + // Append the 'source lines' extra selections. + extraSelections.append(_sourceLinesExtraSelections); + // Append the 'current lines' extra selections. extraSelections.append(_currentLinesExtraSelections); @@ -755,8 +893,6 @@ const QString& SeerEditorWidgetAssemblyArea::address () const { bool SeerEditorWidgetAssemblyArea::setCurrentLine (const QString& address) { - //qDebug() << address; - // Clear current line selections. _currentLinesExtraSelections.clear(); @@ -799,8 +935,6 @@ bool SeerEditorWidgetAssemblyArea::setCurrentLine (const QString& address) { lineno = address.toInt(&ok, 10); // Try it as an 'int'. lineno == 0 on error. } - //qDebug() << address << lineno; - // Stop if no valid lineno. if (lineno < 1) { return false; @@ -837,8 +971,6 @@ bool SeerEditorWidgetAssemblyArea::setCurrentLine (const QString& address) { void SeerEditorWidgetAssemblyArea::scrollToLine (const QString& address) { - //qDebug() << address; - // Just return. if (address == "") { return; @@ -891,8 +1023,6 @@ void SeerEditorWidgetAssemblyArea::scrollToLine (const QString& address) { } } - //qDebug() << address << lineno << ok; - // Try parsing as an integer. if (ok == false && address.startsWith("0x") == false && address.startsWith("+") == false) { lineno = address.toInt(&ok, 10); // Try it as an 'int'. lineno == 0 on error. @@ -1143,8 +1273,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo return; } - //qDebug() << dlg.breakpointText(); - // Emit the create breakpoint signal. emit insertBreakpoint(dlg.breakpointText()); @@ -1154,8 +1282,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle deleting a breakpoint. if (action == deleteAction) { - //qDebug() << "deleteBreakpoints" << lineno; - // Emit the delete breakpoint signal. emit deleteBreakpoints(QString("%1").arg(breakpointAddressToNumber(address))); @@ -1165,8 +1291,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle enabling a breakpoint. if (action == enableAction) { - //qDebug() << "enableBreakpoints" << lineno; - // Emit the enable breakpoint signal. emit enableBreakpoints(QString("%1").arg(breakpointAddressToNumber(address))); @@ -1176,8 +1300,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle disabling a breakpoint. if (action == disableAction) { - //qDebug() << "disableBreakpoints" << lineno; - // Emit the disable breakpoint signal. emit disableBreakpoints(QString("%1").arg(breakpointAddressToNumber(address))); @@ -1187,8 +1309,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle running to a line number. if (action == runToAddressAction) { - //qDebug() << "runToAddress" << lineno; - // Emit the runToLine signal. emit runToAddress(address); @@ -1198,8 +1318,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle adding memory to visualize. if (action == addMemoryAddressVisualizerAction) { - //qDebug() << "addMemoryVisualizer" << lineno; - // Emit the signals. if (textCursor().selectedText() != "") { emit addMemoryVisualize(textCursor().selectedText()); @@ -1211,8 +1329,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle adding array to visualize. if (action == addArrayAddressVisualizerAction) { - //qDebug() << "addArrayVisualizer" << lineno; - // Emit the signals. if (textCursor().selectedText() != "") { emit addArrayVisualize(textCursor().selectedText()); @@ -1224,8 +1340,6 @@ void SeerEditorWidgetAssemblyArea::showContextMenu (const QPoint& pos, const QPo // Handle adding struct to visualize. if (action == addStructAddressVisualizerAction) { - //qDebug() << "addStructVisualizer" << lineno; - // Emit the signals. if (textCursor().selectedText() != "") { emit addStructVisualize(textCursor().selectedText()); @@ -1287,9 +1401,39 @@ bool SeerEditorWidgetAssemblyArea::highlighterEnabled () const { return _sourceHighlighterEnabled; } -void SeerEditorWidgetAssemblyArea::handleText (const QString& text) { +QString SeerEditorWidgetAssemblyArea::sourceForLine (const QString& fullname, const QString& file, int line) { - //qDebug() << text; + // A new file? Zap the previously cached file. + if (fullname != _fileFullname || file != _fileName) { + _fileLines = QStringList(); + _fileFullname = ""; + _fileName = ""; + } + + // Nothing in cache? Open the file and read it. + if (_fileFullname == "" || _fileName == "") { + _fileFullname = fullname; + _fileName = file; + + bool f = Seer::readFile(_fileFullname, _fileLines); + if (f == false) { + qDebug() << "Can't read:" << _fileFullname; + } + } + + // Return the requested line. + // 'line' is 1 based. We want it to be 0 based. + + line --; + + if (line < 0 || line >= _fileLines.size()) { + return ""; + } + + return _fileLines[line]; +} + +void SeerEditorWidgetAssemblyArea::handleText (const QString& text) { if (text.startsWith("*stopped")) { @@ -1371,160 +1515,11 @@ void SeerEditorWidgetAssemblyArea::handleText (const QString& text) { } } - /* }else if (text.startsWith("^done,asm_insns=")) { - //qDebug() << "asm_insns"; + _asm_insns_text = text; - // - // ^done,asm_insns=[ - // {address="0x000000000040093c",func-name="main()",offset="362",opcodes="bf a9 0a 40 00",inst="mov $0x400aa9,%edi"}, - // {address="0x0000000000400941",func-name="main()",offset="367",opcodes="e8 3a fd ff ff",inst="call 0x400680 "}, - // {address="0x0000000000400946",func-name="main()",offset="372",opcodes="48 8b 45 d0",inst="mov -0x30(%rbp),%rax"}, - // {address="0x000000000040094a",func-name="main()",offset="376",opcodes="48 89 c7",inst="mov %rax,%rdi"}, - // - - - // Clear the existing document. - document()->clear(); - - // Clear mappings. - _addressLineMap.clear(); - _offsetLineMap.clear(); - _lineAddressMap.clear(); - _lineOffsetMap.clear(); - _lineOpcodeMap.clear(); - - // Get the list of assembly lines. - QString asm_insns_text = Seer::parseFirst(text, "asm_insns=", '[', ']', false); - - QStringList asm_list = Seer::parse(asm_insns_text, "", '{', '}', false); - - // Loop through the asm list and print each line. - int lineno = 1; - - for ( const auto& asm_text : asm_list ) { - - // Get the strings, with padding. - QString address_text = Seer::parseFirst(asm_text, "address=", '"', '"', false); - QString offset_num = Seer::parseFirst(asm_text, "offset=", '"', '"', false); - QString opcodes_text = Seer::parseFirst(asm_text, "opcodes=", '"', '"', false); - QString inst_text = Seer::parseFirst(asm_text, "inst=", '"', '"', false); - - //qDebug() << inst_text; - - // Write assembly line to the document. - appendPlainText(QString(" ") + inst_text); - - // Add to maps - _addressLineMap.insert(address_text.toULongLong(0,0), lineno); - _offsetLineMap.insert(offset_num.toULongLong(0,0), lineno); - _lineAddressMap.insert(lineno, address_text); - _lineOffsetMap.insert(lineno, offset_num.toULongLong(0,0)); - _lineOpcodeMap.insert(lineno, opcodes_text); - - lineno++; - } - - // Move to the start of the document as a default. - moveCursor(QTextCursor::Start); - - // Move to the line that has our address. - setCurrentLine(_currentAddress); - - // _currentAddress = ""; // Do we need to reset this? - - */ - - }else if (text.startsWith("^done,asm_insns=")) { - - //qDebug() << "asm_insns"; - - // - // ^done,asm_insns=[ - // src_and_asm_line={ - // line="72", - // file="helloarray.cpp", - // fullname="/home/erniep/Development/Peak/src/seer/tests/helloarray/helloarray.cpp", - // line_asm_insn=[ - // {address="0x000000000040093c",func-name="main()",offset="362",opcodes="bf a9 0a 40 00",inst="mov $0x400aa9,%edi"}, - // {address="0x0000000000400941",func-name="main()",offset="367",opcodes="e8 3a fd ff ff",inst="call 0x400680 "} - // ] - // }, - // src_and_asm_line={ - // line="73", - // file="helloarray.cpp", - // fullname="/home/erniep/Development/Peak/src/seer/tests/helloarray/helloarray.cpp", - // line_asm_insn=[ - // ] - // }, - // - - // Clear the existing document. - document()->clear(); - - // Clear mappings. - _addressLineMap.clear(); - _offsetLineMap.clear(); - _lineAddressMap.clear(); - _lineOffsetMap.clear(); - _lineOpcodeMap.clear(); - - // Get the list of source and assembly lines. - QString asm_insns_text = Seer::parseFirst(text, "asm_insns=", '[', ']', false); - - QStringList src_and_asm_list = Seer::parse(asm_insns_text, "src_and_asm_line=", '{', '}', false); - - // Loop through the asm list and print each line. - int lineno = 1; - - for ( const auto& src_and_asm_text : src_and_asm_list ) { - - // Get the strings, with padding. - QString line_text = Seer::parseFirst(src_and_asm_text, "line=", '"', '"', false); - QString file_text = Seer::parseFirst(src_and_asm_text, "file=", '"', '"', false); - QString fullname_text = Seer::parseFirst(src_and_asm_text, "fullname=", '"', '"', false); - - // Write source line to the document. - appendPlainText(QString(" ") + fullname_text + ":" + line_text); - - lineno++; - - // Get the list of assembly lines. - QString asm_insns_text = Seer::parseFirst(src_and_asm_text, "line_asm_insn=", '[', ']', false); - - QStringList asm_list = Seer::parse(asm_insns_text, "", '{', '}', false); - - for ( const auto& asm_text : asm_list ) { - - // Get the strings, with padding. - QString address_text = Seer::parseFirst(asm_text, "address=", '"', '"', false); - QString funcname_text = Seer::parseFirst(asm_text, "func-name=", '"', '"', false); - QString offset_num = Seer::parseFirst(asm_text, "offset=", '"', '"', false); - QString opcodes_text = Seer::parseFirst(asm_text, "opcodes=", '"', '"', false); - QString inst_text = Seer::parseFirst(asm_text, "inst=", '"', '"', false); - - //qDebug() << inst_text; - - // Write assembly line to the document. - appendPlainText(QString(" ") + inst_text); - - // Add to maps - _addressLineMap.insert(address_text.toULongLong(0,0), lineno); - _offsetLineMap.insert(offset_num.toULongLong(0,0), lineno); - _lineAddressMap.insert(lineno, address_text); - _lineOffsetMap.insert(lineno, offset_num.toULongLong(0,0)); - _lineOpcodeMap.insert(lineno, opcodes_text); - - lineno++; - } - } - - // Move to the start of the document as a default. - moveCursor(QTextCursor::Start); - - // Move to the line that has our address. - setCurrentLine(_currentAddress); + updateTextArea(); // This function does all the work on _asm_insns_text. } } diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index a0e3881..a209dc7 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -2115,7 +2115,7 @@ void SeerGdbWidget::handleGdbGetAssembly (QString address) { return; } - //qDebug() << "Getting assembly for address" << address; + //qDebug() << "Getting assembly for address" << address; handleGdbCommand("-data-disassemble -a " + address + " -- 2"); // Use '2' to add opcodes. '0' has no opcodes. } @@ -2126,7 +2126,7 @@ void SeerGdbWidget::handleGdbGetSourceAndAssembly (QString address) { return; } - //qDebug() << "Getting source and assembly for address" << address; + //qDebug() << "Getting source and assembly for address" << address; handleGdbCommand("-data-disassemble -a " + address + " -- 5"); } @@ -2383,6 +2383,7 @@ void SeerGdbWidget::writeSettings () { settings.setValue("assemblyshowaddresscolumn", assemblyShowAddressColumn()); settings.setValue("assemblyshowoffsetcolumn", assemblyShowOffsetColumn()); settings.setValue("assemblyshowopcodecolumn", assemblyShowOpcodeColumn()); + settings.setValue("assemblyshowsourcelines", assemblyShowSourceLines()); } settings.endGroup(); settings.beginGroup("gdboutputlog"); { @@ -2497,6 +2498,7 @@ void SeerGdbWidget::readSettings () { setAssemblyShowAddressColumn(settings.value("assemblyshowaddresscolumn", true).toBool()); setAssemblyShowOffsetColumn(settings.value("assemblyshowoffsetcolumn", false).toBool()); setAssemblyShowOpcodeColumn(settings.value("assemblyshowopcodecolumn", false).toBool()); + setAssemblyShowSourceLines(settings.value("assemblyshowsourcelines", false).toBool()); } settings.endGroup(); settings.beginGroup("gdboutputlog"); { @@ -2886,6 +2888,16 @@ bool SeerGdbWidget::assemblyShowOpcodeColumn () const { return editorManager()->assemblyShowOpcodeColumn(); } +void SeerGdbWidget::setAssemblyShowSourceLines (bool flag) { + + editorManager()->setAssemblyShowSourceLines(flag); +} + +bool SeerGdbWidget::assemblyShowSourceLines () const { + + return editorManager()->assemblyShowSourceLines(); +} + void SeerGdbWidget::setAssemblyRegisterFormat (const QString& format) { _assemblyRegisterFormat = format; diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index f086b4c..42f951b 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -149,6 +149,9 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void setAssemblyShowOpcodeColumn (bool flag); bool assemblyShowOpcodeColumn () const; + void setAssemblyShowSourceLines (bool flag); + bool assemblyShowSourceLines () const; + void setAssemblyRegisterFormat (const QString& format); QString assemblyRegisterFormat () const; diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index 434fa0f..e881268 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -492,6 +492,7 @@ void SeerMainWindow::handleSettingsConfiguration () { dlg.setAssemblyShowAddressColumn(gdbWidget->assemblyShowAddressColumn()); dlg.setAssemblyShowOffsetColumn(gdbWidget->assemblyShowOffsetColumn()); dlg.setAssemblyShowOpcodeColumn(gdbWidget->assemblyShowOpcodeColumn()); + dlg.setAssemblyShowSourceLines(gdbWidget->assemblyShowSourceLines()); dlg.setAssemblyRegisterFormat(gdbWidget->assemblyRegisterFormat()); dlg.setSeerConsoleMode(gdbWidget->consoleMode()); dlg.setSeerConsoleScrollLines(gdbWidget->consoleScrollLines()); @@ -530,6 +531,7 @@ void SeerMainWindow::handleSettingsConfiguration () { gdbWidget->setAssemblyShowAddressColumn(dlg.assemblyShowAddressColumn()); gdbWidget->setAssemblyShowOffsetColumn(dlg.assemblyShowOffsetColumn()); gdbWidget->setAssemblyShowOpcodeColumn(dlg.assemblyShowOpcodeColumn()); + gdbWidget->setAssemblyShowSourceLines(dlg.assemblyShowSourceLines()); gdbWidget->setAssemblyRegisterFormat(dlg.assemblyRegisterFormat()); gdbWidget->setConsoleMode(dlg.seerConsoleMode()); gdbWidget->setConsoleScrollLines(dlg.seerConsoleScrollLines()); diff --git a/src/SeerUtl.cpp b/src/SeerUtl.cpp index e5483e3..e8a06cd 100644 --- a/src/SeerUtl.cpp +++ b/src/SeerUtl.cpp @@ -523,7 +523,10 @@ namespace Seer { // Read the file line-by-line and build up the string list. while (file.atEnd() == false) { - lines.append(file.readLine()); + + QString line = file.readLine(); + line.chop(1); + lines.append(line); } file.close(); diff --git a/src/seergdb.cpp b/src/seergdb.cpp index b95d032..a2c0942 100644 --- a/src/seergdb.cpp +++ b/src/seergdb.cpp @@ -73,7 +73,7 @@ int main (int argc, char* argv[]) { QCommandLineOption configOption(QStringList()<<"config", QCoreApplication::translate("main", "Launch with config dialog.\nSave settings with:\n 'Settings->Save Configuration'")); parser.addOption(configOption); - QCommandLineOption xxdebugOption(QStringList()<<"xxdebug", QCoreApplication::translate("main", "Turn on internal Seer debugging messages.")); + QCommandLineOption xxdebugOption(QStringList()<<"xxx", QCoreApplication::translate("main", "Turn on internal Seer debugging messages.")); parser.addOption(xxdebugOption);