diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55fa335..6e60a7b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@
* Re-added the original struct visualizers as "Basic Struct Visualizer". The advanced
version is called "Struct Visualizer".
* Moved selection of visualizers into a sub menu called "Visualizers" on the menu bar.
+* Added alternate file to load symbols from (instead of the debugee executable.
## [1.13] - 2022-12-02
diff --git a/README.md b/README.md
index 546fae3..a4a4bbc 100644
--- a/README.md
+++ b/README.md
@@ -224,6 +224,11 @@ with no start address randomization.
% seergdb --start --sar yes myprog arg1 arg2 # Debug myprog with its arguments.
# The program's start address is randomized.
+The program's symbols can be taken from a separated file instead of the executable.
+
+ % seergdb --sym myprog.db myprog arg1 arg2 # Debug myprog with its arguments.
+ # Take the symbols from myprog.dbg.
+
See "-h" for the full Seer help.
% seergdb -h
diff --git a/images/opendialog.png b/images/opendialog.png
index 4942e26..29489b4 100644
Binary files a/images/opendialog.png and b/images/opendialog.png differ
diff --git a/src/SeerDebugDialog.cpp b/src/SeerDebugDialog.cpp
index a9830b8..14197c3 100644
--- a/src/SeerDebugDialog.cpp
+++ b/src/SeerDebugDialog.cpp
@@ -20,6 +20,7 @@ SeerDebugDialog::SeerDebugDialog (QWidget* parent) : QDialog(parent) {
// Setup the widgets
setExecutableName("");
+ setExecutableSymbolName("");
setExecutableArguments("");
setBreakpointsFilename("");
setExecutableWorkingDirectory(QDir::currentPath());
@@ -34,6 +35,7 @@ SeerDebugDialog::SeerDebugDialog (QWidget* parent) : QDialog(parent) {
// Connect things.
QObject::connect(executableNameToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleExecutableNameToolButton);
+ QObject::connect(executableSymbolNameToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleExecutableSymbolNameToolButton);
QObject::connect(executableWorkingDirectoryToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleExecutableWorkingDirectoryToolButton);
QObject::connect(loadBreakpointsFilenameToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleLoadBreakpointsFilenameToolButton);
QObject::connect(loadCoreFilenameToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleLoadCoreFilenameToolButton);
@@ -61,6 +63,14 @@ QString SeerDebugDialog::executableName () const {
return executableNameLineEdit->text();
}
+void SeerDebugDialog::setExecutableSymbolName (const QString& executableSymbolName) {
+ executableSymbolNameLineEdit->setText(executableSymbolName);
+}
+
+QString SeerDebugDialog::executableSymbolName () const {
+ return executableSymbolNameLineEdit->text();
+}
+
void SeerDebugDialog::setExecutableWorkingDirectory (const QString& executableWorkingDirectory) {
executableWorkingDirectoryLineEdit->setText(executableWorkingDirectory);
}
@@ -271,6 +281,15 @@ void SeerDebugDialog::handleExecutableNameToolButton () {
}
}
+void SeerDebugDialog::handleExecutableSymbolNameToolButton () {
+
+ QString name = QFileDialog::getOpenFileName(this, "Select a Symbol File for the executable.", executableSymbolName(), "", nullptr, QFileDialog::DontUseNativeDialog);
+
+ if (name != "") {
+ setExecutableSymbolName(name);
+ }
+}
+
void SeerDebugDialog::handleExecutableWorkingDirectoryToolButton () {
QString name = QFileDialog::getExistingDirectory(this, "Select a Working Directory to run in.", executableWorkingDirectory(), QFileDialog::ShowDirsOnly|QFileDialog::DontUseNativeDialog);
diff --git a/src/SeerDebugDialog.h b/src/SeerDebugDialog.h
index f8d6e4a..f3496e0 100644
--- a/src/SeerDebugDialog.h
+++ b/src/SeerDebugDialog.h
@@ -18,6 +18,9 @@ class SeerDebugDialog : public QDialog, protected Ui::SeerDebugDialogForm {
void setExecutableName (const QString& executableName);
QString executableName () const;
+ void setExecutableSymbolName (const QString& executableSymbolName);
+ QString executableSymbolName () const;
+
void setExecutableWorkingDirectory (const QString& executableWorkingDirectory);
QString executableWorkingDirectory () const;
@@ -59,6 +62,7 @@ class SeerDebugDialog : public QDialog, protected Ui::SeerDebugDialogForm {
protected slots:
void handleExecutableNameToolButton ();
+ void handleExecutableSymbolNameToolButton ();
void handleExecutableWorkingDirectoryToolButton ();
void handleLoadBreakpointsFilenameToolButton ();
void handleBreakpointInFunctionLineEdit ();
diff --git a/src/SeerDebugDialog.ui b/src/SeerDebugDialog.ui
index 0118c9f..8de2d2c 100644
--- a/src/SeerDebugDialog.ui
+++ b/src/SeerDebugDialog.ui
@@ -7,24 +7,17 @@
0
0
550
- 777
+ 857
Select Executable to Debug
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
-
- -
+
+
+ 9
+
+
-
Executable Name
@@ -36,6 +29,9 @@
false
+
+ 9
+
-
@@ -47,6 +43,9 @@
The path and name of an executable to debug.
+
+ The path and name of an executable to debug.
+
true
@@ -75,7 +74,61 @@
- -
+
-
+
+
+ Symbol File Name
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ false
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Optional path and name of a symbol file for the executable.
+
+
+ Optional path and name of a symbol file for the executable.
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Open a dialog to select the symbol file for the executable.
+
+
+
+
+
+
+ :/seer/resources/RelaxLightIcons/document-open.svg:/seer/resources/RelaxLightIcons/document-open.svg
+
+
+
+
+
+
+ -
@@ -104,7 +157,10 @@
-
- The working directory path to tell GDB.
+ The working directory path to tell GDB. Default current directory.
+
+
+ The working directory path to tell GDB. Default current directory.
true
@@ -114,7 +170,7 @@
- -
+
-
@@ -563,11 +619,22 @@
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
launchMethodGroupBox
executableNameGroupBox
executableWorkingDirectoryGroupBox
buttonBox
+ executableSymbolNameGroupBox
diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp
index f91844e..a9f1fdb 100644
--- a/src/SeerGdbWidget.cpp
+++ b/src/SeerGdbWidget.cpp
@@ -346,6 +346,17 @@ const QString& SeerGdbWidget::executableName () const {
return _executableName;
}
+void SeerGdbWidget::setExecutableSymbolName (const QString& executableSymbolName) {
+
+ _executableSymbolName = executableSymbolName;
+
+ setNewExecutableFlag(true);
+}
+
+const QString& SeerGdbWidget::executableSymbolName () const {
+ return _executableSymbolName;
+}
+
void SeerGdbWidget::setNewExecutableFlag (bool flag) {
_newExecutableFlag = flag;
@@ -1414,7 +1425,22 @@ void SeerGdbWidget::handleGdbExecutableName () {
return;
}
- handleGdbCommand(QString("-file-exec-and-symbols \"") + executableName() + "\"");
+ //qDebug() << executableName();
+ //qDebug() << executableSymbolName();
+
+ // executableName() is expected to be non-blank.
+
+ // No symbol file? Symbols are expected in the executable.
+ if (executableSymbolName() == "") {
+
+ handleGdbCommand(QString("-file-exec-and-symbols \"") + executableName() + "\"");
+
+ // A symbol file? Open the executable and symbol files separately.
+ }else{
+
+ handleGdbCommand(QString("-file-exec-file \"") + executableName() + "\"");
+ handleGdbCommand(QString("-file-symbol-file \"") + executableSymbolName() + "\"");
+ }
}
void SeerGdbWidget::handleGdbExecutableArguments () {
diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h
index 4372e71..5f4a420 100644
--- a/src/SeerGdbWidget.h
+++ b/src/SeerGdbWidget.h
@@ -29,6 +29,9 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
void setExecutableName (const QString& executableName);
const QString& executableName () const;
+ void setExecutableSymbolName (const QString& executableSymbolName);
+ const QString& executableSymbolName () const;
+
void setNewExecutableFlag (bool flag);
bool newExecutableFlag () const;
@@ -332,6 +335,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
QString _assemblyRegisterFormat;
QString _executableName;
+ QString _executableSymbolName;
QString _executableArguments;
QString _executableWorkingDirectory;
QString _executableBreakpointsFilename;
diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp
index a3b4d5e..46ff61a 100644
--- a/src/SeerMainWindow.cpp
+++ b/src/SeerMainWindow.cpp
@@ -209,6 +209,14 @@ const QString& SeerMainWindow::executableName () const {
return gdbWidget->executableName();
}
+void SeerMainWindow::setExecutableSymbolName (const QString& executableSymbolName) {
+ gdbWidget->setExecutableSymbolName(executableSymbolName);
+}
+
+const QString& SeerMainWindow::executableSymbolName () const {
+ return gdbWidget->executableSymbolName();
+}
+
void SeerMainWindow::setExecutableArguments (const QString& executableArguments) {
gdbWidget->setExecutableArguments(executableArguments);
@@ -380,6 +388,7 @@ void SeerMainWindow::handleFileDebug () {
SeerDebugDialog dlg(this);
dlg.setExecutableName(executableName());
+ dlg.setExecutableSymbolName(executableSymbolName());
dlg.setExecutableWorkingDirectory(executableWorkingDirectory());
dlg.setExecutableArguments(executableArguments());
dlg.setBreakpointsFilename(executableBreakpointsFilename());
@@ -409,6 +418,7 @@ void SeerMainWindow::handleFileDebug () {
}
setExecutableName(dlg.executableName());
+ setExecutableSymbolName(dlg.executableSymbolName());
setExecutableWorkingDirectory(dlg.executableWorkingDirectory());
setExecutableArguments(dlg.executableArguments());
setExecutableBreakpointsFilename(dlg.breakpointsFilename());
diff --git a/src/SeerMainWindow.h b/src/SeerMainWindow.h
index 62160c5..e4b01ff 100644
--- a/src/SeerMainWindow.h
+++ b/src/SeerMainWindow.h
@@ -22,6 +22,8 @@ class SeerMainWindow : public QMainWindow, protected Ui::SeerMainWindowForm {
void setExecutableName (const QString& executableName);
const QString& executableName () const;
+ void setExecutableSymbolName (const QString& executableSymbolName);
+ const QString& executableSymbolName () const;
void setExecutableArguments (const QString& executableArguments);
void setExecutableArguments (const QStringList& executableArguments);
const QString& executableArguments () const;
diff --git a/src/seergdb.cpp b/src/seergdb.cpp
index a2c0942..2ba5f75 100644
--- a/src/seergdb.cpp
+++ b/src/seergdb.cpp
@@ -46,6 +46,9 @@ int main (int argc, char* argv[]) {
QCommandLineOption startOption(QStringList()<<"s"<<"start", QCoreApplication::translate("main", "Load the executable, break in \"main\", and run it."));
parser.addOption(startOption);
+ QCommandLineOption symbolfileOption(QStringList()<<"sym"<<"symbol-file", QCoreApplication::translate("main", "Load symbols from a separate file than the executable."), "symbolfilename");
+ parser.addOption(symbolfileOption);
+
QCommandLineOption breakfileOption(QStringList()<<"bl"<<"break-load", QCoreApplication::translate("main", "Load a previously saved breakpoints file. For --run or --start"), "filename");
parser.addOption(breakfileOption);
@@ -108,6 +111,7 @@ int main (int argc, char* argv[]) {
QString breakMode = "none";
int executablePid = -1;
QString executableHostPort;
+ QString executableSymbolFilename;
QString executableBreakpointsFilename;
QString executableBreakpointFunctionName;
QString executableShowAssemblyTab;
@@ -125,6 +129,10 @@ int main (int argc, char* argv[]) {
breakMode = "inmain";
}
+ if (parser.isSet(symbolfileOption)) {
+ executableSymbolFilename = parser.value(symbolfileOption);
+ }
+
if (parser.isSet(breakfileOption)) {
executableBreakpointsFilename = parser.value(breakfileOption);
}
@@ -178,6 +186,7 @@ int main (int argc, char* argv[]) {
seer.setWindowIcon(QIcon(":/seer/resources/seergdb_64x64.png"));
seer.setExecutableName(executableName);
+ seer.setExecutableSymbolName(executableSymbolFilename);
seer.setExecutableArguments(positionalArguments);
if (executableBreakpointsFilename != "") {
diff --git a/tests/hellosymbolfile/.gitignore b/tests/hellosymbolfile/.gitignore
new file mode 100644
index 0000000..ce95dd3
--- /dev/null
+++ b/tests/hellosymbolfile/.gitignore
@@ -0,0 +1,2 @@
+hellosymbolfile
+hellosymbolfile.dbg
diff --git a/tests/hellosymbolfile/Makefile b/tests/hellosymbolfile/Makefile
new file mode 100644
index 0000000..4355646
--- /dev/null
+++ b/tests/hellosymbolfile/Makefile
@@ -0,0 +1,12 @@
+.PHONY: all
+all: hellosymbolfile
+
+hellosymbolfile: hellosymbolfile.cpp function1.cpp
+ g++ -g -o hellosymbolfile hellosymbolfile.cpp function1.cpp
+ objcopy --only-keep-debug hellosymbolfile hellosymbolfile.dbg
+ strip --strip-debug --strip-unneeded hellosymbolfile
+
+.PHONY: clean
+clean:
+ rm -f hellosymbolfile hellosymbolfile.dbg hellosymbolfile.o function1.o
+
diff --git a/tests/hellosymbolfile/README b/tests/hellosymbolfile/README
new file mode 100644
index 0000000..05fcf96
--- /dev/null
+++ b/tests/hellosymbolfile/README
@@ -0,0 +1 @@
+Simple Hello,World program to test a separate executable and symbol file.
diff --git a/tests/hellosymbolfile/function1.cpp b/tests/hellosymbolfile/function1.cpp
new file mode 100644
index 0000000..61db1f8
--- /dev/null
+++ b/tests/hellosymbolfile/function1.cpp
@@ -0,0 +1,15 @@
+#include "function1.h"
+#include
+#include
+
+void function1 (const std::string& text) {
+
+ int i = 42;
+
+ sleep(2); // Simulate doing work.
+
+ std::cout << text << i << std::endl;
+
+ sleep(3); // Simulate doing work.
+}
+
diff --git a/tests/hellosymbolfile/function1.h b/tests/hellosymbolfile/function1.h
new file mode 100644
index 0000000..8f24a9b
--- /dev/null
+++ b/tests/hellosymbolfile/function1.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include
+
+void function1 (const std::string& text);
+
diff --git a/tests/hellosymbolfile/hellosymbolfile.cpp b/tests/hellosymbolfile/hellosymbolfile.cpp
new file mode 100644
index 0000000..27721f0
--- /dev/null
+++ b/tests/hellosymbolfile/hellosymbolfile.cpp
@@ -0,0 +1,26 @@
+#include
+#include
+
+void function1 (const std::string& message);
+
+int main (int argc, char** argv) {
+
+ int j = 0;
+
+ for (int i=0; i