github.com/freddyisaac/sicortex-golang@v0.0.0-20231019035217-e03519e66f60/src/cmd/link/dwarf_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "cmd/internal/objfile" 9 "debug/dwarf" 10 "internal/testenv" 11 "io" 12 "io/ioutil" 13 "os" 14 "os/exec" 15 "path" 16 "path/filepath" 17 "runtime" 18 "strings" 19 "testing" 20 ) 21 22 func TestDWARF(t *testing.T) { 23 if runtime.GOOS == "windows" { 24 t.Skip("DWARF is not supported on Windows") 25 } 26 27 testenv.MustHaveCGO(t) 28 testenv.MustHaveGoBuild(t) 29 30 if runtime.GOOS == "plan9" { 31 t.Skip("skipping on plan9; no DWARF symbol table in executables") 32 } 33 34 out, err := exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "cmd/link").CombinedOutput() 35 if err != nil { 36 t.Fatalf("go list: %v\n%s", err, out) 37 } 38 if string(out) != "false\n" { 39 t.Fatalf("cmd/link is stale - run go install cmd/link") 40 } 41 42 tmpDir, err := ioutil.TempDir("", "go-link-TestDWARF") 43 if err != nil { 44 t.Fatal("TempDir failed: ", err) 45 } 46 defer os.RemoveAll(tmpDir) 47 48 for _, prog := range []string{"testprog", "testprogcgo"} { 49 t.Run(prog, func(t *testing.T) { 50 exe := filepath.Join(tmpDir, prog+".exe") 51 dir := "../../runtime/testdata/" + prog 52 out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, dir).CombinedOutput() 53 if err != nil { 54 t.Fatalf("go build -o %v %v: %v\n%s", exe, dir, err, out) 55 } 56 57 f, err := objfile.Open(exe) 58 if err != nil { 59 t.Fatal(err) 60 } 61 defer f.Close() 62 63 syms, err := f.Symbols() 64 if err != nil { 65 t.Fatal(err) 66 } 67 68 var addr uint64 69 for _, sym := range syms { 70 if sym.Name == "main.main" { 71 addr = sym.Addr 72 break 73 } 74 } 75 if addr == 0 { 76 t.Fatal("cannot find main.main in symbols") 77 } 78 79 d, err := f.DWARF() 80 if err != nil { 81 t.Fatal(err) 82 } 83 84 // TODO: We'd like to use filepath.Join here. 85 // Also related: golang.org/issue/19784. 86 wantFile := path.Join(prog, "main.go") 87 wantLine := 24 88 r := d.Reader() 89 var line dwarf.LineEntry 90 for { 91 cu, err := r.Next() 92 if err != nil { 93 t.Fatal(err) 94 } 95 if cu == nil { 96 break 97 } 98 if cu.Tag != dwarf.TagCompileUnit { 99 r.SkipChildren() 100 continue 101 } 102 lr, err := d.LineReader(cu) 103 if err != nil { 104 t.Fatal(err) 105 } 106 for { 107 err := lr.Next(&line) 108 if err == io.EOF { 109 break 110 } 111 if err != nil { 112 t.Fatal(err) 113 } 114 if line.Address == addr { 115 if !strings.HasSuffix(line.File.Name, wantFile) || line.Line != wantLine { 116 t.Errorf("%#x is %s:%d, want %s:%d", addr, line.File.Name, line.Line, filepath.Join("...", wantFile), wantLine) 117 } 118 return 119 } 120 } 121 } 122 t.Fatalf("did not find file:line for %#x (main.main)", addr) 123 }) 124 } 125 }