| // Copyright 2009 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 obj |
| |
| import ( |
| "cmd/internal/src" |
| "path/filepath" |
| ) |
| |
| // AbsFile returns the absolute filename for file in the given directory. |
| // It also removes a leading pathPrefix, or else rewrites a leading $GOROOT |
| // prefix to the literal "$GOROOT". |
| // If the resulting path is the empty string, the result is "??". |
| func AbsFile(dir, file, pathPrefix string) string { |
| abs := file |
| if dir != "" && !filepath.IsAbs(file) { |
| abs = filepath.Join(dir, file) |
| } |
| |
| if pathPrefix != "" && hasPathPrefix(abs, pathPrefix) { |
| if abs == pathPrefix { |
| abs = "" |
| } else { |
| abs = abs[len(pathPrefix)+1:] |
| } |
| } else if hasPathPrefix(abs, GOROOT) { |
| abs = "$GOROOT" + abs[len(GOROOT):] |
| } |
| if abs == "" { |
| abs = "??" |
| } |
| |
| return filepath.Clean(abs) |
| } |
| |
| // Does s have t as a path prefix? |
| // That is, does s == t or does s begin with t followed by a slash? |
| // For portability, we allow ASCII case folding, so that hasPathPrefix("a/b/c", "A/B") is true. |
| // Similarly, we allow slash folding, so that hasPathPrefix("a/b/c", "a\\b") is true. |
| // We do not allow full Unicode case folding, for fear of causing more confusion |
| // or harm than good. (For an example of the kinds of things that can go wrong, |
| // see http://article.gmane.org/gmane.linux.kernel/1853266.) |
| func hasPathPrefix(s string, t string) bool { |
| if len(t) > len(s) { |
| return false |
| } |
| var i int |
| for i = 0; i < len(t); i++ { |
| cs := int(s[i]) |
| ct := int(t[i]) |
| if 'A' <= cs && cs <= 'Z' { |
| cs += 'a' - 'A' |
| } |
| if 'A' <= ct && ct <= 'Z' { |
| ct += 'a' - 'A' |
| } |
| if cs == '\\' { |
| cs = '/' |
| } |
| if ct == '\\' { |
| ct = '/' |
| } |
| if cs != ct { |
| return false |
| } |
| } |
| return i >= len(s) || s[i] == '/' || s[i] == '\\' |
| } |
| |
| // AddImport adds a package to the list of imported packages. |
| func (ctxt *Link) AddImport(pkg string) { |
| ctxt.Imports = append(ctxt.Imports, pkg) |
| } |
| |
| func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f *LSym, l int32) { |
| pos := ctxt.PosTable.Pos(xpos) |
| filename := pos.AbsFilename() |
| if !pos.IsKnown() || filename == "" { |
| return Linklookup(ctxt, "??", HistVersion), 0 |
| } |
| // TODO(gri) Should this use relative or absolute line number? |
| return Linklookup(ctxt, filename, HistVersion), int32(pos.RelLine()) |
| } |
| |
| func fieldtrack(ctxt *Link, cursym *LSym) { |
| p := cursym.Text |
| if p == nil || p.Link == nil { // handle external functions and ELF section symbols |
| return |
| } |
| ctxt.Cursym = cursym |
| |
| for ; p != nil; p = p.Link { |
| if p.As == AUSEFIELD { |
| r := Addrel(ctxt.Cursym) |
| r.Off = 0 |
| r.Siz = 0 |
| r.Sym = p.From.Sym |
| r.Type = R_USEFIELD |
| } |
| } |
| } |