mirror of
https://github.com/golang/go
synced 2024-11-17 21:54:49 -07:00
cmd/link: emit a mach-o dwarf segment that dsymutil will accept
Right now, at least with Xcode 8.3, we invoke dsymutil and dutifully copy what it produces back into the binary, but it has actually dropped all the DWARF information that we wanted, because it didn't like the look of go.o. Make it like the look of go.o. DWARF is tested in other ways, but typically indirectly and not for cgo programs. Add a direct test, and one that exercises cgo. This detects missing dwarf information in cgo-using binaries on macOS, at least with Xcode 8.3, and possibly earlier versions as well. Fixes #19772. Change-Id: I0082e52c0bc8fc4e289770ec3dc02f39fd61e743 Reviewed-on: https://go-review.googlesource.com/38855 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
eca90561c3
commit
18e77673d8
115
src/cmd/link/dwarf_test.go
Normal file
115
src/cmd/link/dwarf_test.go
Normal file
@ -0,0 +1,115 @@
|
||||
// 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"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDWARF(t *testing.T) {
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
@ -435,6 +435,10 @@ func (ctxt *Link) loadlib() {
|
||||
Peinit(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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user