]> Cypherpunks repositories - gostls13.git/commitdiff
debug/pe: fix TestDWARF to work with relocations
authorJordan Rhee <jordanrh@microsoft.com>
Fri, 5 Oct 2018 20:12:18 +0000 (13:12 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 5 Oct 2018 20:30:11 +0000 (20:30 +0000)
Fixes #27904

Change-Id: Ie2aad20cd66785b6cc1018c0048824382cb39f8c
Reviewed-on: https://go-review.googlesource.com/c/140158
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/debug/pe/file_test.go

index c65c82d3425ed43306ff575475c9c2023b93286e..4f0510200fecb9d73de7f190c3e79cca08871480 100644 (file)
@@ -298,6 +298,17 @@ const (
        linkCgoExternal
 )
 
+func getImageBase(f *File) uintptr {
+       switch oh := f.OptionalHeader.(type) {
+       case *OptionalHeader32:
+               return uintptr(oh.ImageBase)
+       case *OptionalHeader64:
+               return uintptr(oh.ImageBase)
+       default:
+               panic("unexpected optionalheader type")
+       }
+}
+
 func testDWARF(t *testing.T, linktype int) {
        if runtime.GOOS != "windows" {
                t.Skip("skipping windows only test")
@@ -347,14 +358,15 @@ func testDWARF(t *testing.T, linktype int) {
        if err != nil {
                t.Fatalf("running test executable failed: %s %s", err, out)
        }
+       t.Logf("Testprog output:\n%s", string(out))
 
-       matches := regexp.MustCompile("main=(.*)\n").FindStringSubmatch(string(out))
+       matches := regexp.MustCompile("offset=(.*)\n").FindStringSubmatch(string(out))
        if len(matches) < 2 {
                t.Fatalf("unexpected program output: %s", out)
        }
-       wantaddr, err := strconv.ParseUint(matches[1], 0, 64)
+       wantoffset, err := strconv.ParseUint(matches[1], 0, 64)
        if err != nil {
-               t.Fatalf("unexpected main address %q: %s", matches[1], err)
+               t.Fatalf("unexpected main offset %q: %s", matches[1], err)
        }
 
        f, err := Open(exe)
@@ -363,6 +375,8 @@ func testDWARF(t *testing.T, linktype int) {
        }
        defer f.Close()
 
+       imageBase := getImageBase(f)
+
        var foundDebugGDBScriptsSection bool
        for _, sect := range f.Sections {
                if sect.Name == ".debug_gdb_scripts" {
@@ -389,10 +403,20 @@ func testDWARF(t *testing.T, linktype int) {
                        break
                }
                if e.Tag == dwarf.TagSubprogram {
-                       if name, ok := e.Val(dwarf.AttrName).(string); ok && name == "main.main" {
-                               if addr, ok := e.Val(dwarf.AttrLowpc).(uint64); ok && addr == wantaddr {
-                                       return
+                       name, ok := e.Val(dwarf.AttrName).(string)
+                       if ok && name == "main.main" {
+                               t.Logf("Found main.main")
+                               addr, ok := e.Val(dwarf.AttrLowpc).(uint64)
+                               if !ok {
+                                       t.Fatal("Failed to get AttrLowpc")
+                               }
+                               offset := uintptr(addr) - imageBase
+                               if offset != uintptr(wantoffset) {
+                                       t.Fatal("Runtime offset (0x%x) did "+
+                                               "not match dwarf offset "+
+                                               "(0x%x)", wantoffset, offset)
                                }
+                               return
                        }
                }
        }
@@ -479,11 +503,52 @@ const testprog = `
 package main
 
 import "fmt"
+import "syscall"
+import "unsafe"
 {{if .}}import "C"
 {{end}}
 
+// struct MODULEINFO from the Windows SDK
+type moduleinfo struct {
+       BaseOfDll uintptr
+       SizeOfImage uint32
+       EntryPoint uintptr
+}
+
+func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
+       return unsafe.Pointer(uintptr(p) + x)
+}
+
+func funcPC(f interface{}) uintptr {
+       var a uintptr
+       return **(**uintptr)(add(unsafe.Pointer(&f), unsafe.Sizeof(a)))
+}
+
 func main() {
+       kernel32 := syscall.MustLoadDLL("kernel32.dll")
+       psapi := syscall.MustLoadDLL("psapi.dll")
+       getModuleHandle := kernel32.MustFindProc("GetModuleHandleW")
+       getCurrentProcess := kernel32.MustFindProc("GetCurrentProcess")
+       getModuleInformation := psapi.MustFindProc("GetModuleInformation")
+
+       procHandle, _, _ := getCurrentProcess.Call()
+       moduleHandle, _, err := getModuleHandle.Call(0)
+       if moduleHandle == 0 {
+               panic(fmt.Sprintf("GetModuleHandle() failed: %d", err))
+       }
+
+       var info moduleinfo
+       ret, _, err := getModuleInformation.Call(procHandle, moduleHandle,
+               uintptr(unsafe.Pointer(&info)), unsafe.Sizeof(info))
+
+       if ret == 0 {
+               panic(fmt.Sprintf("GetModuleInformation() failed: %d", err))
+       }
+
+       offset := funcPC(main) - info.BaseOfDll
+       fmt.Printf("base=0x%x\n", info.BaseOfDll)
        fmt.Printf("main=%p\n", main)
+       fmt.Printf("offset=0x%x\n", offset)
 }
 `