From 0f8dffd0aa71ed996d32e77701ac5ec0bc7cde01 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 8 May 2021 00:45:06 +0700 Subject: all: use ":" for compiler generated symbols As it can't appear in user package paths. There is a hack for handling "go:buildid" and "type:*" on windows/386. Previously, windows/386 requires underscore prefix on external symbols, but that's only applied for SHOSTOBJ/SUNDEFEXT or cgo export symbols. "go.buildid" is STEXT, "type.*" is STYPE, thus they are not prefixed with underscore. In external linking mode, the external linker can't resolve them as external symbols. But we are lucky that they have "." in their name, so the external linker see them as Forwarder RVA exports. See: - https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#export-address-table - https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=ld/pe-dll.c;h=e7b82ba6ffadf74dc1b9ee71dc13d48336941e51;hb=HEAD#l972) This CL changes "." to ":" in symbols name, so theses symbols can not be found by external linker anymore. So a hacky way is adding the underscore prefix for these 2 symbols. I don't have enough knowledge to verify whether adding the underscore for all STEXT/STYPE symbols are fine, even if it could be, that would be done in future CL. Fixes #37762 Change-Id: I92eaaf24c0820926a36e0530fdb07b07af1fcc35 Reviewed-on: https://go-review.googlesource.com/c/go/+/317917 Reviewed-by: Than McIntosh Run-TryBot: Cuong Manh Le Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/cmd/compile/internal/base/link.go | 19 ++++++++++++++++++- src/cmd/compile/internal/dwarfgen/dwarf.go | 2 +- src/cmd/compile/internal/gc/main.go | 4 ++-- src/cmd/compile/internal/gc/obj.go | 2 +- src/cmd/compile/internal/ir/expr.go | 1 - src/cmd/compile/internal/noder/import.go | 12 +----------- src/cmd/compile/internal/ppc64/ssa.go | 2 +- src/cmd/compile/internal/reflectdata/reflect.go | 22 +++++++++++----------- src/cmd/compile/internal/staticdata/data.go | 2 +- 9 files changed, 36 insertions(+), 30 deletions(-) (limited to 'src/cmd/compile/internal') diff --git a/src/cmd/compile/internal/base/link.go b/src/cmd/compile/internal/base/link.go index 49fe4352b2..d8aa5a7dcc 100644 --- a/src/cmd/compile/internal/base/link.go +++ b/src/cmd/compile/internal/base/link.go @@ -8,6 +8,19 @@ import ( "cmd/internal/obj" ) +// ReservedImports are import paths used internally for generated +// symbols by the compiler. +// +// The linker uses the magic symbol prefixes "go:" and "type:". +// Avoid potential confusion between import paths and symbols +// by rejecting these reserved imports for now. Also, people +// "can do weird things in GOPATH and we'd prefer they didn't +// do _that_ weird thing" (per rsc). See also #4257. +var ReservedImports = map[string]bool{ + "go": true, + "type": true, +} + var Ctxt *obj.Link // TODO(mdempsky): These should probably be obj.Link methods. @@ -20,7 +33,11 @@ func PkgLinksym(prefix, name string, abi obj.ABI) *obj.LSym { // TODO(mdempsky): Cleanup callers and Fatalf instead. return linksym(prefix, "_", abi) } - return linksym(prefix, prefix+"."+name, abi) + sep := "." + if ReservedImports[prefix] { + sep = ":" + } + return linksym(prefix, prefix+sep+name, abi) } // Linkname returns the linker symbol for the given name as it might diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index 4bbc04826a..bdaa043396 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -471,7 +471,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var gotype := reflectdata.TypeLinksym(n.Type()) delete(fnsym.Func().Autot, gotype) - typename := dwarf.InfoPrefix + gotype.Name[len("type."):] + typename := dwarf.InfoPrefix + gotype.Name[len("type:"):] inlIndex := 0 if base.Flag.GenDwarfInl > 1 { if n.InlFormal() || n.InlLocal() { diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index a5a2d56c46..c9493bf593 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -77,7 +77,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { // pseudo-package, for scoping types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? - types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin + types.BuiltinPkg.Prefix = "go:builtin" // pseudo-package, accessed by import "unsafe" types.UnsafePkg = types.NewPkg("unsafe", "unsafe") @@ -92,7 +92,7 @@ func Main(archInit func(*ssagen.ArchInfo)) { // pseudo-packages used in symbol tables ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab") - ir.Pkgs.Itab.Prefix = "go.itab" // not go%2eitab + ir.Pkgs.Itab.Prefix = "go:itab" // pseudo-package used for methods with anonymous receivers ir.Pkgs.Go = types.NewPkg("go", "") diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 5008aa212a..715b8ee263 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -148,7 +148,7 @@ func dumpdata() { dumpglobls(typecheck.Target.Externs[numExterns:]) if reflectdata.ZeroSize > 0 { - zero := base.PkgLinksym("go.map", "zero", obj.ABI0) + zero := base.PkgLinksym("go:map", "zero", obj.ABI0) objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA) zero.Set(obj.AttrStatic, true) } diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go index 0058a98824..83105de253 100644 --- a/src/cmd/compile/internal/ir/expr.go +++ b/src/cmd/compile/internal/ir/expr.go @@ -1134,7 +1134,6 @@ func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy b.WriteString(".") b.WriteString(msym.Name) b.WriteString(suffix) - return rpkg.LookupBytes(b.Bytes()) } diff --git a/src/cmd/compile/internal/noder/import.go b/src/cmd/compile/internal/noder/import.go index 49b8fd142a..8b017ecfd5 100644 --- a/src/cmd/compile/internal/noder/import.go +++ b/src/cmd/compile/internal/noder/import.go @@ -355,16 +355,6 @@ func addFingerprint(path string, f *os.File, end int64) error { return nil } -// The linker uses the magic symbol prefixes "go." and "type." -// Avoid potential confusion between import paths and symbols -// by rejecting these reserved imports for now. Also, people -// "can do weird things in GOPATH and we'd prefer they didn't -// do _that_ weird thing" (per rsc). See also #4257. -var reservedimports = []string{ - "go", - "type", -} - func checkImportPath(path string, allowSpace bool) error { if path == "" { return errors.New("import path is empty") @@ -374,7 +364,7 @@ func checkImportPath(path string, allowSpace bool) error { return errors.New("import path contains NUL") } - for _, ri := range reservedimports { + for ri := range base.ReservedImports { if path == ri { return fmt.Errorf("import path %q is reserved and cannot be used", path) } diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index c4097947bf..af75b04c6b 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -853,7 +853,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // Special case for a rule combines the bytes of gostring. // The v alignment might seem OK, but we don't want to load it // using an offset because relocation comes later. - genAddr = strings.HasPrefix(fromAddr.Sym.Name, "go.string") || v.Type.Alignment()%4 != 0 || fromAddr.Offset%4 != 0 + genAddr = strings.HasPrefix(fromAddr.Sym.Name, "go:string") || v.Type.Alignment()%4 != 0 || fromAddr.Offset%4 != 0 default: genAddr = fromAddr.Offset%4 != 0 } diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8fb2d50c40..5833c71f4c 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -411,7 +411,7 @@ func dimportpath(p *types.Pkg) { return } - s := base.Ctxt.Lookup("type..importpath." + p.Prefix + ".") + s := base.Ctxt.Lookup("type:.importpath." + p.Prefix + ".") ot := dnameData(s, 0, p.Path, "", nil, false, false) objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA) s.Set(obj.AttrContentAddressable, true) @@ -426,10 +426,10 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int { if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { // If we don't know the full import path of the package being compiled // (i.e. -p was not passed on the compiler command line), emit a reference to - // type..importpath.""., which the linker will rewrite using the correct import path. + // type:.importpath.""., which the linker will rewrite using the correct import path. // Every package that imports this one directly defines the symbol. // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. - ns := base.Ctxt.Lookup(`type..importpath."".`) + ns := base.Ctxt.Lookup(`type:.importpath."".`) return objw.SymPtr(s, ot, ns, 0) } @@ -445,10 +445,10 @@ func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int { if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" { // If we don't know the full import path of the package being compiled // (i.e. -p was not passed on the compiler command line), emit a reference to - // type..importpath.""., which the linker will rewrite using the correct import path. + // type:.importpath.""., which the linker will rewrite using the correct import path. // Every package that imports this one directly defines the symbol. // See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. - ns := base.Ctxt.Lookup(`type..importpath."".`) + ns := base.Ctxt.Lookup(`type:.importpath."".`) return objw.SymPtrOff(s, ot, ns) } @@ -517,11 +517,11 @@ var dnameCount int // dname creates a reflect.name for a struct field or method. func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym { - // Write out data as "type.." to signal two things to the + // Write out data as "type:." to signal two things to the // linker, first that when dynamically linking, the symbol // should be moved to a relro section, and second that the // contents should not be decoded as a type. - sname := "type..namedata." + sname := "type:.namedata." if pkg == nil { // In the common case, share data with other packages. if name == "" { @@ -798,7 +798,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { // TrackSym returns the symbol for tracking use of field/method f, assumed // to be a member of struct/interface type t. func TrackSym(t *types.Type, f *types.Field) *obj.LSym { - return base.PkgLinksym("go.track", t.LinkString()+"."+f.Sym.Name, obj.ABI0) + return base.PkgLinksym("go:track", t.LinkString()+"."+f.Sym.Name, obj.ABI0) } func TypeSymPrefix(prefix string, t *types.Type) *types.Sym { @@ -1358,7 +1358,7 @@ func WriteTabs() { // process ptabs if types.LocalPkg.Name == "main" && len(ptabs) > 0 { ot := 0 - s := base.Ctxt.Lookup("go.plugin.tabs") + s := base.Ctxt.Lookup("go:plugin.tabs") for _, p := range ptabs { // Dump ptab symbol into go.pluginsym package. // @@ -1381,7 +1381,7 @@ func WriteTabs() { objw.Global(s, int32(ot), int16(obj.RODATA)) ot = 0 - s = base.Ctxt.Lookup("go.plugin.exports") + s = base.Ctxt.Lookup("go:plugin.exports") for _, p := range ptabs { ot = objw.SymPtr(s, ot, p.Linksym(), 0) } @@ -1715,7 +1715,7 @@ func ZeroAddr(size int64) ir.Node { if ZeroSize < size { ZeroSize = size } - lsym := base.PkgLinksym("go.map", "zero", obj.ABI0) + lsym := base.PkgLinksym("go:map", "zero", obj.ABI0) x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8]) return typecheck.Expr(typecheck.NodAddr(x)) } diff --git a/src/cmd/compile/internal/staticdata/data.go b/src/cmd/compile/internal/staticdata/data.go index 621da9cbf6..da0db5a573 100644 --- a/src/cmd/compile/internal/staticdata/data.go +++ b/src/cmd/compile/internal/staticdata/data.go @@ -61,7 +61,7 @@ func InitSliceBytes(nam *ir.Name, off int64, s string) { } const ( - stringSymPrefix = "go.string." + stringSymPrefix = "go:string." stringSymPattern = ".gostring.%d.%s" ) -- cgit v1.3