@@ -6,6 +6,7 @@ package main
66
77import (
88 "bytes"
9+ "cmd/internal/pkgpath"
910 "debug/elf"
1011 "debug/macho"
1112 "debug/pe"
@@ -15,7 +16,6 @@ import (
1516 "go/token"
1617 "internal/xcoff"
1718 "io"
18- "io/ioutil"
1919 "os"
2020 "os/exec"
2121 "path/filepath"
@@ -1282,112 +1282,24 @@ func (p *Package) writeExportHeader(fgcch io.Writer) {
12821282 fmt .Fprintf (fgcch , "%s\n " , p .gccExportHeaderProlog ())
12831283}
12841284
1285- // gccgoUsesNewMangling reports whether gccgo uses the new collision-free
1286- // packagepath mangling scheme (see determineGccgoManglingScheme for more
1287- // info).
1288- func gccgoUsesNewMangling () bool {
1289- if ! gccgoMangleCheckDone {
1290- gccgoNewmanglingInEffect = determineGccgoManglingScheme ()
1291- gccgoMangleCheckDone = true
1292- }
1293- return gccgoNewmanglingInEffect
1294- }
1295-
1296- const mangleCheckCode = `
1297- package läufer
1298- func Run(x int) int {
1299- return 1
1300- }
1301- `
1302-
1303- // determineGccgoManglingScheme performs a runtime test to see which
1304- // flavor of packagepath mangling gccgo is using. Older versions of
1305- // gccgo use a simple mangling scheme where there can be collisions
1306- // between packages whose paths are different but mangle to the same
1307- // string. More recent versions of gccgo use a new mangler that avoids
1308- // these collisions. Return value is whether gccgo uses the new mangling.
1309- func determineGccgoManglingScheme () bool {
1310-
1311- // Emit a small Go file for gccgo to compile.
1312- filepat := "*_gccgo_manglecheck.go"
1313- var f * os.File
1314- var err error
1315- if f , err = ioutil .TempFile (* objDir , filepat ); err != nil {
1316- fatalf ("%v" , err )
1317- }
1318- gofilename := f .Name ()
1319- defer os .Remove (gofilename )
1320-
1321- if err = ioutil .WriteFile (gofilename , []byte (mangleCheckCode ), 0666 ); err != nil {
1322- fatalf ("%v" , err )
1323- }
1324-
1325- // Compile with gccgo, capturing generated assembly.
1326- gccgocmd := os .Getenv ("GCCGO" )
1327- if gccgocmd == "" {
1328- gpath , gerr := exec .LookPath ("gccgo" )
1329- if gerr != nil {
1330- fatalf ("unable to locate gccgo: %v" , gerr )
1331- }
1332- gccgocmd = gpath
1333- }
1334- cmd := exec .Command (gccgocmd , "-S" , "-o" , "-" , gofilename )
1335- buf , cerr := cmd .CombinedOutput ()
1336- if cerr != nil {
1337- fatalf ("%s" , cerr )
1338- }
1339-
1340- // New mangling: expect go.l..u00e4ufer.Run
1341- // Old mangling: expect go.l__ufer.Run
1342- return regexp .MustCompile (`go\.l\.\.u00e4ufer\.Run` ).Match (buf )
1343- }
1344-
1345- // gccgoPkgpathToSymbolNew converts a package path to a gccgo-style
1346- // package symbol.
1347- func gccgoPkgpathToSymbolNew (ppath string ) string {
1348- bsl := []byte {}
1349- changed := false
1350- for _ , c := range []byte (ppath ) {
1351- switch {
1352- case 'A' <= c && c <= 'Z' , 'a' <= c && c <= 'z' ,
1353- '0' <= c && c <= '9' , c == '_' :
1354- bsl = append (bsl , c )
1355- case c == '.' :
1356- bsl = append (bsl , ".x2e" ... )
1357- default :
1358- changed = true
1359- encbytes := []byte (fmt .Sprintf ("..z%02x" , c ))
1360- bsl = append (bsl , encbytes ... )
1361- }
1362- }
1363- if ! changed {
1364- return ppath
1365- }
1366- return string (bsl )
1367- }
1368-
1369- // gccgoPkgpathToSymbolOld converts a package path to a gccgo-style
1370- // package symbol using the older mangling scheme.
1371- func gccgoPkgpathToSymbolOld (ppath string ) string {
1372- clean := func (r rune ) rune {
1373- switch {
1374- case 'A' <= r && r <= 'Z' , 'a' <= r && r <= 'z' ,
1375- '0' <= r && r <= '9' :
1376- return r
1377- }
1378- return '_'
1379- }
1380- return strings .Map (clean , ppath )
1381- }
1382-
13831285// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
13841286// symbol.
13851287func gccgoPkgpathToSymbol (ppath string ) string {
1386- if gccgoUsesNewMangling () {
1387- return gccgoPkgpathToSymbolNew (ppath )
1388- } else {
1389- return gccgoPkgpathToSymbolOld (ppath )
1288+ if gccgoMangler == nil {
1289+ var err error
1290+ cmd := os .Getenv ("GCCGO" )
1291+ if cmd == "" {
1292+ cmd , err = exec .LookPath ("gccgo" )
1293+ if err != nil {
1294+ fatalf ("unable to locate gccgo: %v" , err )
1295+ }
1296+ }
1297+ gccgoMangler , err = pkgpath .ToSymbolFunc (cmd , * objDir )
1298+ if err != nil {
1299+ fatalf ("%v" , err )
1300+ }
13901301 }
1302+ return gccgoMangler (ppath )
13911303}
13921304
13931305// Return the package prefix when using gccgo.
0 commit comments