mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
315 lines
5.8 KiB
Go
315 lines
5.8 KiB
Go
|
|
// 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
|
||
|
|
}
|