diff options
-rw-r--r-- | src/cmd/link/dwarf_test.go | 120 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/lib.go | 4 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/macho.go | 2 |
3 files changed, 125 insertions, 1 deletions
diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go new file mode 100644 index 0000000000..33465144e4 --- /dev/null +++ b/src/cmd/link/dwarf_test.go @@ -0,0 +1,120 @@ +// Copyright 2017 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 main + +import ( + "cmd/internal/objfile" + "debug/dwarf" + "internal/testenv" + "io" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + "runtime" + "strings" + "testing" +) + +func TestDWARF(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("DWARF is not supported on Windows") + } + + testenv.MustHaveGoBuild(t) + + out, err := exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "cmd/link").CombinedOutput() + if err != nil { + t.Fatalf("go list: %v\n%s", err, out) + } + if string(out) != "false\n" { + t.Fatalf("cmd/link is stale - run go install cmd/link") + } + + tmpDir, err := ioutil.TempDir("", "go-link-TestDWARF") + if err != nil { + t.Fatal("TempDir failed: ", err) + } + defer os.RemoveAll(tmpDir) + + for _, prog := range []string{"testprog", "testprogcgo"} { + t.Run(prog, func(t *testing.T) { + exe := filepath.Join(tmpDir, prog+".exe") + dir := "../../runtime/testdata/" + prog + out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, dir).CombinedOutput() + if err != nil { + t.Fatalf("go build -o %v %v: %v\n%s", exe, dir, err, out) + } + + f, err := objfile.Open(exe) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + syms, err := f.Symbols() + if err != nil { + t.Fatal(err) + } + + var addr uint64 + for _, sym := range syms { + if sym.Name == "main.main" { + addr = sym.Addr + break + } + } + if addr == 0 { + t.Fatal("cannot find main.main in symbols") + } + + d, err := f.DWARF() + if err != nil { + t.Fatal(err) + } + + // TODO: We'd like to use filepath.Join here. + // Also related: golang.org/issue/19784. + wantFile := path.Join(prog, "main.go") + wantLine := 24 + r := d.Reader() + var line dwarf.LineEntry + for { + cu, err := r.Next() + if err != nil { + t.Fatal(err) + } + if cu == nil { + break + } + if cu.Tag != dwarf.TagCompileUnit { + r.SkipChildren() + continue + } + lr, err := d.LineReader(cu) + if err != nil { + t.Fatal(err) + } + for { + err := lr.Next(&line) + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } + if line.Address == addr { + if !strings.HasSuffix(line.File.Name, wantFile) || line.Line != wantLine { + t.Errorf("%#x is %s:%d, want %s:%d", addr, line.File.Name, line.Line, filepath.Join("...", wantFile), wantLine) + } + return + } + } + } + t.Fatalf("did not find file:line for %#x (main.main)", addr) + }) + } +} diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 6e90d78571..b624aa01af 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -430,6 +430,10 @@ func (ctxt *Link) loadlib() { // We now have enough information to determine the link mode. determineLinkMode(ctxt) + if Headtype == obj.Hdarwin && Linkmode == LinkExternal { + *FlagTextAddr = 0 + } + if Linkmode == LinkExternal && SysArch.Family == sys.PPC64 { toc := ctxt.Syms.Lookup(".TOC.", 0) toc.Type = obj.SDYNIMPORT diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index f3687daa91..1ab61b7d15 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -449,7 +449,7 @@ func Asmbmacho(ctxt *Link) { ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff } else { ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff - ms.vsize = ms.filesize + ms.vsize = Segdwarf.Vaddr + Segdwarf.Length - Segtext.Vaddr } } |