| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package dwarf_test | |
| // Stripped-down, simplified version of ../../gosym/pclntab_test.go | |
| import ( | |
| "fmt" | |
| "io/ioutil" | |
| "os" | |
| "os/exec" | |
| "path/filepath" | |
| "runtime" | |
| "strings" | |
| "testing" | |
| . "golang.org/x/debug/dwarf" | |
| "golang.org/x/debug/elf" | |
| "golang.org/x/debug/macho" | |
| ) | |
| var ( | |
| pclineTempDir string | |
| pclinetestBinary string | |
| ) | |
| func dotest(self bool) bool { | |
| // For now, only works on amd64 platforms. | |
| if runtime.GOARCH != "amd64" { | |
| return false | |
| } | |
| // Self test reads test binary; only works on Linux or Mac. | |
| if self { | |
| if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { | |
| return false | |
| } | |
| } | |
| // Command below expects "sh", so Unix. | |
| if runtime.GOOS == "windows" || runtime.GOOS == "plan9" { | |
| return false | |
| } | |
| if pclinetestBinary != "" { | |
| return true | |
| } | |
| var err error | |
| pclineTempDir, err = ioutil.TempDir("", "pclinetest") | |
| if err != nil { | |
| panic(err) | |
| } | |
| if strings.Contains(pclineTempDir, " ") { | |
| panic("unexpected space in tempdir") | |
| } | |
| // This command builds pclinetest from ../../gosym/pclinetest.asm; | |
| // the resulting binary looks like it was built from pclinetest.s, | |
| // but we have renamed it to keep it away from the go tool. | |
| pclinetestBinary = filepath.Join(pclineTempDir, "pclinetest") | |
| command := fmt.Sprintf("go tool 6a -o %s.6 ../../gosym/pclinetest.asm && go tool 6l -H %s -E main -o %s %s.6", | |
| pclinetestBinary, runtime.GOOS, pclinetestBinary, pclinetestBinary) | |
| cmd := exec.Command("sh", "-c", command) | |
| cmd.Stdout = os.Stdout | |
| cmd.Stderr = os.Stderr | |
| if err := cmd.Run(); err != nil { | |
| panic(err) | |
| } | |
| return true | |
| } | |
| func endtest() { | |
| if pclineTempDir != "" { | |
| os.RemoveAll(pclineTempDir) | |
| pclineTempDir = "" | |
| pclinetestBinary = "" | |
| } | |
| } | |
| func getData(file string) (*Data, error) { | |
| switch runtime.GOOS { | |
| case "linux": | |
| f, err := elf.Open(file) | |
| if err != nil { | |
| return nil, err | |
| } | |
| dwarf, err := f.DWARF() | |
| if err != nil { | |
| return nil, err | |
| } | |
| f.Close() | |
| return dwarf, nil | |
| case "darwin": | |
| f, err := macho.Open(file) | |
| if err != nil { | |
| return nil, err | |
| } | |
| dwarf, err := f.DWARF() | |
| if err != nil { | |
| return nil, err | |
| } | |
| f.Close() | |
| return dwarf, nil | |
| } | |
| panic("unimplemented DWARF for GOOS=" + runtime.GOOS) | |
| } | |
| func TestPCToLine(t *testing.T) { | |
| if !dotest(false) { | |
| return | |
| } | |
| defer endtest() | |
| data, err := getData(pclinetestBinary) | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| // Test PCToLine. | |
| // TODO: Do much more than this. | |
| pc, err := data.LookupFunction("linefrompc") | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| file, line, err := data.PCToLine(pc) | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| // We expect <longpath>/pclinetest.asm, line 13. | |
| if !strings.HasSuffix(file, "/pclinetest.asm") { | |
| t.Errorf("got %s; want %s", file, ".../pclinetest.asm") | |
| } | |
| if line != 13 { | |
| t.Errorf("got %d; want %d", line, 13) | |
| } | |
| } |