Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Picking offset of g struct inside TLS correctly #177

Merged
merged 2 commits into from
Jul 28, 2015

Conversation

aarzilli
Copy link
Member

The change to proc.(*Thread).executeStackProgram is necessary because it seems that cgo programs start at an address that FDEForPC doesn't know about.

@aarzilli
Copy link
Member Author

PS. ocfaode in dwarf/op/op.go seemed like a variable rename gone wrong, I've taken the liberty of renaming it to opcode.

@derekparker
Copy link
Member

This looks great. If you can port your code over for directly reading from TLS as was discussed in https://groups.google.com/d/msgid/delve-dev/55AFE938.5000300%40gmail.com I'll verify and merge as soon as I get back to my machine on Saturday.

@aarzilli
Copy link
Member Author

the patch doesn't work _fixtures/testnextnethttp has the runtime.iscgo flag set but is internally linked so the offset comes out -16, runtime.iscgo is not the right thing to check

@aarzilli
Copy link
Member Author

I can't test the second commit on OS X.

@derekparker
Copy link
Member

Just tried to verify on OSX, ran into some compilation issues, fixed them, and then got a panic when running the tests. Here's the diff:


derekparker at delve(aarzilli-cgo-tls-offset-bug*) gd                                                                      {2}
diff --git a/proc/threads_darwin.c b/proc/threads_darwin.c
index b02febd..a0988b6 100644
--- a/proc/threads_darwin.c
+++ b/proc/threads_darwin.c
@@ -53,7 +53,7 @@ get_registers(mach_port_name_t task, x86_thread_state64_t *state) {
 kern_return_t
 get_identity(mach_port_name_t task, thread_identifier_info_data_t *idinfo) {
        mach_msg_type_number_t idinfoCount = THREAD_IDENTIFIER_INFO_COUNT;
-       return thread_info(task, THREAD_IDENTITY_INFO, (thread_info_t)idinfo, &idinfoCount);
+       return thread_info(task, THREAD_IDENTIFIER_INFO, (thread_info_t)idinfo, &idinfoCount);
 }

 kern_return_t
diff --git a/proc/threads_darwin.h b/proc/threads_darwin.h
index 93310f7..156c410 100644
--- a/proc/threads_darwin.h
+++ b/proc/threads_darwin.h
@@ -27,3 +27,6 @@ resume_thread(thread_act_t);

 kern_return_t
 set_registers(mach_port_name_t, x86_thread_state64_t*);
+
+kern_return_t
+get_identity(mach_port_name_t, thread_identifier_info_data_t *);
derekparker at delve(aarzilli-cgo-tls-offset-bug*)

And heres the panic:

derekparker at delve(aarzilli-cgo-tls-offset-bug*) make
go test github.com/derekparker/delve/terminal github.com/derekparker/delve/dwarf/frame github.com/derekparker/delve/dwarf/op github.com/derekparker/delve/dwarf/util github.com/derekparker/delve/source github.com/derekparker/delve/dwarf/line
ok      github.com/derekparker/delve/terminal   0.028s
ok      github.com/derekparker/delve/dwarf/frame        0.007s
ok      github.com/derekparker/delve/dwarf/op   0.006s
ok      github.com/derekparker/delve/dwarf/util 0.008s
ok      github.com/derekparker/delve/source     0.008s
ok      github.com/derekparker/delve/dwarf/line 0.241s
go test -c github.com/derekparker/delve/proc && codesign -s dbg-cert ./proc.test && ./proc.test  && rm ./proc.test
--- FAIL: TestExit-4 (0.22s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
        panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x18 pc=0x40665e2]

goroutine 5 [running]:
testing.func·006()
        /usr/local/go/src/testing/testing.go:441 +0x181
github.com/derekparker/delve/proc.(*Thread).EvalPackageVariable(0x0, 0x442e590, 0x14, 0x449fd60, 0x0, 0x0)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/variables.go:279 +0x42
github.com/derekparker/delve/proc.(*Process).getGoInformation(0xc208082160, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc.go:688 +0xb0
github.com/derekparker/delve/proc.initializeDebugProcess(0xc208082160, 0xc20806c500, 0x4a, 0x0, 0x0, 0x0, 0x0)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc.go:599 +0x5ad
github.com/derekparker/delve/proc.Launch(0xc208217e78, 0x1, 0x1, 0x10, 0x0, 0x0)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc_darwin.go:77 +0x867
github.com/derekparker/delve/proc.withTestProcess(0x441ea90, 0x10, 0xc208086090, 0xc208217f60)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc_test.go:29 +0x110
github.com/derekparker/delve/proc.TestExit(0xc208086090)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc_test.go:98 +0x5b
testing.tRunner(0xc208086090, 0x45c0fa0)
        /usr/local/go/src/testing/testing.go:447 +0xbf
created by testing.RunTests
        /usr/local/go/src/testing/testing.go:555 +0xa8b

goroutine 1 [chan receive]:
testing.RunTests(0x449d5d0, 0x45c0fa0, 0x16, 0x16, 0x56c96906ea076d01)
        /usr/local/go/src/testing/testing.go:556 +0xad6
testing.(*M).Run(0xc20806c320, 0x0)
        /usr/local/go/src/testing/testing.go:485 +0x6c
github.com/derekparker/delve/proc/test.RunTestsWithFixtures(0xc20806c320, 0xc20806c320)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/test/support.go:59 +0x33
github.com/derekparker/delve/proc.TestMain(0xc20806c320)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc_test.go:24 +0x28
main.main()
        github.com/derekparker/delve/proc/_test/_testmain.go:92 +0x1d1

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 6 [chan receive, locked to thread]:
github.com/derekparker/delve/proc.(*Process).handlePtraceFuncs(0xc208082160)
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc.go:674 +0x5d
created by github.com/derekparker/delve/proc.New
        /Users/derekparker/go/src/github.com/derekparker/delve/proc/proc.go:67 +0x215
make: *** [test] Error 2

I can investigate tomorrow if you don't have access to an OSX machine.

@aarzilli
Copy link
Member Author

That panic seems unrelated to the OS X-specific change. Will this line:
th := dbp.Threads[dbp.Pid]
not always return non-nil on OSX?

@derekparker
Copy link
Member

Yes it is possible. The reason is because on OSX the key in that map is the threads' mach port, which is distinct from the PID. It is preferable to use dbp.CurrentThread as that will always be set correctly.

Here is my current diff:

diff --git a/proc/proc.go b/proc/proc.go
index 61748f4..46150ab 100644
--- a/proc/proc.go
+++ b/proc/proc.go
@@ -683,15 +683,14 @@ func (dbp *Process) execPtraceFunc(fn func()) {
 }

 func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error) {
-   th := dbp.Threads[dbp.Pid]
-
-   vv, err := th.EvalPackageVariable("runtime.buildVersion")
+   vv, err := dbp.CurrentThread.EvalPackageVariable("runtime.buildVersion")
    if err != nil {
        err = fmt.Errorf("Could not determine version number: %v\n", err)
        return
    }

-   ver, ok := parseVersionString(vv.Value)
+   var ok bool
+   ver, ok = parseVersionString(vv.Value)
    if !ok {
        err = fmt.Errorf("Could not parse version number: %s\n", vv.Value)
    }
@@ -709,6 +708,5 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error)
            break
        }
    }
