mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal: remove duplicate pathToPrefix function
goobj.importPathToPrefix is 3x faster than gc.pathToPrefix so rename and move it to cmd/internal/objabi which is already imported by both goobj and gc. Change-Id: I10eda5bce95ef6d5d888818c5c47258c2833ea45 Reviewed-on: https://go-review.googlesource.com/40875 Run-TryBot: Todd Neal <todd@tneal.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
eb40f0621f
commit
dc444418d9
9 changed files with 84 additions and 135 deletions
|
|
@ -606,7 +606,6 @@ var knownFormats = map[string]string{
|
||||||
"[]cmd/compile/internal/ssa.ID %v": "",
|
"[]cmd/compile/internal/ssa.ID %v": "",
|
||||||
"[]string %v": "",
|
"[]string %v": "",
|
||||||
"bool %v": "",
|
"bool %v": "",
|
||||||
"byte %02x": "",
|
|
||||||
"byte %08b": "",
|
"byte %08b": "",
|
||||||
"byte %c": "",
|
"byte %c": "",
|
||||||
"cmd/compile/internal/arm.shift %d": "",
|
"cmd/compile/internal/arm.shift %d": "",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
package gc
|
package gc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/objabi"
|
"cmd/internal/objabi"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
|
|
@ -1958,33 +1957,6 @@ func ngotype(n *Node) *types.Sym {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert raw string to the prefix that will be used in the symbol
|
|
||||||
// table. All control characters, space, '%' and '"', as well as
|
|
||||||
// non-7-bit clean bytes turn into %xx. The period needs escaping
|
|
||||||
// only in the last segment of the path, and it makes for happier
|
|
||||||
// users if we escape that as little as possible.
|
|
||||||
//
|
|
||||||
// If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
|
|
||||||
func pathtoprefix(s string) string {
|
|
||||||
slash := strings.LastIndex(s, "/")
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
c := s[i]
|
|
||||||
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
c := s[i]
|
|
||||||
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
|
|
||||||
fmt.Fprintf(&buf, "%%%02x", c)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
buf.WriteByte(c)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
var pkgMap = make(map[string]*types.Pkg)
|
var pkgMap = make(map[string]*types.Pkg)
|
||||||
var pkgs []*types.Pkg
|
var pkgs []*types.Pkg
|
||||||
|
|
||||||
|
|
@ -1995,7 +1967,7 @@ func mkpkg(path string) *types.Pkg {
|
||||||
|
|
||||||
p := new(types.Pkg)
|
p := new(types.Pkg)
|
||||||
p.Path = path
|
p.Path = path
|
||||||
p.Prefix = pathtoprefix(path)
|
p.Prefix = objabi.PathToPrefix(path)
|
||||||
p.Syms = make(map[string]*types.Sym)
|
p.Syms = make(map[string]*types.Sym)
|
||||||
pkgMap[path] = p
|
pkgMap[path] = p
|
||||||
pkgs = append(pkgs, p)
|
pkgs = append(pkgs, p)
|
||||||
|
|
|
||||||
|
|
@ -159,45 +159,6 @@ type objReader struct {
|
||||||
pkgprefix string
|
pkgprefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
// importPathToPrefix returns the prefix that will be used in the
|
|
||||||
// final symbol table for the given import path.
|
|
||||||
// We escape '%', '"', all control characters and non-ASCII bytes,
|
|
||||||
// and any '.' after the final slash.
|
|
||||||
//
|
|
||||||
// See ../../../cmd/ld/lib.c:/^pathtoprefix and
|
|
||||||
// ../../../cmd/gc/subr.c:/^pathtoprefix.
|
|
||||||
func importPathToPrefix(s string) string {
|
|
||||||
// find index of last slash, if any, or else -1.
|
|
||||||
// used for determining whether an index is after the last slash.
|
|
||||||
slash := strings.LastIndex(s, "/")
|
|
||||||
|
|
||||||
// check for chars that need escaping
|
|
||||||
n := 0
|
|
||||||
for r := 0; r < len(s); r++ {
|
|
||||||
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// quick exit
|
|
||||||
if n == 0 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// escape
|
|
||||||
const hex = "0123456789abcdef"
|
|
||||||
p := make([]byte, 0, len(s)+2*n)
|
|
||||||
for r := 0; r < len(s); r++ {
|
|
||||||
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
|
|
||||||
p = append(p, '%', hex[c>>4], hex[c&0xF])
|
|
||||||
} else {
|
|
||||||
p = append(p, c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// init initializes r to read package p from f.
|
// init initializes r to read package p from f.
|
||||||
func (r *objReader) init(f io.ReadSeeker, p *Package) {
|
func (r *objReader) init(f io.ReadSeeker, p *Package) {
|
||||||
r.f = f
|
r.f = f
|
||||||
|
|
@ -206,7 +167,7 @@ func (r *objReader) init(f io.ReadSeeker, p *Package) {
|
||||||
r.limit, _ = f.Seek(0, io.SeekEnd)
|
r.limit, _ = f.Seek(0, io.SeekEnd)
|
||||||
f.Seek(r.offset, io.SeekStart)
|
f.Seek(r.offset, io.SeekStart)
|
||||||
r.b = bufio.NewReader(f)
|
r.b = bufio.NewReader(f)
|
||||||
r.pkgprefix = importPathToPrefix(p.ImportPath) + "."
|
r.pkgprefix = objabi.PathToPrefix(p.ImportPath) + "."
|
||||||
}
|
}
|
||||||
|
|
||||||
// error records that an error occurred.
|
// error records that an error occurred.
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
// Copyright 2013 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 goobj
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
var importPathToPrefixTests = []struct {
|
|
||||||
in string
|
|
||||||
out string
|
|
||||||
}{
|
|
||||||
{"runtime", "runtime"},
|
|
||||||
{"sync/atomic", "sync/atomic"},
|
|
||||||
{"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
|
|
||||||
{"foo.bar/baz.quux", "foo.bar/baz%2equux"},
|
|
||||||
{"", ""},
|
|
||||||
{"%foo%bar", "%25foo%25bar"},
|
|
||||||
{"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestImportPathToPrefix(t *testing.T) {
|
|
||||||
for _, tt := range importPathToPrefixTests {
|
|
||||||
if out := importPathToPrefix(tt.in); out != tt.out {
|
|
||||||
t.Errorf("importPathToPrefix(%q) = %q, want %q", tt.in, out, tt.out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
41
src/cmd/internal/objabi/path.go
Normal file
41
src/cmd/internal/objabi/path.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2017 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 objabi
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// PathToPrefix converts raw string to the prefix that will be used in the
|
||||||
|
// symbol table. All control characters, space, '%' and '"', as well as
|
||||||
|
// non-7-bit clean bytes turn into %xx. The period needs escaping only in the
|
||||||
|
// last segment of the path, and it makes for happier users if we escape that as
|
||||||
|
// little as possible.
|
||||||
|
func PathToPrefix(s string) string {
|
||||||
|
slash := strings.LastIndex(s, "/")
|
||||||
|
// check for chars that need escaping
|
||||||
|
n := 0
|
||||||
|
for r := 0; r < len(s); r++ {
|
||||||
|
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// quick exit
|
||||||
|
if n == 0 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// escape
|
||||||
|
const hex = "0123456789abcdef"
|
||||||
|
p := make([]byte, 0, len(s)+2*n)
|
||||||
|
for r := 0; r < len(s); r++ {
|
||||||
|
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
|
||||||
|
p = append(p, '%', hex[c>>4], hex[c&0xF])
|
||||||
|
} else {
|
||||||
|
p = append(p, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(p)
|
||||||
|
}
|
||||||
33
src/cmd/internal/objabi/path_test.go
Normal file
33
src/cmd/internal/objabi/path_test.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2017 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 objabi
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestPathToPrefix(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Path string
|
||||||
|
Expected string
|
||||||
|
}{{"foo/bar/v1", "foo/bar/v1"},
|
||||||
|
{"foo/bar/v.1", "foo/bar/v%2e1"},
|
||||||
|
{"f.o.o/b.a.r/v1", "f.o.o/b.a.r/v1"},
|
||||||
|
{"f.o.o/b.a.r/v.1", "f.o.o/b.a.r/v%2e1"},
|
||||||
|
{"f.o.o/b.a.r/v..1", "f.o.o/b.a.r/v%2e%2e1"},
|
||||||
|
{"f.o.o/b.a.r/v..1.", "f.o.o/b.a.r/v%2e%2e1%2e"},
|
||||||
|
{"f.o.o/b.a.r/v%1", "f.o.o/b.a.r/v%251"},
|
||||||
|
{"runtime", "runtime"},
|
||||||
|
{"sync/atomic", "sync/atomic"},
|
||||||
|
{"golang.org/x/tools/godoc", "golang.org/x/tools/godoc"},
|
||||||
|
{"foo.bar/baz.quux", "foo.bar/baz%2equux"},
|
||||||
|
{"", ""},
|
||||||
|
{"%foo%bar", "%25foo%25bar"},
|
||||||
|
{"\x01\x00\x7F☺", "%01%00%7f%e2%98%ba"},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
if got := PathToPrefix(tc.Path); got != tc.Expected {
|
||||||
|
t.Errorf("expected PathToPrefix(%s) = %s, got %s", tc.Path, tc.Expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1059,7 +1059,7 @@ func addstrdata1(ctxt *Link, arg string) {
|
||||||
if eq < 0 || dot < 0 {
|
if eq < 0 || dot < 0 {
|
||||||
Exitf("-X flag requires argument of the form importpath.name=value")
|
Exitf("-X flag requires argument of the form importpath.name=value")
|
||||||
}
|
}
|
||||||
addstrdata(ctxt, pathtoprefix(arg[:dot])+arg[dot:eq], arg[eq+1:])
|
addstrdata(ctxt, objabi.PathToPrefix(arg[:dot])+arg[dot:eq], arg[eq+1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func addstrdata(ctxt *Link, name string, value string) {
|
func addstrdata(ctxt *Link, name string, value string) {
|
||||||
|
|
|
||||||
|
|
@ -651,7 +651,7 @@ func (ctxt *Link) loadlib() {
|
||||||
// first containing package that the linker loads). canonicalize
|
// first containing package that the linker loads). canonicalize
|
||||||
// it here to the package with which it will be laid down
|
// it here to the package with which it will be laid down
|
||||||
// in text.
|
// in text.
|
||||||
s.File = pathtoprefix(lib.Pkg)
|
s.File = objabi.PathToPrefix(lib.Pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -752,7 +752,7 @@ func genhash(ctxt *Link, lib *Library) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func objfile(ctxt *Link, lib *Library) {
|
func objfile(ctxt *Link, lib *Library) {
|
||||||
pkg := pathtoprefix(lib.Pkg)
|
pkg := objabi.PathToPrefix(lib.Pkg)
|
||||||
|
|
||||||
if ctxt.Debugvlog > 1 {
|
if ctxt.Debugvlog > 1 {
|
||||||
ctxt.Logf("%5.2f ldobj: %s (%s)\n", Cputime(), lib.File, pkg)
|
ctxt.Logf("%5.2f ldobj: %s (%s)\n", Cputime(), lib.File, pkg)
|
||||||
|
|
@ -1312,7 +1312,7 @@ func hostlinkArchArgs() []string {
|
||||||
// compiled by a non-Go compiler) it returns the Hostobj pointer. If
|
// compiled by a non-Go compiler) it returns the Hostobj pointer. If
|
||||||
// it is a Go object, it returns nil.
|
// it is a Go object, it returns nil.
|
||||||
func ldobj(ctxt *Link, f *bio.Reader, lib *Library, length int64, pn string, file string, whence int) *Hostobj {
|
func ldobj(ctxt *Link, f *bio.Reader, lib *Library, length int64, pn string, file string, whence int) *Hostobj {
|
||||||
pkg := pathtoprefix(lib.Pkg)
|
pkg := objabi.PathToPrefix(lib.Pkg)
|
||||||
|
|
||||||
eof := f.Offset() + length
|
eof := f.Offset() + length
|
||||||
start := f.Offset()
|
start := f.Offset()
|
||||||
|
|
@ -1572,35 +1572,6 @@ func ldshlibsyms(ctxt *Link, shlib string) {
|
||||||
ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
|
ctxt.Shlibs = append(ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdataAddresses: gcdataAddresses})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copied from ../gc/subr.c:/^pathtoprefix; must stay in sync.
|
|
||||||
/*
|
|
||||||
* Convert raw string to the prefix that will be used in the symbol table.
|
|
||||||
* Invalid bytes turn into %xx. Right now the only bytes that need
|
|
||||||
* escaping are %, ., and ", but we escape all control characters too.
|
|
||||||
*
|
|
||||||
* If you edit this, edit ../gc/subr.c:/^pathtoprefix too.
|
|
||||||
* If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
|
|
||||||
*/
|
|
||||||
func pathtoprefix(s string) string {
|
|
||||||
slash := strings.LastIndex(s, "/")
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
c := s[i]
|
|
||||||
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
c := s[i]
|
|
||||||
if c <= ' ' || i >= slash && c == '.' || c == '%' || c == '"' || c >= 0x7F {
|
|
||||||
fmt.Fprintf(&buf, "%%%02x", c)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
buf.WriteByte(c)
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func addsection(seg *Segment, name string, rwx int) *Section {
|
func addsection(seg *Segment, name string, rwx int) *Section {
|
||||||
sect := new(Section)
|
sect := new(Section)
|
||||||
sect.Rwx = uint8(rwx)
|
sect.Rwx = uint8(rwx)
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ func LoadObjFile(ctxt *Link, f *bio.Reader, lib *Library, length int64, pn strin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *objReader) loadObjFile() {
|
func (r *objReader) loadObjFile() {
|
||||||
pkg := pathtoprefix(r.lib.Pkg)
|
pkg := objabi.PathToPrefix(r.lib.Pkg)
|
||||||
|
|
||||||
// Magic header
|
// Magic header
|
||||||
var buf [8]uint8
|
var buf [8]uint8
|
||||||
|
|
@ -168,7 +168,7 @@ func (r *objReader) readSym() {
|
||||||
typ := r.readSymIndex()
|
typ := r.readSymIndex()
|
||||||
data := r.readData()
|
data := r.readData()
|
||||||
nreloc := r.readInt()
|
nreloc := r.readInt()
|
||||||
pkg := pathtoprefix(r.lib.Pkg)
|
pkg := objabi.PathToPrefix(r.lib.Pkg)
|
||||||
isdup := false
|
isdup := false
|
||||||
|
|
||||||
var dup *Symbol
|
var dup *Symbol
|
||||||
|
|
@ -345,7 +345,7 @@ func (r *objReader) patchDWARFName(s *Symbol) {
|
||||||
if p == -1 {
|
if p == -1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pkgprefix := []byte(pathtoprefix(r.lib.Pkg) + ".")
|
pkgprefix := []byte(objabi.PathToPrefix(r.lib.Pkg) + ".")
|
||||||
patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
|
patched := bytes.Replace(s.P[:e], emptyPkg, pkgprefix, -1)
|
||||||
|
|
||||||
s.P = append(patched, s.P[e:]...)
|
s.P = append(patched, s.P[e:]...)
|
||||||
|
|
@ -478,7 +478,7 @@ func (r *objReader) readData() []byte {
|
||||||
|
|
||||||
// readSymName reads a symbol name, replacing all "". with pkg.
|
// readSymName reads a symbol name, replacing all "". with pkg.
|
||||||
func (r *objReader) readSymName() string {
|
func (r *objReader) readSymName() string {
|
||||||
pkg := pathtoprefix(r.lib.Pkg)
|
pkg := objabi.PathToPrefix(r.lib.Pkg)
|
||||||
n := r.readInt()
|
n := r.readInt()
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
r.readInt64()
|
r.readInt64()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue