proc,terminal: read command line of new processes (#3346)

Read the command line of the main target process as well as any other
process Delve attaches to in follow exec mode.
The command line can be viewed using the 'target list' command.

In follow exec mode this command line is used to match the follow exec
regex to decide whether or not to attach to a child process.

On macOS or when using rr the list of arguments is not available for
attached processes since there is no way to use the gdb serial protocol
to read it.

Fixes #2242
This commit is contained in:
Alessandro Arzilli
2023-05-09 20:40:00 +02:00
committed by GitHub
parent 801a9109c7
commit e95ae9c21b
18 changed files with 310 additions and 67 deletions

View File

@ -172,6 +172,17 @@ func assertLineNumber(p *proc.Target, t *testing.T, lineno int, descr string) (s
return f, l
}
func assertFunctionName(p *proc.Target, t *testing.T, fnname string, descr string) {
pc := currentPC(p, t)
f, l, fn := p.BinInfo().PCToLine(pc)
if fn == nil {
t.Fatalf("%s expected function %s got %s:%d", descr, fnname, f, l)
}
if fn.Name != fnname {
t.Fatalf("%s expected function %s got %s %s:%d", descr, fnname, fn.Name, f, l)
}
}
func TestExit(t *testing.T) {
protest.AllowRecording(t)
withTestProcess("continuetestprog", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
@ -6118,3 +6129,43 @@ func TestStepShadowConcurrentBreakpoint(t *testing.T) {
}
})
}
func TestFollowExecRegexFilter(t *testing.T) {
skipUnlessOn(t, "follow exec only supported on linux", "linux")
withTestProcessArgs("spawn", t, ".", []string{"spawn", "3"}, 0, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
grp.LogicalBreakpoints[1] = &proc.LogicalBreakpoint{LogicalID: 1, Set: proc.SetBreakpoint{FunctionName: "main.traceme1"}, HitCount: make(map[int64]uint64)}
grp.LogicalBreakpoints[2] = &proc.LogicalBreakpoint{LogicalID: 2, Set: proc.SetBreakpoint{FunctionName: "main.traceme2"}, HitCount: make(map[int64]uint64)}
grp.LogicalBreakpoints[3] = &proc.LogicalBreakpoint{LogicalID: 3, Set: proc.SetBreakpoint{FunctionName: "main.traceme3"}, HitCount: make(map[int64]uint64)}
assertNoError(grp.EnableBreakpoint(grp.LogicalBreakpoints[1]), t, "EnableBreakpoint(main.traceme1)")
assertNoError(grp.EnableBreakpoint(grp.LogicalBreakpoints[3]), t, "EnableBreakpoint(main.traceme3)")
assertNoError(grp.FollowExec(true, "spawn.* child C1"), t, "FollowExec")
assertNoError(grp.Continue(), t, "Continue 1")
assertFunctionName(grp.Selected, t, "main.traceme1", "Program did not continue to the expected location (1)")
assertNoError(grp.Continue(), t, "Continue 2")
assertFunctionName(grp.Selected, t, "main.traceme2", "Program did not continue to the expected location (2)")
assertNoError(grp.Continue(), t, "Continue 3")
assertFunctionName(grp.Selected, t, "main.traceme3", "Program did not continue to the expected location (3)")
err := grp.Continue()
if err != nil {
_, isexited := err.(proc.ErrProcessExited)
if !isexited {
assertNoError(err, t, "Continue 4")
}
} else {
t.Fatal("process did not exit after 4 continues")
}
})
}
func TestReadTargetArguments(t *testing.T) {
protest.AllowRecording(t)
withTestProcessArgs("restartargs", t, ".", []string{"one", "two", "three"}, 0, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
t.Logf("command line: %q\n", p.CmdLine)
if !strings.HasSuffix(p.CmdLine, " one two three") {
t.Fatalf("wrong command line")
}
})
}