mirror of
https://github.com/epasveer/seer.git
synced 2026-08-29 08:34:42 +08:00
More fork/exec work.
This commit is contained in:
@@ -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"
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
hellocaller
|
||||
hellocallee
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hellocfork
|
||||
@@ -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
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user