-
    return
 }
diff --git a/proc/threads_darwin.c b/proc/threads_darwin.c
index b02febd..a0988b6 100644
--- a/proc/threads_darwin.c
+++ b/proc/threads_darwin.c
@@ -53,7 +53,7 @@ get_registers(mach_port_name_t task, x86_thread_state64_t *state) {
 kern_return_t
 get_identity(mach_port_name_t task, thread_identifier_info_data_t *idinfo) {
    mach_msg_type_number_t idinfoCount = THREAD_IDENTIFIER_INFO_COUNT;
-   return thread_info(task, THREAD_IDENTITY_INFO, (thread_info_t)idinfo, &idinfoCount);
+   return thread_info(task, THREAD_IDENTIFIER_INFO, (thread_info_t)idinfo, &idinfoCount);
 }

 kern_return_t
diff --git a/proc/threads_darwin.h b/proc/threads_darwin.h
index 93310f7..156c410 100644
--- a/proc/threads_darwin.h
+++ b/proc/threads_darwin.h
@@ -27,3 +27,6 @@ resume_thread(thread_act_t);

 kern_return_t
 set_registers(mach_port_name_t, x86_thread_state64_t*);
+
+kern_return_t
+get_identity(mach_port_name_t, thread_identifier_info_data_t *);

And here is the error I get when running tests:

--- FAIL: TestGetG-4 (0.39s)
        proc_test.go:609: nocgo: g is: &{1 135408 0 135125 garbage collection /usr/local/go/src/runtime/asm_amd64.s 102 0xc20a35f180 108256 0xc209275500}
        proc_test.go:31: Launch(): decoding dwarf section info at offset 0x0: too short
FAIL
make: *** [test] Error 1

@aarzilli
Copy link
Member Author

Some problem with reader.(*Reader).NextCompileUnit on externally linked executables? Weird.

@aarzilli
Copy link
Member Author

PS. isn't this the same thing as Issue #79?

@derekparker
Copy link
Member

Yes it is, was just going to link to it, hah.

It looks like with this patch you're already checking for external linkage with isextld, correct? If we can use that to determine external linkage, we could combine that information with the Go version, and if not externally linked and Go version < 1.5 then we can either spit out an error message saying it's not supported (easiest path for now, especially with 1.5 coming soon and Delve still pre 1.0) OR we could simply return a known error from this function and trigger a re compilation using external linkage which should solve the missing DWARF section issue. The latter would be more convenient for the user, and shouldn't be TOO much work.

Does this patch work on Go 1.5beta2? I haven't tested yet, and won't have time to for a few hours. If it does work, we can just ignore the issue for now and fix it in a separate patch, so we don't continue piling onto this one.

@aarzilli
Copy link
Member Author

It looks like with this patch you're already checking for external linkage with isextld, correct?

Yes, but the code that computes isextld is the one that's failing, because it needs dwarf info, so it doesn't help.

Does this patch work on Go 1.5beta2?

I haven't tested it, I do not know what the state of delve is on 1.5.

@derekparker
Copy link
Member

Right, good point, should have thought that through more before posting, trying to juggle too many things at the same time.

Let me test this out a bit more, and try to think through a solution to this linkage issue on OSX.

hardwareBreakpointUsage: make([]bool, 4),
}
}

func (a *AMD64) SetCurGInstructions(ver GoVersion, isextld bool) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to SetGStructOffset.

@derekparker
Copy link
Member

I'd like to merge this in, regardless of Go1.5 issues on OSX (golang/go#11887) and CGO/Go1.4.2 issues on OSX (https://github.com/derekparker/delve/issues/79) as I believe these are separate concerns.

Aside from the comments above, can you apply the following patch to this branch. The only major change is (for now) ignoring the CGO test you added on OSX for Go on Darwin with version < 1.5.

diff --git a/proc/proc.go b/proc/proc.go
index 61748f4..04b0905 100644
--- a/proc/proc.go
+++ b/proc/proc.go
@@ -683,9 +683,7 @@ func (dbp *Process) execPtraceFunc(fn func()) {
 }

 func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error) {
-   th := dbp.Threads[dbp.Pid]
-
-   vv, err := th.EvalPackageVariable("runtime.buildVersion")
+   vv, err := dbp.CurrentThread.EvalPackageVariable("runtime.buildVersion")
    if err != nil {
        err = fmt.Errorf("Could not determine version number: %v\n", err)
        return
@@ -709,6 +707,5 @@ func (dbp *Process) getGoInformation() (ver GoVersion, isextld bool, err error)
            break
        }
    }
-
    return
 }
diff --git a/proc/proc_test.go b/proc/proc_test.go
index 8e09ca0..145bcd2 100644
--- a/proc/proc_test.go
+++ b/proc/proc_test.go
@@ -9,6 +9,7 @@ import (
    "os"
    "path/filepath"
    "runtime"
+   "strings"
    "testing"
    "time"

@@ -617,6 +618,11 @@ func TestGetG(t *testing.T) {
        testGSupportFunc("nocgo", t, p, fixture)
    })

+   // On OSX with Go < 1.5 CGO is not supported due to: https://github.com/golang/go/issues/8973
+   if runtime.GOOS == "darwin" && strings.Contains(runtime.Version(), "1.4") {
+       return
+   }
+
    withTestProcess("cgotest", t, func(p *Process, fixture protest.Fixture) {
        testGSupportFunc("cgo", t, p, fixture)
    })
diff --git a/proc/threads_darwin.c b/proc/threads_darwin.c
index b02febd..a0988b6 100644
--- a/proc/threads_darwin.c
+++ b/proc/threads_darwin.c
@@ -53,7 +53,7 @@ get_registers(mach_port_name_t task, x86_thread_state64_t *state) {
 kern_return_t
 get_identity(mach_port_name_t task, thread_identifier_info_data_t *idinfo) {
    mach_msg_type_number_t idinfoCount = THREAD_IDENTIFIER_INFO_COUNT;
-   return thread_info(task, THREAD_IDENTITY_INFO, (thread_info_t)idinfo, &idinfoCount);
+   return thread_info(task, THREAD_IDENTIFIER_INFO, (thread_info_t)idinfo, &idinfoCount);
 }

 kern_return_t
diff --git a/proc/threads_darwin.h b/proc/threads_darwin.h
index 93310f7..156c410 100644
--- a/proc/threads_darwin.h
+++ b/proc/threads_darwin.h
@@ -27,3 +27,6 @@ resume_thread(thread_act_t);

 kern_return_t
 set_registers(mach_port_name_t, x86_thread_state64_t*);
+
+kern_return_t
+get_identity(mach_port_name_t, thread_identifier_info_data_t *);

… the value of runtime.buildVersion and presence of compile units created by GNU AS, instead of being fixed to -16
@derekparker derekparker merged commit 0933a68 into go-delve:master Jul 28, 2015
nclifton pushed a commit to nclifton/delve that referenced this pull request Feb 24, 2021
* UPdated conn confs

* UPdated conn confs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants