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 @@
+
+ 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);