Skip to content

Commit

Permalink
debug/pe: fix TestDWARF to work with relocations
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
jordanrh1 authored and bradfitz committed Oct 5, 2018
1 parent 68d5296 commit 3d19d95
Showing 1 changed file with 71 additions and 6 deletions.
77 changes: 71 additions & 6 deletions src/debug/pe/file_test.go
Expand Up @@ -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")
Expand Down Expand Up @@ -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)
Expand All @@ -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" {
Expand All @@ -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
}
}
}
Expand Down Expand Up @@ -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)
}
`

Expand Down

0 comments on commit 3d19d95

Please sign in to comment.