mirror of
https://github.com/golang/go
synced 2024-11-26 10:48:22 -07:00
cmd/cgo, cmd/internal/pkgpath: support gofrontend mangler v3
The gofrontend mangling scheme used by gccgo and GoLLVM has changed again. Support the new version. This is a port of the relevant parts of https://golang.org/cl/271726. For #41862 Change-Id: I9c961c8e17ec960a83a23e1d49ea900962b63393 Reviewed-on: https://go-review.googlesource.com/c/go/+/272127 Trust: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
3fd4917472
commit
c47eac7db0
@ -186,7 +186,7 @@ func (p *Package) writeDefs() {
|
|||||||
panic(fmt.Errorf("invalid var kind %q", n.Kind))
|
panic(fmt.Errorf("invalid var kind %q", n.Kind))
|
||||||
}
|
}
|
||||||
if *gccgo {
|
if *gccgo {
|
||||||
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
|
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, gccgoToSymbol(n.Mangle))
|
||||||
fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
|
fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
|
||||||
fmt.Fprintf(fc, "\n")
|
fmt.Fprintf(fc, "\n")
|
||||||
}
|
}
|
||||||
@ -1148,7 +1148,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||||||
// will not be able to link against it from the C
|
// will not be able to link against it from the C
|
||||||
// code.
|
// code.
|
||||||
goName := "Cgoexp_" + exp.ExpName
|
goName := "Cgoexp_" + exp.ExpName
|
||||||
fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
|
fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, gccgoToSymbol(goName))
|
||||||
fmt.Fprint(fgcc, "\n")
|
fmt.Fprint(fgcc, "\n")
|
||||||
|
|
||||||
fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
|
fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
|
||||||
@ -1182,7 +1182,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||||||
fmt.Fprint(fgcc, "}\n")
|
fmt.Fprint(fgcc, "}\n")
|
||||||
|
|
||||||
// Dummy declaration for _cgo_main.c
|
// Dummy declaration for _cgo_main.c
|
||||||
fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
|
fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, gccgoToSymbol(goName))
|
||||||
fmt.Fprint(fm, "\n")
|
fmt.Fprint(fm, "\n")
|
||||||
|
|
||||||
// For gccgo we use a wrapper function in Go, in order
|
// For gccgo we use a wrapper function in Go, in order
|
||||||
@ -1266,9 +1266,8 @@ func (p *Package) writeExportHeader(fgcch io.Writer) {
|
|||||||
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
|
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
|
||||||
}
|
}
|
||||||
|
|
||||||
// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
|
// gccgoToSymbol converts a name to a mangled symbol for gccgo.
|
||||||
// symbol.
|
func gccgoToSymbol(ppath string) string {
|
||||||
func gccgoPkgpathToSymbol(ppath string) string {
|
|
||||||
if gccgoMangler == nil {
|
if gccgoMangler == nil {
|
||||||
var err error
|
var err error
|
||||||
cmd := os.Getenv("GCCGO")
|
cmd := os.Getenv("GCCGO")
|
||||||
@ -1293,12 +1292,12 @@ func (p *Package) gccgoSymbolPrefix() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if *gccgopkgpath != "" {
|
if *gccgopkgpath != "" {
|
||||||
return gccgoPkgpathToSymbol(*gccgopkgpath)
|
return gccgoToSymbol(*gccgopkgpath)
|
||||||
}
|
}
|
||||||
if *gccgoprefix == "" && p.PackageName == "main" {
|
if *gccgoprefix == "" && p.PackageName == "main" {
|
||||||
return "main"
|
return "main"
|
||||||
}
|
}
|
||||||
prefix := gccgoPkgpathToSymbol(*gccgoprefix)
|
prefix := gccgoToSymbol(*gccgoprefix)
|
||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
prefix = "go"
|
prefix = "go"
|
||||||
}
|
}
|
||||||
@ -1687,8 +1686,12 @@ void _cgoPREFIX_Cfunc__Cmalloc(void *v) {
|
|||||||
`
|
`
|
||||||
|
|
||||||
func (p *Package) cPrologGccgo() string {
|
func (p *Package) cPrologGccgo() string {
|
||||||
return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
|
r := strings.NewReplacer(
|
||||||
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
|
"PREFIX", cPrefix,
|
||||||
|
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(),
|
||||||
|
"_cgoCheckPointer", gccgoToSymbol("_cgoCheckPointer"),
|
||||||
|
"_cgoCheckResult", gccgoToSymbol("_cgoCheckResult"))
|
||||||
|
return r.Replace(cPrologGccgo)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cPrologGccgo = `
|
const cPrologGccgo = `
|
||||||
|
@ -50,9 +50,12 @@ func ToSymbolFunc(cmd, tmpdir string) (func(string) string, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// New mangling: expect go.l..u00e4ufer.Run
|
// Original mangling: go.l__ufer.Run
|
||||||
// Old mangling: expect go.l__ufer.Run
|
// Mangling v2: go.l..u00e4ufer.Run
|
||||||
if bytes.Contains(buf, []byte("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
|
return toSymbolV2, nil
|
||||||
} else if bytes.Contains(buf, []byte("go.l__ufer.Run")) {
|
} else if bytes.Contains(buf, []byte("go.l__ufer.Run")) {
|
||||||
return toSymbolV1, nil
|
return toSymbolV1, nil
|
||||||
@ -82,7 +85,7 @@ func toSymbolV1(ppath string) string {
|
|||||||
return strings.Map(clean, ppath)
|
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 {
|
func toSymbolV2(ppath string) string {
|
||||||
// This has to build at boostrap time, so it has to build
|
// This has to build at boostrap time, so it has to build
|
||||||
// with Go 1.4, so we don't use strings.Builder.
|
// with Go 1.4, so we don't use strings.Builder.
|
||||||
@ -112,3 +115,60 @@ func toSymbolV2(ppath string) string {
|
|||||||
}
|
}
|
||||||
return string(bsl)
|
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)
|
||||||
|
}
|
||||||
|
@ -24,6 +24,9 @@ func init() {
|
|||||||
case "v2":
|
case "v2":
|
||||||
os.Stdout.WriteString(`.string "go.l..u00e4ufer.Run"`)
|
os.Stdout.WriteString(`.string "go.l..u00e4ufer.Run"`)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
case "v3":
|
||||||
|
os.Stdout.WriteString(`.string "go_0l_u00e4ufer.Run"`)
|
||||||
|
os.Exit(0)
|
||||||
case "error":
|
case "error":
|
||||||
os.Stdout.WriteString(`unknown string`)
|
os.Stdout.WriteString(`unknown string`)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
@ -45,6 +48,10 @@ func TestToSymbolFunc(t *testing.T) {
|
|||||||
env: "v2",
|
env: "v2",
|
||||||
mangled: "p..u00e4..u4e16..U0001f703",
|
mangled: "p..u00e4..u4e16..U0001f703",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
env: "v3",
|
||||||
|
mangled: "p_u00e4_u4e16_U0001f703",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
env: "error",
|
env: "error",
|
||||||
fail: true,
|
fail: true,
|
||||||
@ -75,32 +82,37 @@ func TestToSymbolFunc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var symbolTests = []struct {
|
var symbolTests = []struct {
|
||||||
input, v1, v2 string
|
input, v1, v2, v3 string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
|
"",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bytes",
|
"bytes",
|
||||||
"bytes",
|
"bytes",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"bytes",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"net/http",
|
"net/http",
|
||||||
"net_http",
|
"net_http",
|
||||||
"net..z2fhttp",
|
"net..z2fhttp",
|
||||||
|
"net_1http",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"golang.org/x/net/http",
|
"golang.org/x/net/http",
|
||||||
"golang_org_x_net_http",
|
"golang_org_x_net_http",
|
||||||
"golang.x2eorg..z2fx..z2fnet..z2fhttp",
|
"golang.x2eorg..z2fx..z2fnet..z2fhttp",
|
||||||
|
"golang_0org_1x_1net_1http",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"pä世.🜃",
|
"pä世.🜃",
|
||||||
"p____",
|
"p____",
|
||||||
"p..u00e4..u4e16.x2e..U0001f703",
|
"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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user