aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/pkgpath
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/pkgpath')
-rw-r--r--src/cmd/internal/pkgpath/pkgpath.go70
-rw-r--r--src/cmd/internal/pkgpath/pkgpath_test.go22
2 files changed, 86 insertions, 6 deletions
diff --git a/src/cmd/internal/pkgpath/pkgpath.go b/src/cmd/internal/pkgpath/pkgpath.go
index 0b24468be6..72e3bdb631 100644
--- a/src/cmd/internal/pkgpath/pkgpath.go
+++ b/src/cmd/internal/pkgpath/pkgpath.go
@@ -10,9 +10,9 @@ import (
"bytes"
"errors"
"fmt"
+ exec "internal/execabs"
"io/ioutil"
"os"
- "os/exec"
"strings"
)
@@ -50,9 +50,12 @@ func ToSymbolFunc(cmd, tmpdir string) (func(string) string, error) {
return nil, err
}
- // New mangling: expect go.l..u00e4ufer.Run
- // Old mangling: expect go.l__ufer.Run
- if bytes.Contains(buf, []byte("go.l..u00e4ufer.Run")) {
+ // Original mangling: go.l__ufer.Run
+ // Mangling v2: go.l..u00e4ufer.Run
+ // Mangling v3: go_0l_u00e4ufer.Run
+ if bytes.Contains(buf, []byte("go_0l_u00e4ufer.Run")) {
+ return toSymbolV3, nil
+ } else if bytes.Contains(buf, []byte("go.l..u00e4ufer.Run")) {
return toSymbolV2, nil
} else if bytes.Contains(buf, []byte("go.l__ufer.Run")) {
return toSymbolV1, nil
@@ -82,7 +85,7 @@ func toSymbolV1(ppath string) string {
return strings.Map(clean, ppath)
}
-// toSymbolV2 converts a package path using the newer mangling scheme.
+// toSymbolV2 converts a package path using the second mangling scheme.
func toSymbolV2(ppath string) string {
// This has to build at boostrap time, so it has to build
// with Go 1.4, so we don't use strings.Builder.
@@ -112,3 +115,60 @@ func toSymbolV2(ppath string) string {
}
return string(bsl)
}
+
+// v3UnderscoreCodes maps from a character that supports an underscore
+// encoding to the underscore encoding character.
+var v3UnderscoreCodes = map[byte]byte{
+ '_': '_',
+ '.': '0',
+ '/': '1',
+ '*': '2',
+ ',': '3',
+ '{': '4',
+ '}': '5',
+ '[': '6',
+ ']': '7',
+ '(': '8',
+ ')': '9',
+ '"': 'a',
+ ' ': 'b',
+ ';': 'c',
+}
+
+// toSymbolV3 converts a package path using the third mangling scheme.
+func toSymbolV3(ppath string) string {
+ // This has to build at boostrap time, so it has to build
+ // with Go 1.4, so we don't use strings.Builder.
+ bsl := make([]byte, 0, len(ppath))
+ changed := false
+ for _, c := range ppath {
+ if ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') {
+ bsl = append(bsl, byte(c))
+ continue
+ }
+
+ if c < 0x80 {
+ if u, ok := v3UnderscoreCodes[byte(c)]; ok {
+ bsl = append(bsl, '_', u)
+ changed = true
+ continue
+ }
+ }
+
+ var enc string
+ switch {
+ case c < 0x80:
+ enc = fmt.Sprintf("_x%02x", c)
+ case c < 0x10000:
+ enc = fmt.Sprintf("_u%04x", c)
+ default:
+ enc = fmt.Sprintf("_U%08x", c)
+ }
+ bsl = append(bsl, enc...)
+ changed = true
+ }
+ if !changed {
+ return ppath
+ }
+ return string(bsl)
+}
diff --git a/src/cmd/internal/pkgpath/pkgpath_test.go b/src/cmd/internal/pkgpath/pkgpath_test.go
index 7355f81bae..232e803a60 100644
--- a/src/cmd/internal/pkgpath/pkgpath_test.go
+++ b/src/cmd/internal/pkgpath/pkgpath_test.go
@@ -24,6 +24,9 @@ func init() {
case "v2":
os.Stdout.WriteString(`.string "go.l..u00e4ufer.Run"`)
os.Exit(0)
+ case "v3":
+ os.Stdout.WriteString(`.string "go_0l_u00e4ufer.Run"`)
+ os.Exit(0)
case "error":
os.Stdout.WriteString(`unknown string`)
os.Exit(0)
@@ -46,6 +49,10 @@ func TestToSymbolFunc(t *testing.T) {
mangled: "p..u00e4..u4e16..U0001f703",
},
{
+ env: "v3",
+ mangled: "p_u00e4_u4e16_U0001f703",
+ },
+ {
env: "error",
fail: true,
},
@@ -75,32 +82,37 @@ func TestToSymbolFunc(t *testing.T) {
}
var symbolTests = []struct {
- input, v1, v2 string
+ input, v1, v2, v3 string
}{
{
"",
"",
"",
+ "",
},
{
"bytes",
"bytes",
"bytes",
+ "bytes",
},
{
"net/http",
"net_http",
"net..z2fhttp",
+ "net_1http",
},
{
"golang.org/x/net/http",
"golang_org_x_net_http",
"golang.x2eorg..z2fx..z2fnet..z2fhttp",
+ "golang_0org_1x_1net_1http",
},
{
"pä世.🜃",
"p____",
"p..u00e4..u4e16.x2e..U0001f703",
+ "p_u00e4_u4e16_0_U0001f703",
},
}
@@ -119,3 +131,11 @@ func TestV2(t *testing.T) {
}
}
}
+
+func TestV3(t *testing.T) {
+ for _, test := range symbolTests {
+ if got, want := toSymbolV3(test.input), test.v3; got != want {
+ t.Errorf("toSymbolV3(%q) = %q, want %q", test.input, got, want)
+ }
+ }
+}