diff options
Diffstat (limited to 'src/cmd/internal/pkgpath')
| -rw-r--r-- | src/cmd/internal/pkgpath/pkgpath.go | 70 | ||||
| -rw-r--r-- | src/cmd/internal/pkgpath/pkgpath_test.go | 22 |
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) + } + } +} |
