proc: make sure logical breakpoints map exists (#3115)

The logical breakpoints map was created as a side effect of
createUnrecoveredPanicBreakpoint or createFatalThrowBreakpoint, however
with an executable with incomplete debug info (that must be incomplete
in just the right way) both will fail and the logical breakpoint map
will never be created.

It's unknown how such an executable could be created, one easy way is
to debug a non-go executable.

Fixes #3114
This commit is contained in:
Alessandro Arzilli 2022-08-22 21:48:34 +02:00 committed by GitHub
parent dc76cc250d
commit 81781522c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 4 deletions

5
_fixtures/test.c Normal file

@ -0,0 +1,5 @@
#include <stdio.h>
int main(void) {
printf("hello world!");
}

@ -33,6 +33,9 @@ func NewGroup(t *Target) *TargetGroup {
panic("internal error: target is already part of a group")
}
t.partOfGroup = true
if t.Breakpoints().Logical == nil {
t.Breakpoints().Logical = make(map[int]*LogicalBreakpoint)
}
return &TargetGroup{
RecordingManipulation: t.recman,
targets: []*Target{t},

@ -82,6 +82,13 @@ const (
LinkDisableDWARF
)
// TempFile makes a (good enough) random temporary file name
func TempFile(name string) string {
r := make([]byte, 4)
rand.Read(r)
return filepath.Join(os.TempDir(), fmt.Sprintf("%s.%s", name, hex.EncodeToString(r)))
}
// BuildFixture will compile the fixture 'name' using the provided build flags.
func BuildFixture(name string, flags BuildFlags) Fixture {
if !runningWithFixtures {
@ -100,9 +107,6 @@ func BuildFixture(name string, flags BuildFlags) Fixture {
fixturesDir := FindFixturesDir()
// Make a (good enough) random temporary file name
r := make([]byte, 4)
rand.Read(r)
dir := fixturesDir
path := filepath.Join(fixturesDir, name+".go")
if name[len(name)-1] == '/' {
@ -110,7 +114,7 @@ func BuildFixture(name string, flags BuildFlags) Fixture {
path = ""
name = name[:len(name)-1]
}
tmpfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s.%s", name, hex.EncodeToString(r)))
tmpfile := TempFile(name)
buildFlags := []string{"build"}
var ver goversion.GoVersion

@ -2817,3 +2817,42 @@ func TestClientServer_SinglelineStringFormattedWithBigInts(t *testing.T) {
}
})
}
func TestNonGoDebug(t *testing.T) {
// Test that we can at least set breakpoints while debugging a non-go executable.
if runtime.GOOS != "linux" {
t.Skip()
}
dir := protest.FindFixturesDir()
path := protest.TempFile("testc")
cmd := exec.Command("cc", "-g", "-o", path, filepath.Join(dir, "test.c"))
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("Error compiling %s: %s\n%s", path, err, out)
}
listener, clientConn := service.ListenerPipe()
defer listener.Close()
server := rpccommon.NewServer(&service.Config{
Listener: listener,
ProcessArgs: []string{path},
Debugger: debugger.Config{
Backend: testBackend,
ExecuteKind: debugger.ExecutingExistingFile,
},
})
if err := server.Run(); err != nil {
t.Fatal(err)
}
client := rpc2.NewClientFromConn(clientConn)
defer func() {
client.Detach(true)
}()
_, err := client.CreateBreakpoint(&api.Breakpoint{FunctionName: "C.main", Line: -1})
if err != nil {
t.Fatal(err)
}
}