More fork/exec work.

This commit is contained in:
Ernie Pasveer
2022-09-16 19:39:58 -05:00
parent e0bc2df5c9
commit b5b3b3773f
16 changed files with 274 additions and 2 deletions
+28
View File
@@ -0,0 +1,28 @@
When executing a fork() or vfork() call.
^running
*running,thread-id="all"
=thread-group-added,id="i2"
=thread-group-started,id="i2",pid="24125"
=thread-created,id="2",group-id="i2"
=library-loaded,id="/usr/lib64/libstdc++.so.6",target-name="/usr/lib64/libstdc++.so.6",host-name="/usr/lib64/libstdc++.so.6",symbols-loaded="0",thread-group="i2",ranges=[{from="0x00007ffff7a63870",to="0x00007ffff7b558e8"}]
=library-loaded,id="/lib64/libm.so.6",target-name="/lib64/libm.so.6",host-name="/lib64/libm.so.6",symbols-loaded="0",thread-group="i2",ranges=[{from="0x00007ffff76873a0",to="0x00007ffff7723d95"}]
=library-loaded,id="/lib64/libgcc_s.so.1",target-name="/lib64/libgcc_s.so.1",host-name="/lib64/libgcc_s.so.1",symbols-loaded="0",thread-group="i2",ranges=[{from="0x00007ffff745e010",to="0x00007ffff746f365"}]
=library-loaded,id="/lib64/libc.so.6",target-name="/lib64/libc.so.6",host-name="/lib64/libc.so.6",symbols-loaded="0",thread-group="i2",ranges=[{from="0x00007ffff709aaf0",to="0x00007ffff7200afc"}]
=library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i2",ranges=[{from="0x00007ffff7dd4170",to="0x00007ffff7df4090"}]
*stopped,reason="end-stepping-range",frame={addr="0x0000000000400702",func="main",args=[],file="helloinferior.c",fullname="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior.c",line="11",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="0"
^running
*running,thread-id="all"
=thread-group-added,id="i2"
=thread-group-started,id="i2",pid="11514"
=thread-created,id="2",group-id="i2"
*running,thread-id="2"
*stopped,reason="end-stepping-range",frame={addr="0x0000000000400702",func="main",args=[],file="hellovfork.c",fullname="/home/erniep/Development/Peak/src/seer/tests/hellovfork/hellovfork.c",line="11",arch="i386:x86-64"},thread-id="2",stopped-threads="all",core="4"
+24
View File
@@ -137,6 +137,9 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) {
QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, this, &SeerGdbWidget::handleText);
QObject::connect(_gdbMonitor, &GdbMonitor::equalTextOutput, this, &SeerGdbWidget::handleText);
QObject::connect(_gdbMonitor, &GdbMonitor::equalTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText);
QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText);
QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshBreakpointsList, this, &SeerGdbWidget::handleGdbGenericpointList);
QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshStackFrames, this, &SeerGdbWidget::handleGdbStackListFrames);
QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::insertBreakpoint, this, &SeerGdbWidget::handleGdbBreakpointInsert);
@@ -202,6 +205,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) {
QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::refreshThreadFrames, this, &SeerGdbWidget::handleGdbThreadListFrames);
QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile);
QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::selectedThread, this, &SeerGdbWidget::handleGdbThreadSelectId);
QObject::connect(threadManagerWidget, &SeerThreadManagerWidget::forkFollowsModeChanged, this, &SeerGdbWidget::handleGdbForkFollowMode);
QObject::connect(_breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::refreshBreakpointsList, this, &SeerGdbWidget::handleGdbGenericpointList);
QObject::connect(_breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::deleteBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointDelete);
@@ -2496,6 +2500,26 @@ void SeerGdbWidget::setAssemblySymbolDemagling (const QString& onoff) {
}
}
void SeerGdbWidget::handleGdbForkFollowMode (QString mode) {
if (executableLaunchMode() == "") {
return;
}
if (mode == "Parent") {
handleGdbCommand("-gdb-set follow-fork-mode parent");
handleGdbCommand("-gdb-set detach-on-fork on");
}else if (mode == "Child") {
handleGdbCommand("-gdb-set follow-fork-mode child");
handleGdbCommand("-gdb-set detach-on-fork on");
}else if (mode == "Both") {
handleGdbCommand("-gdb-set follow-fork-mode parent");
handleGdbCommand("-gdb-set detach-on-fork off");
}else{
qWarning() << "Invalid 'ForkFollowMode' of '" << mode << "'";
}
}
QString SeerGdbWidget::assemblySymbolDemagling () const {
return _assemblySymbolDemangling;
+1
View File
@@ -247,6 +247,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
void handleGdbSaveBreakpoints ();
void handleGdbAssemblyDisassemblyFlavor ();
void handleGdbAssemblySymbolDemangling ();
void handleGdbForkFollowMode (QString mode);
void handleGdbProcessFinished (int exitCode, QProcess::ExitStatus exitStatus);
void handleGdbProcessErrored (QProcess::ProcessError errorStatus);
+14
View File
@@ -152,6 +152,20 @@ void SeerThreadFramesBrowserWidget::handleText (const QString& text) {
}
}
}else if (text.startsWith("*running,thread-id=")) {
refresh();
}else if (text.startsWith("=thread-created,id=")) {
// =thread-created,id="2",group-id="i2"
refresh();
}else if (text.startsWith("=thread-exited,id=")) {
// =thread-exited,id="2",group-id="i2"
refresh();
}else if (text.startsWith("^error,msg=\"No registers.\"")) {
threadTreeWidget->clear();
+19 -1
View File
@@ -26,7 +26,8 @@ SeerThreadManagerWidget::SeerThreadManagerWidget (QWidget* parent) : QWidget(par
tabWidget->setCornerWidget(refreshToolButton, Qt::TopRightCorner);
// Connect things.
QObject::connect(refreshToolButton, &QToolButton::clicked, this, &SeerThreadManagerWidget::handleRefreshToolButtonClicked);
QObject::connect(refreshToolButton, &QToolButton::clicked, this, &SeerThreadManagerWidget::handleRefreshToolButtonClicked);
QObject::connect(forkFollowsComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SeerThreadManagerWidget::handleForkFollowComboBox);
}
SeerThreadManagerWidget::~SeerThreadManagerWidget () {
@@ -40,9 +41,26 @@ SeerThreadFramesBrowserWidget* SeerThreadManagerWidget::threadFramesBrowserWidge
return _threadFramesBrowserWidget;
}
void SeerThreadManagerWidget::setForkFollowsMode (const QString& mode) {
forkFollowsComboBox->setCurrentText(mode);
}
QString SeerThreadManagerWidget::forkFollowsMode () const {
return forkFollowsComboBox->currentText();
}
void SeerThreadManagerWidget::handleRefreshToolButtonClicked () {
threadFramesBrowserWidget()->refresh();
threadIdsBrowserWidget()->refresh();
}
void SeerThreadManagerWidget::handleForkFollowComboBox (int index) {
Q_UNUSED(index);
emit forkFollowsModeChanged(forkFollowsComboBox->currentText());
}
+8
View File
@@ -19,9 +19,17 @@ class SeerThreadManagerWidget : public QWidget, protected Ui::SeerThreadManagerW
SeerThreadFramesBrowserWidget* threadFramesBrowserWidget ();
signals:
void forkFollowsModeChanged (const QString& mode);
public slots:
void setForkFollowsMode (const QString& mode);
QString forkFollowsMode () const;
private slots:
void handleRefreshToolButtonClicked ();
void handleForkFollowComboBox (int index);
private:
SeerThreadIdsBrowserWidget* _threadIdsBrowserWidget;
+43
View File
@@ -33,6 +33,49 @@
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="forkFollowsLabel">
<property name="text">
<string>Fork follows:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="forkFollowsComboBox">
<item>
<property name="text">
<string>Parent</string>
</property>
</item>
<item>
<property name="text">
<string>Child</string>
</property>
</item>
<item>
<property name="text">
<string>Both</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
+2
View File
@@ -0,0 +1,2 @@
hellocaller
hellocallee
+16
View File
@@ -0,0 +1,16 @@
# This is the default target, which will be built when
# you invoke make
.PHONY: all
all: hellocaller hellocallee
hellocaller: hellocaller.c
g++ -g -o hellocaller hellocaller.c
hellocallee: hellocallee.c
g++ -g -o hellocallee hellocallee.c
.PHONY: clean
clean:
rm -f hellocaller hellocaller.o
rm -f hellocallee hellocallee.o
+14
View File
@@ -0,0 +1,14 @@
#include <stdio.h>
int main(int argc, char *argv[0]) {
for (int i = 1; i < argc; ++i) {
if (i != 1) printf(" ");
printf("%s", argv[i]);
}
printf("\n");
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
int status = 0;
if (pid == 0) {
execlp("./hellocallee", "echo", "aa", "bb", (char*)0);
abort();
}else{
printf("parent %d waiting for %d\n", getpid(), pid);
waitpid(pid, &status, 0);
printf("child %d exited %d\n", pid, status);
}
return status;
}
+30 -1
View File
@@ -1,7 +1,36 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main () {
pid_t pid = fork();
printf("Hello!\n");
if (pid == 0) {
printf("Hello from child! (%d)\n", getpid());
sleep(10);
exit(EXIT_SUCCESS);
}
// To Here and see the difference
printf("Hello from parent! (%d)\n", getpid());
// Comment from here to...
// Parent waits process pid (child)
int status;
waitpid(pid, &status, 0);
// Option is 0 since I check it later
if (WIFSIGNALED(status)){
printf("Error\n");
}else if (WEXITSTATUS(status)){
printf("Child exited normally.\n");
}
return 0;
}
+1
View File
@@ -0,0 +1 @@
hellocfork
+12
View File
@@ -0,0 +1,12 @@
# This is the default target, which will be built when
# you invoke make
.PHONY: all
all: hellovfork
hellovfork: hellovfork.c
g++ -g -o hellovfork hellovfork.c
.PHONY: clean
clean:
rm -f hellovfork hellovfork.o
BIN
View File
Binary file not shown.
+36
View File
@@ -0,0 +1,36 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main () {
pid_t pid = vfork();
if (pid == 0) {
printf("Hello from child! (%d)\n", getpid());
sleep(2);
exit(EXIT_SUCCESS);
}
// To Here and see the difference
printf("Hello from parent! (%d)\n", getpid());
// Comment from here to...
// Parent waits process pid (child)
int status;
waitpid(pid, &status, 0);
// Option is 0 since I check it later
if (WIFSIGNALED(status)){
printf("Error\n");
}else if (WEXITSTATUS(status)){
printf("Child exited normally.\n");
}
return 0;
}