diff options
Diffstat (limited to 'src/cmd/internal/obj/obj.go')
| -rw-r--r-- | src/cmd/internal/obj/obj.go | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/src/cmd/internal/obj/obj.go b/src/cmd/internal/obj/obj.go new file mode 100644 index 0000000000..23ecd57e5e --- /dev/null +++ b/src/cmd/internal/obj/obj.go @@ -0,0 +1,314 @@ +// 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 ( + "fmt" + "path/filepath" + "strings" +) + +const ( + HISTSZ = 10 + NSYM = 50 +) + +func linklinefmt(ctxt *Link, lno0 int, showAll, showFullPath bool) string { + var a [HISTSZ]struct { + incl *Hist + idel int32 + line *Hist + ldel int32 + } + lno := int32(lno0) + lno1 := lno + var d int32 + var i int + var n int + var h *Hist + n = 0 + var fp string + for h = ctxt.Hist; h != nil; h = h.Link { + if h.Offset < 0 { + continue + } + if lno < h.Line { + break + } + if h.Name != "<no name>" { + if h.Offset > 0 { + // #line directive + if n > 0 && n < int(HISTSZ) { + a[n-1].line = h + a[n-1].ldel = h.Line - h.Offset + 1 + } + } else { + // beginning of file + if n < int(HISTSZ) { + a[n].incl = h + a[n].idel = h.Line + a[n].line = nil + } + n++ + } + continue + } + n-- + if n > 0 && n < int(HISTSZ) { + d = h.Line - a[n].incl.Line + a[n-1].ldel += d + a[n-1].idel += d + } + } + if n > int(HISTSZ) { + n = int(HISTSZ) + } + for i = n - 1; i >= 0; i-- { + if i != n-1 { + if !showAll { + break + } + fp += " " + } + if ctxt.Debugline != 0 || showFullPath { + fp += fmt.Sprintf("%s/", ctxt.Pathname) + } + if a[i].line != nil { + fp += fmt.Sprintf("%s:%d[%s:%d]", a[i].line.Name, lno-a[i].ldel+1, a[i].incl.Name, lno-a[i].idel+1) + } else { + fp += fmt.Sprintf("%s:%d", a[i].incl.Name, lno-a[i].idel+1) + } + lno = a[i].incl.Line - 1 // now print out start of this file + } + if n == 0 { + fp += fmt.Sprintf("<unknown line number %d %d %d %s>", lno1, ctxt.Hist.Offset, ctxt.Hist.Line, ctxt.Hist.Name) + } + return fp +} + +// 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. +func haspathprefix(s string, t string) bool { + var i int + var cs int + var ct int + if len(t) > len(s) { + return false + } + 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] == '\\' +} + +// This is a simplified copy of linklinefmt above. +// It doesn't allow printing the full stack, and it returns the file name and line number separately. +// TODO: Unify with linklinefmt somehow. +func linkgetline(ctxt *Link, line int32, f **LSym, l *int32) { + var a [HISTSZ]struct { + incl *Hist + idel int32 + line *Hist + ldel int32 + } + var lno int32 + var d int32 + var dlno int32 + var n int + var h *Hist + var buf string + var buf1 string + var file string + lno = int32(line) + n = 0 + for h = ctxt.Hist; h != nil; h = h.Link { + if h.Offset < 0 { + continue + } + if lno < h.Line { + break + } + if h.Name != "<no name>" { + if h.Offset > 0 { + // #line directive + if n > 0 && n < HISTSZ { + a[n-1].line = h + a[n-1].ldel = h.Line - h.Offset + 1 + } + } else { + // beginning of file + if n < HISTSZ { + a[n].incl = h + a[n].idel = h.Line + a[n].line = nil + } + n++ + } + continue + } + n-- + if n > 0 && n < HISTSZ { + d = h.Line - a[n].incl.Line + a[n-1].ldel += d + a[n-1].idel += d + } + } + if n > HISTSZ { + n = HISTSZ + } + if n <= 0 { + *f = Linklookup(ctxt, "??", HistVersion) + *l = 0 + return + } + n-- + if a[n].line != nil { + file = a[n].line.Name + dlno = a[n].ldel - 1 + } else { + file = a[n].incl.Name + dlno = a[n].idel - 1 + } + if filepath.IsAbs(file) || strings.HasPrefix(file, "<") { + buf = fmt.Sprintf("%s", file) + } else { + buf = fmt.Sprintf("%s/%s", ctxt.Pathname, file) + } + // Remove leading ctxt->trimpath, or else rewrite $GOROOT to $GOROOT_FINAL. + if ctxt.Trimpath != "" && haspathprefix(buf, ctxt.Trimpath) { + if len(buf) == len(ctxt.Trimpath) { + buf = "??" + } else { + buf1 = fmt.Sprintf("%s", buf[len(ctxt.Trimpath)+1:]) + if buf1[0] == '\x00' { + buf1 = "??" + } + buf = buf1 + } + } else if ctxt.Goroot_final != "" && haspathprefix(buf, ctxt.Goroot) { + buf1 = fmt.Sprintf("%s%s", ctxt.Goroot_final, buf[len(ctxt.Goroot):]) + buf = buf1 + } + lno -= dlno + *f = Linklookup(ctxt, buf, HistVersion) + *l = lno +} + +func linklinehist(ctxt *Link, lineno int, f string, offset int) { + var h *Hist + + if false { // debug['f'] + if f != "" { + if offset != 0 { + fmt.Printf("%4d: %s (#line %d)\n", lineno, f, offset) + } else { + + fmt.Printf("%4d: %s\n", lineno, f) + } + } else { + + fmt.Printf("%4d: <pop>\n", lineno) + } + } + + h = new(Hist) + *h = Hist{} + h.Name = f + h.Line = int32(lineno) + h.Offset = int32(offset) + h.Link = nil + if ctxt.Ehist == nil { + ctxt.Hist = h + ctxt.Ehist = h + return + } + + ctxt.Ehist.Link = h + ctxt.Ehist = h +} + +func linkprfile(ctxt *Link, line int) { + l := int32(line) + var i int + var n int + var a [HISTSZ]Hist + var h *Hist + var d int32 + n = 0 + for h = ctxt.Hist; h != nil; h = h.Link { + if l < h.Line { + break + } + if h.Name != "<no name>" { + if h.Offset == 0 { + if n >= 0 && n < HISTSZ { + a[n] = *h + } + n++ + continue + } + if n > 0 && n < HISTSZ { + if a[n-1].Offset == 0 { + a[n] = *h + n++ + } else { + a[n-1] = *h + } + } + continue + } + n-- + if n >= 0 && n < HISTSZ { + d = h.Line - a[n].Line + for i = 0; i < n; i++ { + a[i].Line += d + } + } + } + if n > HISTSZ { + n = HISTSZ + } + for i = 0; i < n; i++ { + fmt.Printf("%s:%d ", a[i].Name, int(l-a[i].Line+a[i].Offset+1)) + } +} + +/* + * start a new Prog list. + */ +func linknewplist(ctxt *Link) *Plist { + + var pl *Plist + + pl = new(Plist) + *pl = Plist{} + if ctxt.Plist == nil { + ctxt.Plist = pl + } else { + + ctxt.Plast.Link = pl + } + ctxt.Plast = pl + + return pl +} |
