github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/internal/obj/line.go (about) 1 // Copyright 2009 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 obj 6 7 import ( 8 "cmd/internal/src" 9 "path/filepath" 10 ) 11 12 // AbsFile returns the absolute filename for file in the given directory. 13 // It also removes a leading pathPrefix, or else rewrites a leading $GOROOT 14 // prefix to the literal "$GOROOT". 15 // If the resulting path is the empty string, the result is "??". 16 func AbsFile(dir, file, pathPrefix string) string { 17 abs := file 18 if dir != "" && !filepath.IsAbs(file) { 19 abs = filepath.Join(dir, file) 20 } 21 22 if pathPrefix != "" && hasPathPrefix(abs, pathPrefix) { 23 if abs == pathPrefix { 24 abs = "" 25 } else { 26 abs = abs[len(pathPrefix)+1:] 27 } 28 } else if hasPathPrefix(abs, GOROOT) { 29 abs = "$GOROOT" + abs[len(GOROOT):] 30 } 31 if abs == "" { 32 abs = "??" 33 } 34 35 return filepath.Clean(abs) 36 } 37 38 // Does s have t as a path prefix? 39 // That is, does s == t or does s begin with t followed by a slash? 40 // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true. 41 // Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true. 42 // We do not allow full Unicode case folding, for fear of causing more confusion 43 // or harm than good. (For an example of the kinds of things that can go wrong, 44 // see http://article.gmane.org/gmane.linux.kernel/1853266.) 45 func hasPathPrefix(s string, t string) bool { 46 if len(t) > len(s) { 47 return false 48 } 49 var i int 50 for i = 0; i < len(t); i++ { 51 cs := int(s[i]) 52 ct := int(t[i]) 53 if 'A' <= cs && cs <= 'Z' { 54 cs += 'a' - 'A' 55 } 56 if 'A' <= ct && ct <= 'Z' { 57 ct += 'a' - 'A' 58 } 59 if cs == '\\' { 60 cs = '/' 61 } 62 if ct == '\\' { 63 ct = '/' 64 } 65 if cs != ct { 66 return false 67 } 68 } 69 return i >= len(s) || s[i] == '/' || s[i] == '\\' 70 } 71 72 // AddImport adds a package to the list of imported packages. 73 func (ctxt *Link) AddImport(pkg string) { 74 ctxt.Imports = append(ctxt.Imports, pkg) 75 } 76 77 func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f *LSym, l int32) { 78 pos := ctxt.PosTable.Pos(xpos) 79 filename := pos.AbsFilename() 80 if !pos.IsKnown() || filename == "" { 81 return Linklookup(ctxt, "??", HistVersion), 0 82 } 83 // TODO(gri) Should this use relative or absolute line number? 84 return Linklookup(ctxt, filename, HistVersion), int32(pos.RelLine()) 85 } 86 87 func fieldtrack(ctxt *Link, cursym *LSym) { 88 p := cursym.Text 89 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 90 return 91 } 92 ctxt.Cursym = cursym 93 94 for ; p != nil; p = p.Link { 95 if p.As == AUSEFIELD { 96 r := Addrel(ctxt.Cursym) 97 r.Off = 0 98 r.Siz = 0 99 r.Sym = p.From.Sym 100 r.Type = R_USEFIELD 101 } 102 } 103 }