mirror of
https://github.com/epasveer/seer.git
synced 2026-08-29 08:34:42 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f4a4e7cdc4 | |||
| aa49afb9c0 | |||
| 2773246157 | |||
| f63fa43b62 | |||
| aba3c788d7 | |||
| 17ad7ce375 | |||
| 01ccb85854 | |||
| b8c66af170 | |||
| 60e1682af4 | |||
| e24d033f63 | |||
| 04f45a89af | |||
| 2a556e698c | |||
| e64e0043e2 | |||
| d53dd8359f | |||
| 552b37fdc8 | |||
| 13ceb02631 | |||
| f0c9b21b86 | |||
| 63a5ab886e | |||
| c9c46c9212 | |||
| 5104b4ec97 | |||
| 4221a79955 | |||
| e759dd4b7f | |||
| 6f40af315d | |||
| da0291e508 |
@@ -27,7 +27,10 @@ jobs:
|
||||
modules: 'qtcharts'
|
||||
|
||||
- name: Where Am I
|
||||
run: pwd; ls -l; lscpu
|
||||
run: |
|
||||
pwd
|
||||
ls -l
|
||||
lscpu
|
||||
|
||||
- name: Versions
|
||||
run: g++ --version
|
||||
@@ -35,18 +38,35 @@ jobs:
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cd src; cmake -B ${{github.workspace}}/src/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
run: |
|
||||
cd src
|
||||
cmake -B ${{github.workspace}}/src/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cd src; cmake --build ${{github.workspace}}/src/build --config ${{env.BUILD_TYPE}} --target seergdb --parallel `grep -c processor /proc/cpuinfo`
|
||||
run: |
|
||||
cd src
|
||||
cmake --build ${{github.workspace}}/src/build --config ${{env.BUILD_TYPE}} --target seergdb --parallel `grep -c processor /proc/cpuinfo`
|
||||
|
||||
- name: Build Result
|
||||
run: cd src; ls -l build/
|
||||
- name: Tar
|
||||
run: |
|
||||
cd src/build
|
||||
cp ../../LICENSE .
|
||||
cp ../../CHANGELOG.md .
|
||||
tar zcvf seergdb.tar.gz LICENSE CHANGELOG.md seergdb
|
||||
|
||||
- name: Build Release
|
||||
uses: AButler/upload-release-assets@v2.0
|
||||
- name: List Results
|
||||
run: |
|
||||
cd src
|
||||
ls -l build/
|
||||
|
||||
- name: Build Ubuntu Release
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
with:
|
||||
files: 'src/build/seergdb'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
automatic_release_tag: "latest"
|
||||
prerelease: true
|
||||
title: "Ubuntu Development Release"
|
||||
files: |
|
||||
src/build/seergdb.tar.gz
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
|
||||
# Seer Change Log
|
||||
|
||||
## [1.12beta] - 2022-MM-DD
|
||||
|
||||
* Added Gdb's Non-Stop mode.
|
||||
- https://sourceware.org/gdb/onlinedocs/gdb/Non_002dStop-Mode.html
|
||||
- A new --non-stop-mode <yes|no> command line flag
|
||||
- A new entry in the Debug dialog.
|
||||
- A new entry in Seer's config dialog under the gdb section.
|
||||
|
||||
## [1.11] - 2022-09-26
|
||||
|
||||
* Thread/Process manager.
|
||||
|
||||
@@ -99,7 +99,7 @@ The main view for Seer looks like:
|
||||
Open Dialog
|
||||
-----------
|
||||
|
||||
When the open exectable dialog is invoked, it looks like this :
|
||||
When the open executable dialog is invoked, it looks like this :
|
||||

