aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/obj.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj/obj.go')
-rw-r--r--src/cmd/internal/obj/obj.go314
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
+}