github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/ssa/stmtlines_test.go (about) 1 package ssa_test 2 3 import ( 4 cmddwarf "github.com/gagliardetto/golang-go/cmd/internal/dwarf" 5 "debug/dwarf" 6 "debug/elf" 7 "debug/macho" 8 "debug/pe" 9 "fmt" 10 "github.com/gagliardetto/golang-go/not-internal/testenv" 11 "github.com/gagliardetto/golang-go/not-internal/xcoff" 12 "io" 13 "os" 14 "runtime" 15 "sort" 16 "testing" 17 ) 18 19 func open(path string) (*dwarf.Data, error) { 20 if fh, err := elf.Open(path); err == nil { 21 return fh.DWARF() 22 } 23 24 if fh, err := pe.Open(path); err == nil { 25 return fh.DWARF() 26 } 27 28 if fh, err := macho.Open(path); err == nil { 29 return fh.DWARF() 30 } 31 32 if fh, err := xcoff.Open(path); err == nil { 33 return fh.DWARF() 34 } 35 36 return nil, fmt.Errorf("unrecognized executable format") 37 } 38 39 func must(err error) { 40 if err != nil { 41 panic(err) 42 } 43 } 44 45 type Line struct { 46 File string 47 Line int 48 } 49 50 func TestStmtLines(t *testing.T) { 51 if runtime.GOOS == "plan9" { 52 t.Skip("skipping on plan9; no DWARF symbol table in executables") 53 } 54 55 if runtime.GOOS == "aix" { 56 extld := os.Getenv("CC") 57 if extld == "" { 58 extld = "gcc" 59 } 60 enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extld) 61 if err != nil { 62 t.Fatal(err) 63 } 64 if !enabled { 65 t.Skip("skipping on aix: no DWARF with ld version < 7.2.2 ") 66 } 67 } 68 69 lines := map[Line]bool{} 70 dw, err := open(testenv.GoToolPath(t)) 71 must(err) 72 rdr := dw.Reader() 73 rdr.Seek(0) 74 for { 75 e, err := rdr.Next() 76 must(err) 77 if e == nil { 78 break 79 } 80 if e.Tag != dwarf.TagCompileUnit { 81 continue 82 } 83 pkgname, _ := e.Val(dwarf.AttrName).(string) 84 if pkgname == "runtime" { 85 continue 86 } 87 if e.Val(dwarf.AttrStmtList) == nil { 88 continue 89 } 90 lrdr, err := dw.LineReader(e) 91 must(err) 92 93 var le dwarf.LineEntry 94 95 for { 96 err := lrdr.Next(&le) 97 if err == io.EOF { 98 break 99 } 100 must(err) 101 fl := Line{le.File.Name, le.Line} 102 lines[fl] = lines[fl] || le.IsStmt 103 } 104 } 105 106 nonStmtLines := []Line{} 107 for line, isstmt := range lines { 108 if !isstmt { 109 nonStmtLines = append(nonStmtLines, line) 110 } 111 } 112 113 if runtime.GOARCH == "amd64" { 114 if len(nonStmtLines)*100 > len(lines) { // > 99% obtained on amd64, no backsliding 115 t.Errorf("Saw too many (amd64, > 1%%) lines without statement marks, total=%d, nostmt=%d ('-run TestStmtLines -v' lists failing lines)\n", len(lines), len(nonStmtLines)) 116 } 117 } else if len(nonStmtLines)*100 > 2*len(lines) { // expect 98% elsewhere. 118 t.Errorf("Saw too many (not amd64, > 2%%) lines without statement marks, total=%d, nostmt=%d ('-run TestStmtLines -v' lists failing lines)\n", len(lines), len(nonStmtLines)) 119 } 120 if testing.Verbose() { 121 sort.Slice(nonStmtLines, func(i, j int) bool { 122 if nonStmtLines[i].File != nonStmtLines[j].File { 123 return nonStmtLines[i].File < nonStmtLines[j].File 124 } 125 return nonStmtLines[i].Line < nonStmtLines[j].Line 126 }) 127 for _, l := range nonStmtLines { 128 t.Logf("%s:%d has no DWARF is_stmt mark\n", l.File, l.Line) 129 } 130 } 131 t.Logf("total=%d, nostmt=%d\n", len(lines), len(nonStmtLines)) 132 }