|
||||
|
||||
Seer Console
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
seer (1.11) UNRELEASED; urgency=medium
|
||||
seergdb (1.12beta) UNRELEASED; urgency=medium
|
||||
|
||||
* Updated release.
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
# Run from this 'script' directory.
|
||||
#
|
||||
|
||||
# % cat ../src/CMakeLists.txt | sed 's/^project(seer VERSION \b\S\+\b/project(seer VERSION x.x/g'
|
||||
# % cat ../src/CMakeLists.txt | sed 's/^project(seergdb VERSION \b\S\+\b/project(seergdb VERSION x.x/g'
|
||||
# % cat ../src/SeerUtl.cpp | sed 's/SEER_VERSION \"\b\S\+\b\"/SEER_VERSION "x.x"/g'
|
||||
# % cat ../debian/changelog | sed 's/^seer (\b\S\+\b)/seer (x.x)/g'
|
||||
# % cat ../debian/changelog | sed 's/^seergdb (\b\S\+\b)/seergdb (x.x)/g'
|
||||
# % vim ../CHANGELOG.md
|
||||
|
||||
VERSION=""
|
||||
@@ -51,13 +51,13 @@ VERSION_CMAKE="`echo $VERSION | sed -e s/beta/0/g`"
|
||||
echo "Changing Seer files to version ${VERSION}."
|
||||
|
||||
echo "../debian/changelog"
|
||||
sed -i "s/^seer (\b\S\+\b)/seer ($VERSION)/g" ../debian/changelog
|
||||
sed -i "s/^seergdb (\b\S\+\b)/seergdb ($VERSION)/g" ../debian/changelog
|
||||
|
||||
echo "../src/SeerUtl.cpp"
|
||||
sed -i "s/SEER_VERSION \"\b\S\+\b\"/SEER_VERSION \"$VERSION\"/g" ../src/SeerUtl.cpp
|
||||
sed -i "s/SEER_VERSION \"\b\S\+\b\"/SEER_VERSION \"$VERSION\"/g" ../src/SeerUtl.cpp
|
||||
|
||||
echo "../src/CMakeLists.txt"
|
||||
sed -i "s/^project(seer VERSION \b\S\+\b/project(seer VERSION $VERSION_CMAKE/g" ../src/CMakeLists.txt
|
||||
sed -i "s/^project(seergdb VERSION \b\S\+\b/project(seergdb VERSION $VERSION_CMAKE/g" ../src/CMakeLists.txt
|
||||
|
||||
echo "Done."
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
|
||||
project(seergdb VERSION 1.11 LANGUAGES CXX)
|
||||
project(seergdb VERSION 1.12.0 LANGUAGES CXX)
|
||||
|
||||
set(PROJECT_NAME seergdb)
|
||||
|
||||
|
||||
@@ -23,7 +23,11 @@ SeerAboutDialog::SeerAboutDialog (QWidget* parent) : QDialog(parent) {
|
||||
text.replace("VERSIONNUMBER", Seer::version());
|
||||
|
||||
// Put the About text in as markdown. Move back to the begining.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
textBrowser->setMarkdown(text);
|
||||
#else
|
||||
textBrowser->setText(text);
|
||||
#endif
|
||||
textBrowser->moveCursor (QTextCursor::Start);
|
||||
|
||||
// Set the TextBrowser's background to the same as the window's.
|
||||
|
||||
@@ -89,7 +89,7 @@ SeerArrayVisualizerWidget::SeerArrayVisualizerWidget (QWidget* parent) : QWidget
|
||||
QObject::connect(pointsCheckBox, &QCheckBox::clicked, this, &SeerArrayVisualizerWidget::handlePointsCheckBox);
|
||||
QObject::connect(labelsCheckBox, &QCheckBox::clicked, this, &SeerArrayVisualizerWidget::handleLabelsCheckBox);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
QObject::connect(lineTypeButtonGroup, QOverload<int>::of(&QButtonGroup::idClicked), this, &SeerArrayVisualizerWidget::handleLineTypeButtonGroup);
|
||||
#else
|
||||
QObject::connect(lineTypeButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &SeerArrayVisualizerWidget::handleLineTypeButtonGroup);
|
||||
@@ -301,14 +301,22 @@ void SeerArrayVisualizerWidget::handleText (const QString& text) {
|
||||
|
||||
if (id_text.toInt() == _aVariableId) {
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList words = Seer::filterEscapes(Seer::parseFirst(text, "value=", '"', '"', false)).split(' ', Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList words = Seer::filterEscapes(Seer::parseFirst(text, "value=", '"', '"', false)).split(' ', QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
setAVariableAddress(words.first());
|
||||
}
|
||||
|
||||
if (id_text.toInt() == _bVariableId) {
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList words = Seer::filterEscapes(Seer::parseFirst(text, "value=", '"', '"', false)).split(' ', Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList words = Seer::filterEscapes(Seer::parseFirst(text, "value=", '"', '"', false)).split(' ', QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
setBVariableAddress(words.first());
|
||||
}
|
||||
|
||||
@@ -129,6 +129,16 @@ bool SeerConfigDialog::gdbAsyncMode () const {
|
||||
return _gdbConfigPage->gdbAsyncMode();
|
||||
}
|
||||
|
||||
void SeerConfigDialog::setGdbNonStopMode (bool flag) {
|
||||
|
||||
_gdbConfigPage->setGdbNonStopMode(flag);
|
||||
}
|
||||
|
||||
bool SeerConfigDialog::gdbNonStopMode () const {
|
||||
|
||||
return _gdbConfigPage->gdbNonStopMode();
|
||||
}
|
||||
|
||||
void SeerConfigDialog::setGdbHandleTerminatingException (bool flag) {
|
||||
|
||||
_gdbConfigPage->setGdbHandleTerminatingException(flag);
|
||||
|
||||
@@ -32,6 +32,9 @@ class SeerConfigDialog : public QDialog, protected Ui::SeerConfigDialogForm {
|
||||
void setGdbAsyncMode (bool flag);
|
||||
bool gdbAsyncMode () const;
|
||||
|
||||
void setGdbNonStopMode (bool flag);
|
||||
bool gdbNonStopMode () const;
|
||||
|
||||
void setGdbHandleTerminatingException (bool flag);
|
||||
bool gdbHandleTerminatingException () const;
|
||||
|
||||
|
||||
+12
-1
@@ -27,6 +27,7 @@ SeerDebugDialog::SeerDebugDialog (QWidget* parent) : QDialog(parent) {
|
||||
setBreakpointFunctionName("");
|
||||
setShowAssemblyTab(false);
|
||||
setRandomizeStartAddress(false);
|
||||
setNonStopMode(false);
|
||||
setAttachPid(0);
|
||||
setConnectHostPort("");
|
||||
setCoreFilename("");
|
||||
@@ -39,7 +40,7 @@ SeerDebugDialog::SeerDebugDialog (QWidget* parent) : QDialog(parent) {
|
||||
QObject::connect(breakpointInFunctionLineEdit, &QLineEdit::textChanged, this, &SeerDebugDialog::handleBreakpointInFunctionLineEdit);
|
||||
QObject::connect(attachProgramPidToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleProgramPidToolButton);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
QObject::connect(_runModeButtonGroup, QOverload<int>::of(&QButtonGroup::idClicked), this, &SeerDebugDialog::handleRunModeChanged);
|
||||
#else
|
||||
QObject::connect(_runModeButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &SeerDebugDialog::handleRunModeChanged);
|
||||
@@ -137,6 +138,14 @@ bool SeerDebugDialog::randomizeStartAddress () const {
|
||||
return randomizeStartAddressCheckBox->isChecked();
|
||||
}
|
||||
|
||||
void SeerDebugDialog::setNonStopMode (bool flag) {
|
||||
nonStopModeCheckBox->setChecked(flag);
|
||||
}
|
||||
|
||||
bool SeerDebugDialog::nonStopMode () const {
|
||||
return nonStopModeCheckBox->isChecked();
|
||||
}
|
||||
|
||||
void SeerDebugDialog::setCoreFilename (const QString& coreFilename) {
|
||||
loadCoreFilenameLineEdit->setText(coreFilename);
|
||||
}
|
||||
@@ -322,6 +331,7 @@ void SeerDebugDialog::handleRunModeChanged (int id) {
|
||||
breakpointInFunctionLineEdit->setEnabled(false);
|
||||
showAsseblyTabCheckBox->setEnabled(false);
|
||||
randomizeStartAddressCheckBox->setEnabled(false);
|
||||
nonStopModeCheckBox->setEnabled(false);
|
||||
|
||||
// ID == 2
|
||||
attachProgramPidLabel->setEnabled(false);
|
||||
@@ -358,6 +368,7 @@ void SeerDebugDialog::handleRunModeChanged (int id) {
|
||||
breakpointInFunctionLineEdit->setEnabled(true);
|
||||
showAsseblyTabCheckBox->setEnabled(true);
|
||||
randomizeStartAddressCheckBox->setEnabled(true);
|
||||
nonStopModeCheckBox->setEnabled(true);
|
||||
}
|
||||
|
||||
// ID == 2
|
||||
|
||||
@@ -34,6 +34,8 @@ class SeerDebugDialog : public QDialog, protected Ui::SeerDebugDialogForm {
|
||||
bool showAssemblyTab () const;
|
||||
void setRandomizeStartAddress (bool flag);
|
||||
bool randomizeStartAddress () const;
|
||||
void setNonStopMode (bool flag);
|
||||
bool nonStopMode () const;
|
||||
|
||||
// Attach to a running process. "attach".
|
||||
void setAttachPid (int pid);
|
||||
|
||||
+56
-42
@@ -125,8 +125,8 @@
|
||||
<property name="title">
|
||||
<string>Launch Method</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QRadioButton" name="runProgramRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Run the program.</string>
|
||||
@@ -264,34 +264,48 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="showAsseblyTabCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Show Assembly tab at startup.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Assembly tab</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="4" column="0" colspan="5">
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="showAsseblyTabCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Show Assembly tab at startup.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Assembly tab</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="nonStopModeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Allow other threads to continue if any thread reaches a breakpoint.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Non-stop mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="randomizeStartAddressCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Randomize the process start address.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Randomize start address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="randomizeStartAddressCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Randomize the process start address.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Randomize start address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="5">
|
||||
<item row="5" column="0" colspan="5">
|
||||
<widget class="Line" name="line_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="attachProgramRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Attach to an already running program.</string>
|
||||
@@ -301,14 +315,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="attachProgramPidLabel">
|
||||
<property name="text">
|
||||
<string>Process PID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="attachProgramPidLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@@ -330,7 +344,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<item row="7" column="2">
|
||||
<widget class="QToolButton" name="attachProgramPidToolButton">
|
||||
<property name="toolTip">
|
||||
<string>Open a dialog to select a pid on the local system.</string>
|
||||
@@ -340,7 +354,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="3" colspan="2">
|
||||
<item row="7" column="3" colspan="2">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@@ -356,14 +370,14 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="5">
|
||||
<item row="8" column="0" colspan="5">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QRadioButton" name="connectProgramRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Connect to an already running program started with gdbserver.</string>
|
||||
@@ -373,14 +387,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="connectProgramHostPortLabel">
|
||||
<property name="text">
|
||||
<string>Gdbserver</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1" colspan="4">
|
||||
<item row="10" column="1">
|
||||
<widget class="QLineEdit" name="connectProgramHostPortLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@@ -402,14 +416,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="connectProgramSerialLabel">
|
||||
<property name="text">
|
||||
<string>Serial</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QLineEdit" name="connectProgramBaudLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@@ -431,7 +445,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="3" colspan="2">
|
||||
<item row="11" column="2" colspan="3">
|
||||
<spacer name="horizontalSpacer_1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@@ -447,14 +461,14 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="connectProgramParityLabel">
|
||||
<property name="text">
|
||||
<string>Parity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<item row="12" column="1">
|
||||
<widget class="QComboBox" name="connectProgramParityComboBox">
|
||||
<property name="toolTip">
|
||||
<string>Serial port parity setting.</string>
|
||||
@@ -476,7 +490,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="3" colspan="2">
|
||||
<item row="12" column="2" colspan="3">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@@ -492,14 +506,14 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="5">
|
||||
<item row="13" column="0" colspan="5">
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0" colspan="2">
|
||||
<item row="14" column="0">
|
||||
<widget class="QRadioButton" name="loadCoreRadioButton">
|
||||
<property name="toolTip">
|
||||
<string>Load a core file to debug.</string>
|
||||
@@ -509,14 +523,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="loadCoreFilenameLabel">
|
||||
<property name="text">
|
||||
<string>Core file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1" colspan="3">
|
||||
<item row="15" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="loadCoreFilenameLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
@@ -532,7 +546,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="4">
|
||||
<item row="15" column="4">
|
||||
<widget class="QToolButton" name="loadCoreFilenameToolButton">
|
||||
<property name="toolTip">
|
||||
<string>Open a dialog to select a core file.</string>
|
||||
|
||||
@@ -11,7 +11,7 @@ SeerGdbConfigPage::SeerGdbConfigPage(QWidget* parent) : QWidget(parent) {
|
||||
// Connect things.
|
||||
QObject::connect(gdbProgramToolButton, &QToolButton::clicked, this, &SeerGdbConfigPage::handleGdbProgramToolButton);
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
QObject::connect(styleButtonGroup, QOverload<int>::of(&QButtonGroup::idClicked), this, &SeerGdbConfigPage::handleDprintfButtonGroup);
|
||||
#else
|
||||
QObject::connect(styleButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &SeerGdbConfigPage::handleDprintfButtonGroup);
|
||||
@@ -39,6 +39,11 @@ bool SeerGdbConfigPage::gdbAsyncMode () const {
|
||||
return gdbAsyncModeCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool SeerGdbConfigPage::gdbNonStopMode () const {
|
||||
|
||||
return gdbNonStopModeCheckBox->isChecked();
|
||||
}
|
||||
|
||||
bool SeerGdbConfigPage::gdbHandleTerminatingException () const {
|
||||
|
||||
return gdbHandleTerminateExceptionCheckBox->isChecked();
|
||||
@@ -69,6 +74,11 @@ void SeerGdbConfigPage::setGdbAsyncMode (bool flag) {
|
||||
gdbAsyncModeCheckBox->setChecked(flag);
|
||||
}
|
||||
|
||||
void SeerGdbConfigPage::setGdbNonStopMode (bool flag) {
|
||||
|
||||
gdbNonStopModeCheckBox->setChecked(flag);
|
||||
}
|
||||
|
||||
void SeerGdbConfigPage::setGdbHandleTerminatingException (bool flag) {
|
||||
|
||||
gdbHandleTerminateExceptionCheckBox->setChecked(flag);
|
||||
@@ -136,6 +146,7 @@ void SeerGdbConfigPage::reset () {
|
||||
setGdbProgram("/usr/bin/gdb");
|
||||
setGdbArguments("--interpreter=mi");
|
||||
setGdbAsyncMode(true);
|
||||
setGdbNonStopMode(false);
|
||||
setGdbHandleTerminatingException(true);
|
||||
setGdbRandomizeStartAddress(false);
|
||||
setGdbEnablePrettyPrinting(true);
|
||||
|
||||
@@ -15,6 +15,7 @@ class SeerGdbConfigPage : public QWidget, protected Ui::SeerGdbConfigPage {
|
||||
QString gdbProgram () const;
|
||||
QString gdbArguments () const;
|
||||
bool gdbAsyncMode () const;
|
||||
bool gdbNonStopMode () const;
|
||||
bool gdbHandleTerminatingException () const;
|
||||
bool gdbRandomizeStartAddress () const;
|
||||
bool gdbEnablePrettyPrinting () const;
|
||||
@@ -22,6 +23,7 @@ class SeerGdbConfigPage : public QWidget, protected Ui::SeerGdbConfigPage {
|
||||
void setGdbProgram (const QString& program);
|
||||
void setGdbArguments (const QString& arguments);
|
||||
void setGdbAsyncMode (bool flag);
|
||||
void setGdbNonStopMode (bool flag);
|
||||
void setGdbHandleTerminatingException (bool flag);
|
||||
void setGdbRandomizeStartAddress (bool flag);
|
||||
void setGdbEnablePrettyPrinting (bool flag);
|
||||
|
||||
+112
-123
@@ -20,97 +20,6 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="gdbGroupBox">
|
||||
<property name="title">
|
||||
<string>Gdb Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="gdbRandomizeStartAddressCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Randomize the process start address.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Randomize start address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="gdbHandleTerminateExceptionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Handle terminating exceptions when calling functions.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Handle terminating-exception</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="gdbArgumentsLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Arguments to pass to the gdb debugger.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="gdbArgumentsLabel">
|
||||
<property name="text">
|
||||
<string>GDB arguments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="gdbProgramToolButton">
|
||||
<property name="toolTip">
|
||||
<string>Open a file dialog to locate the gdb debugger.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resource.qrc">
|
||||
<normaloff>:/seer/resources/RelaxLightIcons/document-open.svg</normaloff>:/seer/resources/RelaxLightIcons/document-open.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="gdbProgramLabel">
|
||||
<property name="text">
|
||||
<string>GDB program</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="gdbAsyncModeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Turn gdb 'async' mode on or off.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>GDB asycn mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="gdbProgramLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Specify the path and name of the gdb debugger.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="gdbEnablePrettyPrintingCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Show variables with gdb's 'pretty-printing' system.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable pretty-printing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="printPointGroupBox">
|
||||
<property name="title">
|
||||
@@ -190,40 +99,14 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>626</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>626</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<item row="1" column="1" colspan="4">
|
||||
<widget class="QLineEdit" name="functionLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>The name of a function in your program to use.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<item row="2" column="1" colspan="4">
|
||||
<widget class="QLineEdit" name="channelLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>The channel value, if required by the function.</string>
|
||||
@@ -243,18 +126,22 @@
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Specify an alternate gdb program and alternate gdb flags.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Specify an alternate gdb program and alternate gdb flags. </span></p>
|
||||
<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; font-weight:600;"><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=" font-weight:600;">Changing many of these require saving the new configuration and restarting Seer to take effect</span>.</p>
|
||||
<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;">Note, Seer relies on the &quot;mi&quot; interpreter that is built into gdb. If a different debugger is used, it must provide that. So, usually, the &quot;--interpreter=mi&quot; argument is a must.</p>
|
||||
<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;">Async mode allows all gdb actions to happen in the background. This allows interrupting of a running program possible. <span style=" font-weight:600;">Changing this reqires saving the configuration and the restart of Seer to take effect</span>.</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Async mode allows all gdb actions to happen in the background. This allows interrupting of a running program possible. </p>
|
||||
<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;">Non-stop mode, when turned on, will allow other threads to continue to run while another thread reaches a breakpoint.</p>
|
||||
<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;">The gdb debugger normally starts the process at the same address each time. The program's start address can be randomized.</p>
|
||||
<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;">A terminating-exception can happen when gdb is asked to call a function in your program. Like printing the return value from a function. If the function throws an exception, gdb can handle it by suppressing the exception or allowing the program to terminate. See:</p>
|
||||
<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=" font-family:'ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace'; color:#24292f; background-color:transparent;"> unwind-on-terminating-exception on|off</span></p>
|
||||
<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;">The gdb debugger normally starts the process at the same address each time. The process start address can be randomized.</p>
|
||||
<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;">Enabling pretty-printing allows gdb to present certain variables (like std::string) in a pleasing way. Otherwise, the contents of the variables are presented in their full description. (See gdb 'pretty-printing'). Once enabled, it can not be turned off for the Seer session.</p>
|
||||
<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;">Printpoints use the 'dprintf' command available in gdb. The output of 'dprintf' can be sent to the Seer Console ('call') or the GDB output tab ('gdb'). A value of 'agent' is meant for use with a gdbserver.</p>
|
||||
@@ -266,6 +153,108 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="gdbGroupBox">
|
||||
<property name="title">
|
||||
<string>Gdb Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="gdbProgramLabel">
|
||||
<property name="text">
|
||||
<string>GDB program</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="gdbProgramLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Specify the path and name of the gdb debugger.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="gdbProgramToolButton">
|
||||
<property name="toolTip">
|
||||
<string>Open a file dialog to locate the gdb debugger.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resource.qrc">
|
||||
<normaloff>:/seer/resources/RelaxLightIcons/document-open.svg</normaloff>:/seer/resources/RelaxLightIcons/document-open.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="gdbArgumentsLabel">
|
||||
<property name="text">
|
||||
<string>GDB arguments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="gdbArgumentsLineEdit">
|
||||
<property name="toolTip">
|
||||
<string>Arguments to pass to the gdb debugger.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="gdbAsyncModeCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Turn gdb 'async' mode on or off.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Asycn mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="gdbNonStopModeCheckBox">
|
||||
<property name="text">
|
||||
<string>Non-stop mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="gdbRandomizeStartAddressCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Randomize the process start address.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Randomize start address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="gdbHandleTerminateExceptionCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Handle terminating exceptions when calling functions.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Handle terminating-exception</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="gdbEnablePrettyPrintingCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Show variables with gdb's 'pretty-printing' system.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable pretty-printing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>gdbGroupBox</zorder>
|
||||
<zorder>textBrowser</zorder>
|
||||
|
||||
+26
-6
@@ -49,6 +49,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) {
|
||||
_gdbProgram = "/usr/bin/gdb";
|
||||
_gdbArguments = "--interpreter=mi";
|
||||
_gdbASyncMode = true;
|
||||
_gdbNonStopMode = false;
|
||||
_assemblyShowAssemblyTabOnStartup = false;
|
||||
_assemblyDisassemblyFlavor = "att";
|
||||
_gdbHandleTerminatingException = true;
|
||||
@@ -449,6 +450,16 @@ bool SeerGdbWidget::gdbAsyncMode () const {
|
||||
return _gdbASyncMode;
|
||||
}
|
||||
|
||||
void SeerGdbWidget::setGdbNonStopMode (bool flag) {
|
||||
|
||||
_gdbNonStopMode = flag;
|
||||
}
|
||||
|
||||
bool SeerGdbWidget::gdbNonStopMode () const {
|
||||
|
||||
return _gdbNonStopMode;
|
||||
}
|
||||
|
||||
void SeerGdbWidget::setGdbHandleTerminatingException (bool flag) {
|
||||
|
||||
_gdbHandleTerminatingException = flag;
|
||||
@@ -663,6 +674,13 @@ void SeerGdbWidget::handleGdbRunExecutable (const QString& breakMode) {
|
||||
if (gdbAsyncMode()) {
|
||||
handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen.
|
||||
}
|
||||
|
||||
if (gdbNonStopMode()) {
|
||||
handleGdbCommand("-gdb-set pagination off");
|
||||
handleGdbCommand("-gdb-set non-stop on");
|
||||
}else{
|
||||
handleGdbCommand("-gdb-set non-stop off");
|
||||
}
|
||||
}
|
||||
|
||||
// Set dprint parameters.
|
||||
@@ -944,12 +962,6 @@ void SeerGdbWidget::handleGdbCoreFileExecutable () {
|
||||
if (gdbAsyncMode()) {
|
||||
handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen.
|
||||
}
|
||||
|
||||
if (gdbHandleTerminatingException()) {
|
||||
handleGdbCommand("-gdb-set unwind-on-terminating-exception on"); // Turn on terminating exceptions when gdb calls the program's functions.
|
||||
}else{
|
||||
handleGdbCommand("-gdb-set unwind-on-terminating-exception off");
|
||||
}
|
||||
}
|
||||
|
||||
// Set dprint parameters.
|
||||
@@ -1721,7 +1733,11 @@ void SeerGdbWidget::handleGdbDataDeleteExpressions (QString expressionids) {
|
||||
|
||||
}else{
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList ids = expressionids.split(' ', Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList ids = expressionids.split(' ', QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
bool first = true;
|
||||
for (int i=0; i<ids.size(); i++) {
|
||||
@@ -2273,7 +2289,11 @@ void SeerGdbWidget::startGdb () {
|
||||
_gdbProcess->setProgram(gdbProgram());
|
||||
|
||||
// Build the gdb argument list.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList args = gdbArguments().split(' ', Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList args = gdbArguments().split(' ', QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
// Give the gdb process the argument list.
|
||||
_gdbProcess->setArguments(args);
|
||||
|
||||
@@ -73,6 +73,9 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
|
||||
void setGdbAsyncMode (bool flag);
|
||||
bool gdbAsyncMode () const;
|
||||
|
||||
void setGdbNonStopMode (bool flag);
|
||||
bool gdbNonStopMode () const;
|
||||
|
||||
void setGdbHandleTerminatingException (bool flag);
|
||||
bool gdbHandleTerminatingException () const;
|
||||
|
||||
@@ -276,6 +279,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
|
||||
QString _gdbProgram;
|
||||
QString _gdbArguments;
|
||||
bool _gdbASyncMode;
|
||||
bool _gdbNonStopMode;
|
||||
bool _gdbHandleTerminatingException;
|
||||
bool _gdbRandomizeStartAddress;
|
||||
bool _gdbEnablePrettyPrinting;
|
||||
|
||||
@@ -45,7 +45,11 @@ void SeerHelpPageWidget::loadFile (const QString& filename) {
|
||||
void SeerHelpPageWidget::loadText (const QString& text) {
|
||||
|
||||
// Put the Help text in as markdown. Move back to the begining.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
textBrowser->setMarkdown(text);
|
||||
#else
|
||||
textBrowser->setText(text);
|
||||
#endif
|
||||
textBrowser->moveCursor(QTextCursor::Start);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,11 @@ void SeerLibraryBrowserWidget::handleSearchLineEdit (const QString& text) {
|
||||
|
||||
QList<QTreeWidgetItem*> matches;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
matches = libraryTreeWidget->findItems(text, Qt::MatchRegularExpression | Qt::MatchRecursive, 0);
|
||||
#else
|
||||
matches = libraryTreeWidget->findItems(text, Qt::MatchRegExp | Qt::MatchRecursive, 0);
|
||||
#endif
|
||||
|
||||
QList<QTreeWidgetItem*>::const_iterator it = matches.begin();
|
||||
QList<QTreeWidgetItem*>::const_iterator e = matches.end();
|
||||
|
||||
@@ -47,7 +47,11 @@ SeerMainWindow::SeerMainWindow(QWidget* parent) : QMainWindow(parent) {
|
||||
// Set up Styles menu.
|
||||
//
|
||||
_styleMenuActionGroup = new QActionGroup(this);
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
_styleMenuActionGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive);
|
||||
#else
|
||||
_styleMenuActionGroup->setExclusive(true);
|
||||
#endif
|
||||
_styleMenuActionGroup->setEnabled(true);
|
||||
_styleMenuActionGroup->setVisible(true);
|
||||
|
||||
@@ -242,6 +246,14 @@ bool SeerMainWindow::executableRandomizeStartAddress () const {
|
||||
return gdbWidget->gdbRandomizeStartAddress();
|
||||
}
|
||||
|
||||
void SeerMainWindow::setExecutableNonStopMode (bool flag) {
|
||||
gdbWidget->setGdbNonStopMode(flag);
|
||||
}
|
||||
|
||||
bool SeerMainWindow::executableNonStopMode () const {
|
||||
return gdbWidget->gdbNonStopMode();
|
||||
}
|
||||
|
||||
void SeerMainWindow::setExecutablePid (int pid) {
|
||||
gdbWidget->setExecutablePid(pid);
|
||||
}
|
||||
@@ -333,6 +345,7 @@ void SeerMainWindow::handleFileDebug () {
|
||||
dlg.setBreakpointFunctionName(executableBreakpointFunctionName());
|
||||
dlg.setShowAssemblyTab(executableShowAssemblyTab());
|
||||
dlg.setRandomizeStartAddress(executableRandomizeStartAddress());
|
||||
dlg.setNonStopMode(executableNonStopMode());
|
||||
dlg.setAttachPid(executablePid());
|
||||
dlg.setConnectHostPort(executableHostPort());
|
||||
dlg.setConnectSerialBaud(executableSerialBaud());
|
||||
@@ -361,6 +374,7 @@ void SeerMainWindow::handleFileDebug () {
|
||||
setExecutableBreakpointFunctionName(dlg.breakpointFunctionName());
|
||||
setExecutableShowAssemblyTab(dlg.showAssemblyTab());
|
||||
setExecutableRandomizeStartAddress(dlg.randomizeStartAddress());
|
||||
setExecutableNonStopMode(dlg.nonStopMode());
|
||||
setExecutablePid(dlg.attachPid());
|
||||
setExecutableHostPort(dlg.connectHostPort());
|
||||
setExecutableSerialBaud(dlg.connectSerialBaud());
|
||||
@@ -373,6 +387,7 @@ void SeerMainWindow::handleFileDebug () {
|
||||
void SeerMainWindow::handleFileArguments () {
|
||||
|
||||
SeerArgumentsDialog dlg(this);
|
||||
|
||||
dlg.setExecutableArguments(executableArguments());
|
||||
|
||||
int ret = dlg.exec();
|
||||
@@ -438,6 +453,7 @@ void SeerMainWindow::handleSettingsConfiguration () {
|
||||
dlg.setGdbProgram(gdbWidget->gdbProgram());
|
||||
dlg.setGdbArguments(gdbWidget->gdbArguments());
|
||||
dlg.setGdbAsyncMode(gdbWidget->gdbAsyncMode());
|
||||
dlg.setGdbNonStopMode(gdbWidget->gdbNonStopMode());
|
||||
dlg.setGdbHandleTerminatingException(gdbWidget->gdbHandleTerminatingException());
|
||||
dlg.setGdbRandomizeStartAddress(gdbWidget->gdbRandomizeStartAddress());
|
||||
dlg.setGdbEnablePrettyPrinting(gdbWidget->gdbEnablePrettyPrinting());
|
||||
@@ -472,6 +488,7 @@ void SeerMainWindow::handleSettingsConfiguration () {
|
||||
gdbWidget->setGdbProgram(dlg.gdbProgram());
|
||||
gdbWidget->setGdbArguments(dlg.gdbArguments());
|
||||
gdbWidget->setGdbAsyncMode(dlg.gdbAsyncMode());
|
||||
gdbWidget->setGdbNonStopMode(dlg.gdbNonStopMode());
|
||||
gdbWidget->setGdbHandleTerminatingException(dlg.gdbHandleTerminatingException());
|
||||
gdbWidget->setGdbRandomizeStartAddress(dlg.gdbRandomizeStartAddress());
|
||||
gdbWidget->setGdbEnablePrettyPrinting(dlg.gdbEnablePrettyPrinting());
|
||||
@@ -840,6 +857,7 @@ void SeerMainWindow::writeConfigSettings () {
|
||||
settings.setValue("program", gdbWidget->gdbProgram());
|
||||
settings.setValue("arguments", gdbWidget->gdbArguments());
|
||||
settings.setValue("asyncmode", gdbWidget->gdbAsyncMode());
|
||||
settings.setValue("nonstopmode", gdbWidget->gdbNonStopMode());
|
||||
settings.setValue("handleterminatingexception", gdbWidget->gdbHandleTerminatingException());
|
||||
settings.setValue("randomizestartaddress", gdbWidget->gdbRandomizeStartAddress());
|
||||
settings.setValue("enableprettyprinting", gdbWidget->gdbEnablePrettyPrinting());
|
||||
@@ -907,6 +925,7 @@ void SeerMainWindow::readConfigSettings () {
|
||||
gdbWidget->setGdbProgram(settings.value("program", "/usr/bin/gdb").toString());
|
||||
gdbWidget->setGdbArguments(settings.value("arguments", "--interpreter=mi").toString());
|
||||
gdbWidget->setGdbAsyncMode(settings.value("asyncmode", true).toBool());
|
||||
gdbWidget->setGdbNonStopMode(settings.value("nonstopmode", false).toBool());
|
||||
gdbWidget->setGdbHandleTerminatingException(settings.value("handleterminatingexception", true).toBool());
|
||||
gdbWidget->setGdbRandomizeStartAddress(settings.value("randomizestartaddress", false).toBool());
|
||||
gdbWidget->setGdbEnablePrettyPrinting(settings.value("enableprettyprinting", true).toBool());
|
||||
|
||||
@@ -35,6 +35,8 @@ class SeerMainWindow : public QMainWindow, protected Ui::SeerMainWindowForm {
|
||||
bool executableShowAssemblyTab () const;
|
||||
void setExecutableRandomizeStartAddress (bool flag);
|
||||
bool executableRandomizeStartAddress () const;
|
||||
void setExecutableNonStopMode (bool flag);
|
||||
bool executableNonStopMode () const;
|
||||
void setExecutablePid (int pid);
|
||||
int executablePid () const;
|
||||
void setExecutableHostPort (const QString& executableHostPort);
|
||||
|
||||
@@ -154,7 +154,11 @@ void SeerMemoryVisualizerWidget::handleText (const QString& text) {
|
||||
|
||||
if (id_text.toInt() == _variableId) {
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
QStringList words = Seer::filterEscapes(Seer::parseFirst(text, "value=", '"', '"', false)).split(' ', Qt::SkipEmptyParts);
|
||||
#else
|
||||
QStringList words = Seer::filterEscapes(Seer::parseFirst(text, "value=", '"', '"', false)).split(' ', QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
setVariableAddress(words.first());
|
||||
}
|
||||
|
||||
@@ -245,8 +245,11 @@ void SeerSourceBrowserWidget::handleSearchLineEdit (const QString& text) {
|
||||
|
||||
QList<QTreeWidgetItem*> matches;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
matches = sourceTreeWidget->findItems(text, Qt::MatchRegularExpression | Qt::MatchRecursive, 0);
|
||||
//matches = sourceTreeWidget->findItems(text, Qt::MatchWildcard | Qt::MatchRecursive, 0); // Unix style wildcarding. Needs preceeding '*' all the time.
|
||||
#else
|
||||
matches = sourceTreeWidget->findItems(text, Qt::MatchRegExp | Qt::MatchRecursive, 0);
|
||||
#endif
|
||||
|
||||
QList<QTreeWidgetItem*>::const_iterator it = matches.begin();
|
||||
QList<QTreeWidgetItem*>::const_iterator e = matches.end();
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
// Increment this with every release on GitHub.
|
||||
// See scripts/change_versionnumber
|
||||
//
|
||||
#define SEER_VERSION "1.11"
|
||||
#define SEER_VERSION "1.12beta"
|
||||
|
||||
namespace Seer {
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Notes for building Seer with cmake.
|
||||
|
||||
|
||||
% make clean # Clean files.
|
||||
% make seer # Build Seer.
|
||||
% make seergdb # Build Seer.
|
||||
% sudo make install # Install it.
|
||||
|
||||
% cmake --build . --config Release
|
||||
|
||||
@@ -58,6 +58,9 @@ int main (int argc, char* argv[]) {
|
||||
QCommandLineOption startAddressRandomizeOption(QStringList()<<"sar"<<"start-address-randomize", QCoreApplication::translate("main", "Randomize the program's starting address. For --run or --start"), "yes|no");
|
||||
parser.addOption(startAddressRandomizeOption);
|
||||
|
||||
QCommandLineOption nonStopModeOption(QStringList()<<"nsm"<<"non-stop-mode", QCoreApplication::translate("main", "Continue to run other threads at breakpoints. For --run or --start"), "yes|no");
|
||||
parser.addOption(nonStopModeOption);
|
||||
|
||||
QCommandLineOption attachOption(QStringList()<<"attach", QCoreApplication::translate("main", "Attach to a locally running process."), "pid");
|
||||
parser.addOption(attachOption);
|
||||
|
||||
@@ -109,6 +112,7 @@ int main (int argc, char* argv[]) {
|
||||
QString executableBreakpointFunctionName;
|
||||
QString executableShowAssemblyTab;
|
||||
QString executableStartAddressRandomize;
|
||||
QString executableNonStopMode;
|
||||
QString executableCoreFilename;
|
||||
|
||||
if (parser.isSet(runOption)) {
|
||||
@@ -138,6 +142,10 @@ int main (int argc, char* argv[]) {
|
||||
executableStartAddressRandomize = parser.value(startAddressRandomizeOption);
|
||||
}
|
||||
|
||||
if (parser.isSet(nonStopModeOption)) {
|
||||
executableNonStopMode = parser.value(nonStopModeOption);
|
||||
}
|
||||
|
||||
if (parser.isSet(attachOption)) {
|
||||
launchMode = "attach";
|
||||
|
||||
@@ -206,6 +214,19 @@ int main (int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (executableNonStopMode != "") {
|
||||
if (executableNonStopMode == "yes") {
|
||||
seer.setExecutableNonStopMode(true);
|
||||
|
||||
}else if (executableNonStopMode == "no") {
|
||||
seer.setExecutableNonStopMode(false);
|
||||
|
||||
}else{
|
||||
printf("%s: Unknown --non-stop-mode option '%s'\n", qPrintable(QCoreApplication::applicationName()), qPrintable(executableNonStopMode));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
seer.setExecutablePid(executablePid);
|
||||
seer.setExecutableHostPort(executableHostPort);
|
||||
seer.setExecutableCoreFilename(executableCoreFilename);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
hellodebugbreak
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.PHONY: all
|
||||
all: hellodebugbreak
|
||||
|
||||
|
||||
hellodebugbreak: hellodebugbreak.c
|
||||
g++ -g -o hellodebugbreak hellodebugbreak.c
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f hellodebugbreak hellodebugbreak.o
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
/* Copyright (c) 2011-2021, Scott Tsai
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef DEBUG_BREAK_H
|
||||
#define DEBUG_BREAK_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define debug_break __debugbreak
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEBUG_BREAK_USE_TRAP_INSTRUCTION 1
|
||||
#define DEBUG_BREAK_USE_BULTIN_TRAP 2
|
||||
#define DEBUG_BREAK_USE_SIGTRAP 3
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
__inline__ static void trap_instruction(void)
|
||||
{
|
||||
__asm__ volatile("int $0x03");
|
||||
}
|
||||
#elif defined(__thumb__)
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
/* FIXME: handle __THUMB_INTERWORK__ */
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void trap_instruction(void)
|
||||
{
|
||||
/* See 'arm-linux-tdep.c' in GDB source.
|
||||
* Both instruction sequences below work. */
|
||||
#if 1
|
||||
/* 'eabi_linux_thumb_le_breakpoint' */
|
||||
__asm__ volatile(".inst 0xde01");
|
||||
#else
|
||||
/* 'eabi_linux_thumb2_le_breakpoint' */
|
||||
__asm__ volatile(".inst.w 0xf7f0a000");
|
||||
#endif
|
||||
|
||||
/* Known problem:
|
||||
* After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.
|
||||
* 'step' would keep getting stuck on the same instruction.
|
||||
*
|
||||
* Workaround: use the new GDB commands 'debugbreak-step' and
|
||||
* 'debugbreak-continue' that become available
|
||||
* after you source the script from GDB:
|
||||
*
|
||||
* $ gdb -x debugbreak-gdb.py <... USUAL ARGUMENTS ...>
|
||||
*
|
||||
* 'debugbreak-step' would jump over the breakpoint instruction with
|
||||
* roughly equivalent of:
|
||||
* (gdb) set $instruction_len = 2
|
||||
* (gdb) tbreak *($pc + $instruction_len)
|
||||
* (gdb) jump *($pc + $instruction_len)
|
||||
*/
|
||||
}
|
||||
#elif defined(__arm__) && !defined(__thumb__)
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void trap_instruction(void)
|
||||
{
|
||||
/* See 'arm-linux-tdep.c' in GDB source,
|
||||
* 'eabi_linux_arm_le_breakpoint' */
|
||||
__asm__ volatile(".inst 0xe7f001f0");
|
||||
/* Known problem:
|
||||
* Same problem and workaround as Thumb mode */
|
||||
}
|
||||
#elif defined(__aarch64__) && defined(__APPLE__)
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_BULTIN_DEBUGTRAP
|
||||
#elif defined(__aarch64__)
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void trap_instruction(void)
|
||||
{
|
||||
/* See 'aarch64-tdep.c' in GDB source,
|
||||
* 'aarch64_default_breakpoint' */
|
||||
__asm__ volatile(".inst 0xd4200000");
|
||||
}
|
||||
#elif defined(__powerpc__)
|
||||
/* PPC 32 or 64-bit, big or little endian */
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void trap_instruction(void)
|
||||
{
|
||||
/* See 'rs6000-tdep.c' in GDB source,
|
||||
* 'rs6000_breakpoint' */
|
||||
__asm__ volatile(".4byte 0x7d821008");
|
||||
|
||||
/* Known problem:
|
||||
* After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.
|
||||
* 'step' stuck on the same instruction ("twge r2,r2").
|
||||
*
|
||||
* The workaround is the same as ARM Thumb mode: use debugbreak-gdb.py
|
||||
* or manually jump over the instruction. */
|
||||
}
|
||||
#elif defined(__riscv)
|
||||
/* RISC-V 32 or 64-bit, whether the "C" extension
|
||||
* for compressed, 16-bit instructions are supported or not */
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void trap_instruction(void)
|
||||
{
|
||||
/* See 'riscv-tdep.c' in GDB source,
|
||||
* 'riscv_sw_breakpoint_from_kind' */
|
||||
__asm__ volatile(".4byte 0x00100073");
|
||||
}
|
||||
#else
|
||||
#define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_SIGTRAP
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DEBUG_BREAK_IMPL
|
||||
#error "debugbreak.h is not supported on this target"
|
||||
#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_TRAP_INSTRUCTION
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void debug_break(void)
|
||||
{
|
||||
trap_instruction();
|
||||
}
|
||||
#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_DEBUGTRAP
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void debug_break(void)
|
||||
{
|
||||
__builtin_debugtrap();
|
||||
}
|
||||
#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_TRAP
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void debug_break(void)
|
||||
{
|
||||
__builtin_trap();
|
||||
}
|
||||
#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_SIGTRAP
|
||||
#include <signal.h>
|
||||
__attribute__((always_inline))
|
||||
__inline__ static void debug_break(void)
|
||||
{
|
||||
raise(SIGTRAP);
|
||||
}
|
||||
#else
|
||||
#error "invalid DEBUG_BREAK_IMPL value"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifdef _MSC_VER */
|
||||
|
||||
#endif /* ifndef DEBUG_BREAK_H */
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <stdio.h>
|
||||
#include "debugbreak.h"
|
||||
|
||||
//
|
||||
// https://github.com/scottt/debugbreak
|
||||
//
|
||||
int fib(int n) {
|
||||
|
||||
int r;
|
||||
if (n == 0 || n == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
r = fib(n-1) + fib(n-2);
|
||||
|
||||
if (r == 89) {
|
||||
debug_break();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
printf("%d\n", fib(15));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
hellothreads
|
||||
hellothreads2
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hellothreads4
|
||||
@@ -0,0 +1,10 @@
|
||||
.PHONY: all
|
||||
all: hellothreads4
|
||||
|
||||
hellothreads4: hellothreads4.cpp
|
||||
g++ -g -pthread -o hellothreads4 hellothreads4.cpp
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f hellothreads4 hellothreads4.o
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// CPP program to demonstrate multithreading
|
||||
//
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
// A callable object
|
||||
class thread_obj {
|
||||
public:
|
||||
void operator() (int x) {
|
||||
for (int i = 0; i < x; i++) {
|
||||
std::cout << "Thread using function object as callable" << std::endl;
|
||||
sleep(3);
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
|
||||
// This thread is launched by using
|
||||
// function object as callable
|
||||
std::thread th3(thread_obj(), 3);
|
||||
std::thread th4(thread_obj(), 3);
|
||||
std::thread th5(thread_obj(), 3);
|
||||
std::thread th6(thread_obj(), 3);
|
||||
std::thread th7(thread_obj(), 3);
|
||||
std::thread th8(thread_obj(), 3);
|
||||
std::thread th9(thread_obj(), 3);
|
||||
|
||||
// Wait for thread t3 to finish
|
||||
th3.join();
|
||||
th4.join();
|
||||
th5.join();
|
||||
th6.join();
|
||||
th7.join();
|
||||
th8.join();
|
||||
th9.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user