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 <thanm@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Cuong Manh Le 2021-05-08 00:45:06 +07:00
parent 5639fcae7f
commit 0f8dffd0aa
37 changed files with 283 additions and 231 deletions

View File

@ -589,12 +589,12 @@ func testABIHashNote(t *testing.T, f *elf.File, note *note) {
return return
} }
for _, sym := range symbols { for _, sym := range symbols {
if sym.Name == "go.link.abihashbytes" { if sym.Name == "go:link.abihashbytes" {
hashbytes = sym hashbytes = sym
} }
} }
if hashbytes.Name == "" { if hashbytes.Name == "" {
t.Errorf("no symbol called go.link.abihashbytes") t.Errorf("no symbol called go:link.abihashbytes")
return return
} }
if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL { if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL {

View File

@ -8,6 +8,19 @@ import (
"cmd/internal/obj" "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 var Ctxt *obj.Link
// TODO(mdempsky): These should probably be obj.Link methods. // 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. // TODO(mdempsky): Cleanup callers and Fatalf instead.
return linksym(prefix, "_", abi) 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 // Linkname returns the linker symbol for the given name as it might

View File

@ -471,7 +471,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var
gotype := reflectdata.TypeLinksym(n.Type()) gotype := reflectdata.TypeLinksym(n.Type())
delete(fnsym.Func().Autot, gotype) delete(fnsym.Func().Autot, gotype)
typename := dwarf.InfoPrefix + gotype.Name[len("type."):] typename := dwarf.InfoPrefix + gotype.Name[len("type:"):]
inlIndex := 0 inlIndex := 0
if base.Flag.GenDwarfInl > 1 { if base.Flag.GenDwarfInl > 1 {
if n.InlFormal() || n.InlLocal() { if n.InlFormal() || n.InlLocal() {

View File

@ -77,7 +77,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
// pseudo-package, for scoping // pseudo-package, for scoping
types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? 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" // pseudo-package, accessed by import "unsafe"
types.UnsafePkg = types.NewPkg("unsafe", "unsafe") types.UnsafePkg = types.NewPkg("unsafe", "unsafe")
@ -92,7 +92,7 @@ func Main(archInit func(*ssagen.ArchInfo)) {
// pseudo-packages used in symbol tables // pseudo-packages used in symbol tables
ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab") 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 // pseudo-package used for methods with anonymous receivers
ir.Pkgs.Go = types.NewPkg("go", "") ir.Pkgs.Go = types.NewPkg("go", "")

View File

@ -148,7 +148,7 @@ func dumpdata() {
dumpglobls(typecheck.Target.Externs[numExterns:]) dumpglobls(typecheck.Target.Externs[numExterns:])
if reflectdata.ZeroSize > 0 { 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) objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
zero.Set(obj.AttrStatic, true) zero.Set(obj.AttrStatic, true)
} }

View File

@ -1134,7 +1134,6 @@ func MethodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy
b.WriteString(".") b.WriteString(".")
b.WriteString(msym.Name) b.WriteString(msym.Name)
b.WriteString(suffix) b.WriteString(suffix)
return rpkg.LookupBytes(b.Bytes()) return rpkg.LookupBytes(b.Bytes())
} }

View File

@ -355,16 +355,6 @@ func addFingerprint(path string, f *os.File, end int64) error {
return nil 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 { func checkImportPath(path string, allowSpace bool) error {
if path == "" { if path == "" {
return errors.New("import path is empty") 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") return errors.New("import path contains NUL")
} }
for _, ri := range reservedimports { for ri := range base.ReservedImports {
if path == ri { if path == ri {
return fmt.Errorf("import path %q is reserved and cannot be used", path) return fmt.Errorf("import path %q is reserved and cannot be used", path)
} }

View File

@ -853,7 +853,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
// Special case for a rule combines the bytes of gostring. // Special case for a rule combines the bytes of gostring.
// The v alignment might seem OK, but we don't want to load it // The v alignment might seem OK, but we don't want to load it
// using an offset because relocation comes later. // 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: default:
genAddr = fromAddr.Offset%4 != 0 genAddr = fromAddr.Offset%4 != 0
} }

View File

@ -411,7 +411,7 @@ func dimportpath(p *types.Pkg) {
return 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) ot := dnameData(s, 0, p.Path, "", nil, false, false)
objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA) objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
s.Set(obj.AttrContentAddressable, true) 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 pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" {
// If we don't know the full import path of the package being compiled // 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 // (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. // Every package that imports this one directly defines the symbol.
// See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. // 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) 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 pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" {
// If we don't know the full import path of the package being compiled // 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 // (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. // Every package that imports this one directly defines the symbol.
// See also https://groups.google.com/forum/#!topic/golang-dev/myb9s53HxGQ. // 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) return objw.SymPtrOff(s, ot, ns)
} }
@ -517,11 +517,11 @@ var dnameCount int
// dname creates a reflect.name for a struct field or method. // dname creates a reflect.name for a struct field or method.
func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym { 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 // linker, first that when dynamically linking, the symbol
// should be moved to a relro section, and second that the // should be moved to a relro section, and second that the
// contents should not be decoded as a type. // contents should not be decoded as a type.
sname := "type..namedata." sname := "type:.namedata."
if pkg == nil { if pkg == nil {
// In the common case, share data with other packages. // In the common case, share data with other packages.
if name == "" { 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 // TrackSym returns the symbol for tracking use of field/method f, assumed
// to be a member of struct/interface type t. // to be a member of struct/interface type t.
func TrackSym(t *types.Type, f *types.Field) *obj.LSym { 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 { func TypeSymPrefix(prefix string, t *types.Type) *types.Sym {
@ -1358,7 +1358,7 @@ func WriteTabs() {
// process ptabs // process ptabs
if types.LocalPkg.Name == "main" && len(ptabs) > 0 { if types.LocalPkg.Name == "main" && len(ptabs) > 0 {
ot := 0 ot := 0
s := base.Ctxt.Lookup("go.plugin.tabs") s := base.Ctxt.Lookup("go:plugin.tabs")
for _, p := range ptabs { for _, p := range ptabs {
// Dump ptab symbol into go.pluginsym package. // Dump ptab symbol into go.pluginsym package.
// //
@ -1381,7 +1381,7 @@ func WriteTabs() {
objw.Global(s, int32(ot), int16(obj.RODATA)) objw.Global(s, int32(ot), int16(obj.RODATA))
ot = 0 ot = 0
s = base.Ctxt.Lookup("go.plugin.exports") s = base.Ctxt.Lookup("go:plugin.exports")
for _, p := range ptabs { for _, p := range ptabs {
ot = objw.SymPtr(s, ot, p.Linksym(), 0) ot = objw.SymPtr(s, ot, p.Linksym(), 0)
} }
@ -1715,7 +1715,7 @@ func ZeroAddr(size int64) ir.Node {
if ZeroSize < size { if ZeroSize < size {
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]) x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8])
return typecheck.Expr(typecheck.NodAddr(x)) return typecheck.Expr(typecheck.NodAddr(x))
} }

View File

@ -61,7 +61,7 @@ func InitSliceBytes(nam *ir.Name, off int64, s string) {
} }
const ( const (
stringSymPrefix = "go.string." stringSymPrefix = "go:string."
stringSymPattern = ".gostring.%d.%s" stringSymPattern = ".gostring.%d.%s"
) )

View File

@ -21,15 +21,15 @@ import (
) )
// InfoPrefix is the prefix for all the symbols containing DWARF info entries. // InfoPrefix is the prefix for all the symbols containing DWARF info entries.
const InfoPrefix = "go.info." const InfoPrefix = "go:info."
// ConstInfoPrefix is the prefix for all symbols containing DWARF info // ConstInfoPrefix is the prefix for all symbols containing DWARF info
// entries that contain constants. // entries that contain constants.
const ConstInfoPrefix = "go.constinfo." const ConstInfoPrefix = "go:constinfo."
// CUInfoPrefix is the prefix for symbols containing information to // CUInfoPrefix is the prefix for symbols containing information to
// populate the DWARF compilation unit info entries. // populate the DWARF compilation unit info entries.
const CUInfoPrefix = "go.cuinfo." const CUInfoPrefix = "go:cuinfo."
// Used to form the symbol name assigned to the DWARF 'abstract subprogram" // Used to form the symbol name assigned to the DWARF 'abstract subprogram"
// info entry for a function // info entry for a function

View File

@ -214,40 +214,40 @@ var builtins = [...]struct {
{"runtime.morestack", 0}, {"runtime.morestack", 0},
{"runtime.morestackc", 0}, {"runtime.morestackc", 0},
{"runtime.morestack_noctxt", 0}, {"runtime.morestack_noctxt", 0},
{"type.int8", 0}, {"type:int8", 0},
{"type.*int8", 0}, {"type:*int8", 0},
{"type.uint8", 0}, {"type:uint8", 0},
{"type.*uint8", 0}, {"type:*uint8", 0},
{"type.int16", 0}, {"type:int16", 0},
{"type.*int16", 0}, {"type:*int16", 0},
{"type.uint16", 0}, {"type:uint16", 0},
{"type.*uint16", 0}, {"type:*uint16", 0},
{"type.int32", 0}, {"type:int32", 0},
{"type.*int32", 0}, {"type:*int32", 0},
{"type.uint32", 0}, {"type:uint32", 0},
{"type.*uint32", 0}, {"type:*uint32", 0},
{"type.int64", 0}, {"type:int64", 0},
{"type.*int64", 0}, {"type:*int64", 0},
{"type.uint64", 0}, {"type:uint64", 0},
{"type.*uint64", 0}, {"type:*uint64", 0},
{"type.float32", 0}, {"type:float32", 0},
{"type.*float32", 0}, {"type:*float32", 0},
{"type.float64", 0}, {"type:float64", 0},
{"type.*float64", 0}, {"type:*float64", 0},
{"type.complex64", 0}, {"type:complex64", 0},
{"type.*complex64", 0}, {"type:*complex64", 0},
{"type.complex128", 0}, {"type:complex128", 0},
{"type.*complex128", 0}, {"type:*complex128", 0},
{"type.unsafe.Pointer", 0}, {"type:unsafe.Pointer", 0},
{"type.*unsafe.Pointer", 0}, {"type:*unsafe.Pointer", 0},
{"type.uintptr", 0}, {"type:uintptr", 0},
{"type.*uintptr", 0}, {"type:*uintptr", 0},
{"type.bool", 0}, {"type:bool", 0},
{"type.*bool", 0}, {"type:*bool", 0},
{"type.string", 0}, {"type:string", 0},
{"type.*string", 0}, {"type:*string", 0},
{"type.error", 0}, {"type:error", 0},
{"type.*error", 0}, {"type:*error", 0},
{"type.func(error) string", 0}, {"type:func(error) string", 0},
{"type.*func(error) string", 0}, {"type:*func(error) string", 0},
} }

View File

@ -105,7 +105,7 @@ func mkbuiltin(w io.Writer) {
extras := append(fextras[:], enumerateBasicTypes()...) extras := append(fextras[:], enumerateBasicTypes()...)
for _, b := range extras { for _, b := range extras {
prefix := "" prefix := ""
if !strings.HasPrefix(b.name, "type.") { if !strings.HasPrefix(b.name, "type:") {
prefix = pkg + "." prefix = pkg + "."
} }
name := prefix + b.name name := prefix + b.name
@ -130,8 +130,8 @@ func enumerateBasicTypes() []extra {
"func(error) string"} "func(error) string"}
result := []extra{} result := []extra{}
for _, n := range names { for _, n := range names {
result = append(result, extra{"type." + n, 0}) result = append(result, extra{"type:" + n, 0})
result = append(result, extra{"type.*" + n, 0}) result = append(result, extra{"type:*" + n, 0})
} }
return result return result
} }

View File

@ -321,14 +321,14 @@ func (w *writer) Sym(s *LSym) {
if s.ReflectMethod() { if s.ReflectMethod() {
flag |= goobj.SymFlagReflectMethod flag |= goobj.SymFlagReflectMethod
} }
if strings.HasPrefix(s.Name, "type.") && s.Name[5] != '.' && s.Type == objabi.SRODATA { if strings.HasPrefix(s.Name, "type:") && s.Name[5] != '.' && s.Type == objabi.SRODATA {
flag |= goobj.SymFlagGoType flag |= goobj.SymFlagGoType
} }
flag2 := uint8(0) flag2 := uint8(0)
if s.UsedInIface() { if s.UsedInIface() {
flag2 |= goobj.SymFlagUsedInIface flag2 |= goobj.SymFlagUsedInIface
} }
if strings.HasPrefix(s.Name, "go.itab.") && s.Type == objabi.SRODATA { if strings.HasPrefix(s.Name, "go:itab.") && s.Type == objabi.SRODATA {
flag2 |= goobj.SymFlagItab flag2 |= goobj.SymFlagItab
} }
if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], ".") && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath)+1:], objabi.GlobalDictPrefix) { if strings.HasPrefix(s.Name, w.ctxt.Pkgpath) && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath):], ".") && strings.HasPrefix(s.Name[len(w.ctxt.Pkgpath)+1:], objabi.GlobalDictPrefix) {
@ -351,9 +351,9 @@ func (w *writer) Sym(s *LSym) {
// TODO: maybe the compiler could set the alignment for all // TODO: maybe the compiler could set the alignment for all
// data symbols more carefully. // data symbols more carefully.
switch { switch {
case strings.HasPrefix(s.Name, "go.string."), case strings.HasPrefix(s.Name, "go:string."),
strings.HasPrefix(name, "type..namedata."), strings.HasPrefix(name, "type:.namedata."),
strings.HasPrefix(name, "type..importpath."), strings.HasPrefix(name, "type:.importpath."),
strings.HasPrefix(name, "runtime.gcbits."), strings.HasPrefix(name, "runtime.gcbits."),
strings.HasSuffix(name, ".opendefer"), strings.HasSuffix(name, ".opendefer"),
strings.HasSuffix(name, ".arginfo0"), strings.HasSuffix(name, ".arginfo0"),
@ -430,9 +430,9 @@ func contentHashSection(s *LSym) byte {
strings.HasSuffix(name, ".wrapinfo") || strings.HasSuffix(name, ".wrapinfo") ||
strings.HasSuffix(name, ".args_stackmap") || strings.HasSuffix(name, ".args_stackmap") ||
strings.HasSuffix(name, ".stkobj") { strings.HasSuffix(name, ".stkobj") {
return 'F' // go.func.* or go.funcrel.* return 'F' // go:func.* or go:funcrel.*
} }
if strings.HasPrefix(name, "type.") { if strings.HasPrefix(name, "type:") {
return 'T' return 'T'
} }
return 0 return 0

View File

@ -222,7 +222,7 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
if ldr.SymName(rs) == "main.main" || (!target.IsPlugin() && ldr.SymName(rs) == "main..inittask") { if ldr.SymName(rs) == "main.main" || (!target.IsPlugin() && ldr.SymName(rs) == "main..inittask") {
sb := ldr.MakeSymbolUpdater(rs) sb := ldr.MakeSymbolUpdater(rs)
sb.SetType(sym.SDYNIMPORT) sb.SetType(sym.SDYNIMPORT)
} else if strings.HasPrefix(ldr.SymName(rs), "go.info.") { } else if strings.HasPrefix(ldr.SymName(rs), "go:info.") {
// Skip go.info symbols. They are only needed to communicate // Skip go.info symbols. They are only needed to communicate
// DWARF info between the compiler and linker. // DWARF info between the compiler and linker.
continue continue
@ -1108,7 +1108,7 @@ func addstrdata(arch *sys.Arch, l *loader.Loader, name, value string) {
} }
if goType := l.SymGoType(s); goType == 0 { if goType := l.SymGoType(s); goType == 0 {
return return
} else if typeName := l.SymName(goType); typeName != "type.string" { } else if typeName := l.SymName(goType); typeName != "type:string" {
Errorf(nil, "%s: cannot set with -X: not a var of type string (%s)", name, typeName) Errorf(nil, "%s: cannot set with -X: not a var of type string (%s)", name, typeName)
return return
} }
@ -2152,7 +2152,7 @@ func (ctxt *Link) textbuildid() {
} }
ldr := ctxt.loader ldr := ctxt.loader
s := ldr.CreateSymForUpdate("go.buildid", 0) s := ldr.CreateSymForUpdate("go:buildid", 0)
// The \xff is invalid UTF-8, meant to make it less likely // The \xff is invalid UTF-8, meant to make it less likely
// to find one of these accidentally. // to find one of these accidentally.
data := "\xff Go build ID: " + strconv.Quote(*flagBuildid) + "\n \xff" data := "\xff Go build ID: " + strconv.Quote(*flagBuildid) + "\n \xff"
@ -2627,7 +2627,7 @@ func (ctxt *Link) address() []*sym.Segment {
} }
if ctxt.BuildMode == BuildModeShared { if ctxt.BuildMode == BuildModeShared {
s := ldr.LookupOrCreateSym("go.link.abihashbytes", 0) s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
sect := ldr.SymSect(ldr.LookupOrCreateSym(".note.go.abihash", 0)) sect := ldr.SymSect(ldr.LookupOrCreateSym(".note.go.abihash", 0))
ldr.SetSymSect(s, sect) ldr.SetSymSect(s, sect)
ldr.SetSymValue(s, int64(sect.Vaddr+16)) ldr.SetSymValue(s, int64(sect.Vaddr+16))

View File

@ -72,11 +72,11 @@ func (d *deadcodePass) init() {
// We redirect unreachable methods to it. // We redirect unreachable methods to it.
names = append(names, "runtime.unreachableMethod") names = append(names, "runtime.unreachableMethod")
if d.ctxt.BuildMode == BuildModePlugin { if d.ctxt.BuildMode == BuildModePlugin {
names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs") names = append(names, objabi.PathToPrefix(*flagPluginPath)+"..inittask", objabi.PathToPrefix(*flagPluginPath)+".main", "go:plugin.tabs")
// We don't keep the go.plugin.exports symbol, // We don't keep the go.plugin.exports symbol,
// but we do keep the symbols it refers to. // but we do keep the symbols it refers to.
exportsIdx := d.ldr.Lookup("go.plugin.exports", 0) exportsIdx := d.ldr.Lookup("go:plugin.exports", 0)
if exportsIdx != 0 { if exportsIdx != 0 {
relocs := d.ldr.Relocs(exportsIdx) relocs := d.ldr.Relocs(exportsIdx)
for i := 0; i < relocs.Count(); i++ { for i := 0; i < relocs.Count(); i++ {

View File

@ -23,7 +23,7 @@ func TestDeadcode(t *testing.T) {
pos, neg string // positive and negative patterns pos, neg string // positive and negative patterns
}{ }{
{"reflectcall", "", "main.T.M"}, {"reflectcall", "", "main.T.M"},
{"typedesc", "", "type.main.T"}, {"typedesc", "", "type:main.T"},
{"ifacemethod", "", "main.T.M"}, {"ifacemethod", "", "main.T.M"},
{"ifacemethod2", "main.T.M", ""}, {"ifacemethod2", "main.T.M", ""},
{"ifacemethod3", "main.S.M", ""}, {"ifacemethod3", "main.S.M", ""},

View File

@ -43,18 +43,18 @@ type dwctxt struct {
arch *sys.Arch arch *sys.Arch
// This maps type name string (e.g. "uintptr") to loader symbol for // This maps type name string (e.g. "uintptr") to loader symbol for
// the DWARF DIE for that type (e.g. "go.info.type.uintptr") // the DWARF DIE for that type (e.g. "go:info.type.uintptr")
tmap map[string]loader.Sym tmap map[string]loader.Sym
// This maps loader symbol for the DWARF DIE symbol generated for // This maps loader symbol for the DWARF DIE symbol generated for
// a type (e.g. "go.info.uintptr") to the type symbol itself // a type (e.g. "go:info.uintptr") to the type symbol itself
// ("type.uintptr"). // ("type:uintptr").
// FIXME: try converting this map (and the next one) to a single // FIXME: try converting this map (and the next one) to a single
// array indexed by loader.Sym -- this may perform better. // array indexed by loader.Sym -- this may perform better.
rtmap map[loader.Sym]loader.Sym rtmap map[loader.Sym]loader.Sym
// This maps Go type symbol (e.g. "type.XXX") to loader symbol for // This maps Go type symbol (e.g. "type:XXX") to loader symbol for
// the typedef DIE for that type (e.g. "go.info.XXX..def") // the typedef DIE for that type (e.g. "go:info.XXX..def")
tdmap map[loader.Sym]loader.Sym tdmap map[loader.Sym]loader.Sym
// Cache these type symbols, so as to avoid repeatedly looking them up // Cache these type symbols, so as to avoid repeatedly looking them up
@ -337,8 +337,8 @@ func walktypedef(die *dwarf.DWDie) *dwarf.DWDie {
func (d *dwctxt) walksymtypedef(symIdx loader.Sym) loader.Sym { func (d *dwctxt) walksymtypedef(symIdx loader.Sym) loader.Sym {
// We're being given the loader symbol for the type DIE, e.g. // We're being given the loader symbol for the type DIE, e.g.
// "go.info.type.uintptr". Map that first to the type symbol (e.g. // "go:info.type.uintptr". Map that first to the type symbol (e.g.
// "type.uintptr") and then to the typedef DIE for the type. // "type:uintptr") and then to the typedef DIE for the type.
// FIXME: this seems clunky, maybe there is a better way to do this. // FIXME: this seems clunky, maybe there is a better way to do this.
if ts, ok := d.rtmap[symIdx]; ok { if ts, ok := d.rtmap[symIdx]; ok {
@ -519,8 +519,8 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym {
} }
sn := d.ldr.SymName(gotype) sn := d.ldr.SymName(gotype)
if !strings.HasPrefix(sn, "type.") { if !strings.HasPrefix(sn, "type:") {
d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type.\"") d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type:\"")
return d.mustFind("<unspecified>") return d.mustFind("<unspecified>")
} }
name := sn[5:] // could also decode from Type.string name := sn[5:] // could also decode from Type.string
@ -678,7 +678,7 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie {
s := decodetypeStructFieldType(d.ldr, d.arch, gotype, i) s := decodetypeStructFieldType(d.ldr, d.arch, gotype, i)
if f == "" { if f == "" {
sn := d.ldr.SymName(s) sn := d.ldr.SymName(s)
f = sn[5:] // skip "type." f = sn[5:] // skip "type:"
} }
fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f) fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f)
d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s)) d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
@ -747,7 +747,7 @@ func (d *dwctxt) defptrto(dwtype loader.Sym) loader.Sym {
// The DWARF info synthesizes pointer types that don't exist at the // The DWARF info synthesizes pointer types that don't exist at the
// language level, like *hash<...> and *bucket<...>, and the data // language level, like *hash<...> and *bucket<...>, and the data
// pointers of slices. Link to the ones we can find. // pointers of slices. Link to the ones we can find.
gts := d.ldr.Lookup("type."+ptrname, 0) gts := d.ldr.Lookup("type:"+ptrname, 0)
if gts != 0 && d.ldr.AttrReachable(gts) { if gts != 0 && d.ldr.AttrReachable(gts) {
newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(gts)) newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(gts))
} }
@ -814,7 +814,7 @@ func (d *dwctxt) findprotodie(ctxt *Link, name string) *dwarf.DWDie {
} }
func (d *dwctxt) synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) { func (d *dwctxt) synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
prototype := walktypedef(d.findprotodie(ctxt, "type.runtime.stringStructDWARF")) prototype := walktypedef(d.findprotodie(ctxt, "type:runtime.stringStructDWARF"))
if prototype == nil { if prototype == nil {
return return
} }
@ -828,7 +828,7 @@ func (d *dwctxt) synthesizestringtypes(ctxt *Link, die *dwarf.DWDie) {
} }
func (d *dwctxt) synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) { func (d *dwctxt) synthesizeslicetypes(ctxt *Link, die *dwarf.DWDie) {
prototype := walktypedef(d.findprotodie(ctxt, "type.runtime.slice")) prototype := walktypedef(d.findprotodie(ctxt, "type:runtime.slice"))
if prototype == nil { if prototype == nil {
return return
} }
@ -870,8 +870,8 @@ func (d *dwctxt) mkinternaltype(ctxt *Link, abbrev int, typename, keyname, valna
} }
func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) { func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
hash := walktypedef(d.findprotodie(ctxt, "type.runtime.hmap")) hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap"))
bucket := walktypedef(d.findprotodie(ctxt, "type.runtime.bmap")) bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap"))
if hash == nil { if hash == nil {
return return
@ -966,9 +966,9 @@ func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
} }
func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) { func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
sudog := walktypedef(d.findprotodie(ctxt, "type.runtime.sudog")) sudog := walktypedef(d.findprotodie(ctxt, "type:runtime.sudog"))
waitq := walktypedef(d.findprotodie(ctxt, "type.runtime.waitq")) waitq := walktypedef(d.findprotodie(ctxt, "type:runtime.waitq"))
hchan := walktypedef(d.findprotodie(ctxt, "type.runtime.hchan")) hchan := walktypedef(d.findprotodie(ctxt, "type:runtime.hchan"))
if sudog == nil || waitq == nil || hchan == nil { if sudog == nil || waitq == nil || hchan == nil {
return return
} }
@ -1135,7 +1135,7 @@ func (d *dwctxt) importInfoSymbol(dsym loader.Sym) {
// symbol name here? // symbol name here?
sn := d.ldr.SymName(rsym) sn := d.ldr.SymName(rsym)
tn := sn[len(dwarf.InfoPrefix):] tn := sn[len(dwarf.InfoPrefix):]
ts := d.ldr.Lookup("type."+tn, 0) ts := d.ldr.Lookup("type:"+tn, 0)
d.defgotype(ts) d.defgotype(ts)
} }
} }
@ -1662,7 +1662,7 @@ func (d *dwctxt) mkBuiltinType(ctxt *Link, abrv int, tname string) *dwarf.DWDie
die := d.newdie(&dwtypes, abrv, tname) die := d.newdie(&dwtypes, abrv, tname)
// Look up type symbol. // Look up type symbol.
gotype := d.lookupOrDiag("type." + tname) gotype := d.lookupOrDiag("type:" + tname)
// Map from die sym to type sym // Map from die sym to type sym
ds := loader.Sym(die.Sym.(dwSym)) ds := loader.Sym(die.Sym.(dwSym))
@ -1735,7 +1735,7 @@ func (d *dwctxt) dwarfVisitFunction(fnSym loader.Sym, unit *sym.CompilationUnit)
rsn := d.ldr.SymName(rsym) rsn := d.ldr.SymName(rsym)
tn := rsn[len(dwarf.InfoPrefix):] tn := rsn[len(dwarf.InfoPrefix):]
ts := d.ldr.Lookup("type."+tn, 0) ts := d.ldr.Lookup("type:"+tn, 0)
d.defgotype(ts) d.defgotype(ts)
} }
} }
@ -1760,8 +1760,8 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
tdmap: make(map[loader.Sym]loader.Sym), tdmap: make(map[loader.Sym]loader.Sym),
rtmap: make(map[loader.Sym]loader.Sym), rtmap: make(map[loader.Sym]loader.Sym),
} }
d.typeRuntimeEface = d.lookupOrDiag("type.runtime.eface") d.typeRuntimeEface = d.lookupOrDiag("type:runtime.eface")
d.typeRuntimeIface = d.lookupOrDiag("type.runtime.iface") d.typeRuntimeIface = d.lookupOrDiag("type:runtime.iface")
if ctxt.HeadType == objabi.Haix { if ctxt.HeadType == objabi.Haix {
// Initial map used to store package size for each DWARF section. // Initial map used to store package size for each DWARF section.
@ -1781,34 +1781,34 @@ func dwarfGenerateDebugInfo(ctxt *Link) {
newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0) newattr(die, dwarf.DW_AT_encoding, dwarf.DW_CLS_CONSTANT, dwarf.DW_ATE_unsigned, 0)
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(d.arch.PtrSize), 0) newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, int64(d.arch.PtrSize), 0)
newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0) newattr(die, dwarf.DW_AT_go_kind, dwarf.DW_CLS_CONSTANT, objabi.KindUintptr, 0)
newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_ADDRESS, 0, dwSym(d.lookupOrDiag("type.uintptr"))) newattr(die, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_ADDRESS, 0, dwSym(d.lookupOrDiag("type:uintptr")))
d.uintptrInfoSym = d.mustFind("uintptr") d.uintptrInfoSym = d.mustFind("uintptr")
// Prototypes needed for type synthesis. // Prototypes needed for type synthesis.
prototypedies = map[string]*dwarf.DWDie{ prototypedies = map[string]*dwarf.DWDie{
"type.runtime.stringStructDWARF": nil, "type:runtime.stringStructDWARF": nil,
"type.runtime.slice": nil, "type:runtime.slice": nil,
"type.runtime.hmap": nil, "type:runtime.hmap": nil,
"type.runtime.bmap": nil, "type:runtime.bmap": nil,
"type.runtime.sudog": nil, "type:runtime.sudog": nil,
"type.runtime.waitq": nil, "type:runtime.waitq": nil,
"type.runtime.hchan": nil, "type:runtime.hchan": nil,
} }
// Needed by the prettyprinter code for interface inspection. // Needed by the prettyprinter code for interface inspection.
for _, typ := range []string{ for _, typ := range []string{
"type.runtime._type", "type:runtime._type",
"type.runtime.arraytype", "type:runtime.arraytype",
"type.runtime.chantype", "type:runtime.chantype",
"type.runtime.functype", "type:runtime.functype",
"type.runtime.maptype", "type:runtime.maptype",
"type.runtime.ptrtype", "type:runtime.ptrtype",
"type.runtime.slicetype", "type:runtime.slicetype",
"type.runtime.structtype", "type:runtime.structtype",
"type.runtime.interfacetype", "type:runtime.interfacetype",
"type.runtime.itab", "type:runtime.itab",
"type.runtime.imethod"} { "type:runtime.imethod"} {
d.defgotype(d.lookupOrDiag(typ)) d.defgotype(d.lookupOrDiag(typ))
} }

View File

@ -1531,7 +1531,7 @@ func (ctxt *Link) doelf() {
if ctxt.IsShared() { if ctxt.IsShared() {
// The go.link.abihashbytes symbol will be pointed at the appropriate // The go.link.abihashbytes symbol will be pointed at the appropriate
// part of the .note.go.abihash section in data.go:func address(). // part of the .note.go.abihash section in data.go:func address().
s := ldr.LookupOrCreateSym("go.link.abihashbytes", 0) s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
sb := ldr.MakeSymbolUpdater(s) sb := ldr.MakeSymbolUpdater(s)
ldr.SetAttrLocal(s, true) ldr.SetAttrLocal(s, true)
sb.SetType(sym.SRODATA) sb.SetType(sym.SRODATA)

View File

@ -385,7 +385,7 @@ func Adddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym)
func fieldtrack(arch *sys.Arch, l *loader.Loader) { func fieldtrack(arch *sys.Arch, l *loader.Loader) {
var buf bytes.Buffer var buf bytes.Buffer
for i := loader.Sym(1); i < loader.Sym(l.NSym()); i++ { for i := loader.Sym(1); i < loader.Sym(l.NSym()); i++ {
if name := l.SymName(i); strings.HasPrefix(name, "go.track.") { if name := l.SymName(i); strings.HasPrefix(name, "go:track.") {
if l.AttrReachable(i) { if l.AttrReachable(i) {
l.SetAttrSpecial(i, true) l.SetAttrSpecial(i, true)
l.SetAttrNotInSymbolTable(i, true) l.SetAttrNotInSymbolTable(i, true)

View File

@ -232,7 +232,7 @@ func PrepareAddmoduledata(ctxt *Link) (*loader.SymbolBuilder, loader.Sym) {
// Create a new init func text symbol. Caller will populate this // Create a new init func text symbol. Caller will populate this
// sym with arch-specific content. // sym with arch-specific content.
ifs := ctxt.loader.LookupOrCreateSym("go.link.addmoduledata", 0) ifs := ctxt.loader.LookupOrCreateSym("go:link.addmoduledata", 0)
initfunc := ctxt.loader.MakeSymbolUpdater(ifs) initfunc := ctxt.loader.MakeSymbolUpdater(ifs)
ctxt.loader.SetAttrReachable(ifs, true) ctxt.loader.SetAttrReachable(ifs, true)
ctxt.loader.SetAttrLocal(ifs, true) ctxt.loader.SetAttrLocal(ifs, true)
@ -245,7 +245,7 @@ func PrepareAddmoduledata(ctxt *Link) (*loader.SymbolBuilder, loader.Sym) {
ctxt.Textp = append(ctxt.Textp, initfunc.Sym()) ctxt.Textp = append(ctxt.Textp, initfunc.Sym())
// Create an init array entry // Create an init array entry
amdi := ctxt.loader.LookupOrCreateSym("go.link.addmoduledatainit", 0) amdi := ctxt.loader.LookupOrCreateSym("go:link.addmoduledatainit", 0)
initarray_entry := ctxt.loader.MakeSymbolUpdater(amdi) initarray_entry := ctxt.loader.MakeSymbolUpdater(amdi)
ctxt.loader.SetAttrReachable(amdi, true) ctxt.loader.SetAttrReachable(amdi, true)
ctxt.loader.SetAttrLocal(amdi, true) ctxt.loader.SetAttrLocal(amdi, true)

View File

@ -926,24 +926,24 @@ func (ctxt *Link) mangleTypeSym() {
// typeSymbolMangle mangles the given symbol name into something shorter. // typeSymbolMangle mangles the given symbol name into something shorter.
// //
// Keep the type.. prefix, which parts of the linker (like the // Keep the type:. prefix, which parts of the linker (like the
// DWARF generator) know means the symbol is not decodable. // DWARF generator) know means the symbol is not decodable.
// Leave type.runtime. symbols alone, because other parts of // Leave type:runtime. symbols alone, because other parts of
// the linker manipulates them. // the linker manipulates them.
func typeSymbolMangle(name string) string { func typeSymbolMangle(name string) string {
if !strings.HasPrefix(name, "type.") { if !strings.HasPrefix(name, "type:") {
return name return name
} }
if strings.HasPrefix(name, "type.runtime.") { if strings.HasPrefix(name, "type:runtime.") {
return name return name
} }
if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529 if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
return name return name
} }
hash := notsha256.Sum256([]byte(name)) hash := notsha256.Sum256([]byte(name))
prefix := "type." prefix := "type:"
if name[5] == '.' { if name[5] == '.' {
prefix = "type.." prefix = "type:."
} }
return prefix + base64.StdEncoding.EncodeToString(hash[:6]) return prefix + base64.StdEncoding.EncodeToString(hash[:6])
} }
@ -2319,11 +2319,11 @@ func ldshlibsyms(ctxt *Link, shlib string) {
continue continue
} }
// Symbols whose names start with "type." are compiler // Symbols whose names start with "type:" are compiler generated,
// generated, so make functions with that prefix internal. // so make functions with that prefix internal.
ver := 0 ver := 0
symname := elfsym.Name // (unmangled) symbol name symname := elfsym.Name // (unmangled) symbol name
if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type.") { if elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC && strings.HasPrefix(elfsym.Name, "type:") {
ver = abiInternalVer ver = abiInternalVer
} else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC { } else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
// Demangle the ABI name. Keep in sync with symtab.go:mangleABIName. // Demangle the ABI name. Keep in sync with symtab.go:mangleABIName.
@ -2357,7 +2357,7 @@ func ldshlibsyms(ctxt *Link, shlib string) {
// The decodetype_* functions in decodetype.go need access to // The decodetype_* functions in decodetype.go need access to
// the type data. // the type data.
sname := l.SymName(s) sname := l.SymName(s)
if strings.HasPrefix(sname, "type.") && !strings.HasPrefix(sname, "type..") { if strings.HasPrefix(sname, "type:") && !strings.HasPrefix(sname, "type:.") {
su.SetData(readelfsymboldata(ctxt, f, &elfsym)) su.SetData(readelfsymboldata(ctxt, f, &elfsym))
} }
} }

View File

@ -1020,16 +1020,16 @@ func machoShouldExport(ctxt *Link, ldr *loader.Loader, s loader.Sym) bool {
return true return true
} }
name := ldr.SymName(s) name := ldr.SymName(s)
if strings.HasPrefix(name, "go.itab.") { if strings.HasPrefix(name, "go:itab.") {
return true return true
} }
if strings.HasPrefix(name, "type.") && !strings.HasPrefix(name, "type..") { if strings.HasPrefix(name, "type:") && !strings.HasPrefix(name, "type:.") {
// reduce runtime typemap pressure, but do not // reduce runtime typemap pressure, but do not
// export alg functions (type..*), as these // export alg functions (type:.*), as these
// appear in pclntable. // appear in pclntable.
return true return true
} }
if strings.HasPrefix(name, "go.link.pkghash") { if strings.HasPrefix(name, "go:link.pkghash") {
return true return true
} }
return ldr.SymType(s) >= sym.SFirstWritable // only writable sections return ldr.SymType(s) >= sym.SFirstWritable // only writable sections

View File

@ -222,7 +222,7 @@ func (state *pclntab) generatePCHeader(ctxt *Link) {
// Write header. // Write header.
// Keep in sync with runtime/symtab.go:pcHeader and package debug/gosym. // Keep in sync with runtime/symtab.go:pcHeader and package debug/gosym.
header.SetUint32(ctxt.Arch, 0, 0xfffffff0) header.SetUint32(ctxt.Arch, 0, 0xfffffff1)
header.SetUint8(ctxt.Arch, 6, uint8(ctxt.Arch.MinLC)) header.SetUint8(ctxt.Arch, 6, uint8(ctxt.Arch.MinLC))
header.SetUint8(ctxt.Arch, 7, uint8(ctxt.Arch.PtrSize)) header.SetUint8(ctxt.Arch, 7, uint8(ctxt.Arch.PtrSize))
off := header.SetUint(ctxt.Arch, 8, uint64(state.nfunc)) off := header.SetUint(ctxt.Arch, 8, uint64(state.nfunc))
@ -627,7 +627,7 @@ func writePCToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, sta
func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) { func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) {
ldr := ctxt.loader ldr := ctxt.loader
deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer) deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer)
gofunc := ldr.Lookup("go.func.*", 0) gofunc := ldr.Lookup("go:func.*", 0)
gofuncBase := ldr.SymValue(gofunc) gofuncBase := ldr.SymValue(gofunc)
textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0)) textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0))
funcdata := []loader.Sym{} funcdata := []loader.Sym{}
@ -716,7 +716,7 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
} }
} }
// Write funcdata refs as offsets from go.func.* and go.funcrel.*. // Write funcdata refs as offsets from go:func.* and go:funcrel.*.
funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata) funcdata = funcData(ldr, s, fi, inlSyms[s], funcdata)
// Missing funcdata will be ^0. See runtime/symtab.go:funcdata. // Missing funcdata will be ^0. See runtime/symtab.go:funcdata.
off = int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4) off = int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4)
@ -729,7 +729,7 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
} }
if outer := ldr.OuterSym(fdsym); outer != gofunc { if outer := ldr.OuterSym(fdsym); outer != gofunc {
panic(fmt.Sprintf("bad carrier sym for symbol %s (funcdata %s#%d), want go.func.* got %s", ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer))) panic(fmt.Sprintf("bad carrier sym for symbol %s (funcdata %s#%d), want go:func.* got %s", ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer)))
} }
sb.SetUint32(ctxt.Arch, dataoff, uint32(ldr.SymValue(fdsym)-gofuncBase)) sb.SetUint32(ctxt.Arch, dataoff, uint32(ldr.SymValue(fdsym)-gofuncBase))
} }

View File

@ -723,7 +723,27 @@ func (f *peFile) writeSymbols(ctxt *Link) {
// Only windows/386 requires underscore prefix on external symbols. // Only windows/386 requires underscore prefix on external symbols.
if ctxt.Is386() && ctxt.IsExternal() && if ctxt.Is386() && ctxt.IsExternal() &&
(t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s)) { (t == sym.SHOSTOBJ || t == sym.SUNDEFEXT || ldr.AttrCgoExport(s) ||
// TODO(cuonglm): remove this hack
//
// 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)
//
// CL 317917 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.
name == "go:buildid" || name == "type:*") {
name = "_" + name name = "_" + name
} }

View File

@ -472,7 +472,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
var symtype, symtyperel loader.Sym var symtype, symtyperel loader.Sym
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
s = ldr.CreateSymForUpdate("type.*", 0) s = ldr.CreateSymForUpdate("type:*", 0)
s.SetType(sym.STYPE) s.SetType(sym.STYPE)
s.SetSize(0) s.SetSize(0)
s.SetAlign(int32(ctxt.Arch.PtrSize)) s.SetAlign(int32(ctxt.Arch.PtrSize))
@ -484,7 +484,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
s.SetAlign(int32(ctxt.Arch.PtrSize)) s.SetAlign(int32(ctxt.Arch.PtrSize))
symtyperel = s.Sym() symtyperel = s.Sym()
} else { } else {
s = ldr.CreateSymForUpdate("type.*", 0) s = ldr.CreateSymForUpdate("type:*", 0)
s.SetType(sym.STYPE) s.SetType(sym.STYPE)
s.SetSize(0) s.SetSize(0)
s.SetAlign(int32(ctxt.Arch.PtrSize)) s.SetAlign(int32(ctxt.Arch.PtrSize))
@ -505,14 +505,14 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
return s.Sym() return s.Sym()
} }
var ( var (
symgostring = groupSym("go.string.*", sym.SGOSTRING) symgostring = groupSym("go:string.*", sym.SGOSTRING)
symgofunc = groupSym("go.func.*", sym.SGOFUNC) symgofunc = groupSym("go:func.*", sym.SGOFUNC)
symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS)
) )
symgofuncrel := symgofunc symgofuncrel := symgofunc
if ctxt.UseRelro() { if ctxt.UseRelro() {
symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) symgofuncrel = groupSym("go:funcrel.*", sym.SGOFUNCRELRO)
} }
symt := ldr.CreateSymForUpdate("runtime.symtab", 0) symt := ldr.CreateSymForUpdate("runtime.symtab", 0)
@ -538,13 +538,13 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
name := ldr.SymName(s) name := ldr.SymName(s)
switch { switch {
case strings.HasPrefix(name, "go.string."): case strings.HasPrefix(name, "go:string."):
symGroupType[s] = sym.SGOSTRING symGroupType[s] = sym.SGOSTRING
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetCarrierSym(s, symgostring) ldr.SetCarrierSym(s, symgostring)
case strings.HasPrefix(name, "runtime.gcbits."), case strings.HasPrefix(name, "runtime.gcbits."),
strings.HasPrefix(name, "type..gcprog."): strings.HasPrefix(name, "type:.gcprog."):
symGroupType[s] = sym.SGCBITS symGroupType[s] = sym.SGCBITS
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetCarrierSym(s, symgcbits) ldr.SetCarrierSym(s, symgcbits)
@ -582,10 +582,10 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1) liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
} }
// Note: Check for "type." prefix after checking for .arginfo1 suffix. // Note: Check for "type:" prefix after checking for .arginfo1 suffix.
// That way symbols like "type..eq.[2]interface {}.arginfo1" that belong // That way symbols like "type:.eq.[2]interface {}.arginfo1" that belong
// in go.func.* end up there. // in go:func.* end up there.
case strings.HasPrefix(name, "type."): case strings.HasPrefix(name, "type:"):
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
ldr.SetAttrNotInSymbolTable(s, true) ldr.SetAttrNotInSymbolTable(s, true)
} }
@ -604,19 +604,19 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
} }
if ctxt.BuildMode == BuildModeShared { if ctxt.BuildMode == BuildModeShared {
abihashgostr := ldr.CreateSymForUpdate("go.link.abihash."+filepath.Base(*flagOutfile), 0) abihashgostr := ldr.CreateSymForUpdate("go:link.abihash."+filepath.Base(*flagOutfile), 0)
abihashgostr.SetType(sym.SRODATA) abihashgostr.SetType(sym.SRODATA)
hashsym := ldr.LookupOrCreateSym("go.link.abihashbytes", 0) hashsym := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
abihashgostr.AddAddr(ctxt.Arch, hashsym) abihashgostr.AddAddr(ctxt.Arch, hashsym)
abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym))) abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym)))
} }
if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() { if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
for _, l := range ctxt.Library { for _, l := range ctxt.Library {
s := ldr.CreateSymForUpdate("go.link.pkghashbytes."+l.Pkg, 0) s := ldr.CreateSymForUpdate("go:link.pkghashbytes."+l.Pkg, 0)
s.SetType(sym.SRODATA) s.SetType(sym.SRODATA)
s.SetSize(int64(len(l.Fingerprint))) s.SetSize(int64(len(l.Fingerprint)))
s.SetData(l.Fingerprint[:]) s.SetData(l.Fingerprint[:])
str := ldr.CreateSymForUpdate("go.link.pkghash."+l.Pkg, 0) str := ldr.CreateSymForUpdate("go:link.pkghash."+l.Pkg, 0)
str.SetType(sym.SRODATA) str.SetType(sym.SRODATA)
str.AddAddr(ctxt.Arch, s.Sym()) str.AddAddr(ctxt.Arch, s.Sym())
str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint))) str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint)))
@ -678,7 +678,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go.func.*", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go:func.*", 0))
if ctxt.IsAIX() && ctxt.IsExternal() { if ctxt.IsAIX() && ctxt.IsExternal() {
// Add R_XCOFFREF relocation to prevent ld's garbage collection of // Add R_XCOFFREF relocation to prevent ld's garbage collection of
@ -695,8 +695,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
// important that the offsets we computed stay unchanged by the external // important that the offsets we computed stay unchanged by the external
// linker, i.e. all symbols in Textp should not be removed. // linker, i.e. all symbols in Textp should not be removed.
// Most of them are actually referenced (our deadcode pass ensures that), // Most of them are actually referenced (our deadcode pass ensures that),
// except go.buildid which is generated late and not used by the program. // except go:buildid which is generated late and not used by the program.
addRef("go.buildid") addRef("go:buildid")
} }
// text section information // text section information
@ -717,10 +717,10 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
moduledata.AddUint(ctxt.Arch, nitablinks) moduledata.AddUint(ctxt.Arch, nitablinks)
moduledata.AddUint(ctxt.Arch, nitablinks) moduledata.AddUint(ctxt.Arch, nitablinks)
// The ptab slice // The ptab slice
if ptab := ldr.Lookup("go.plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) { if ptab := ldr.Lookup("go:plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) {
ldr.SetAttrLocal(ptab, true) ldr.SetAttrLocal(ptab, true)
if ldr.SymType(ptab) != sym.SRODATA { if ldr.SymType(ptab) != sym.SRODATA {
panic(fmt.Sprintf("go.plugin.tabs is %v, not SRODATA", ldr.SymType(ptab))) panic(fmt.Sprintf("go:plugin.tabs is %v, not SRODATA", ldr.SymType(ptab)))
} }
nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff) nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff)
moduledata.AddAddr(ctxt.Arch, ptab) moduledata.AddAddr(ctxt.Arch, ptab)
@ -732,19 +732,19 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
moduledata.AddUint(ctxt.Arch, 0) moduledata.AddUint(ctxt.Arch, 0)
} }
if ctxt.BuildMode == BuildModePlugin { if ctxt.BuildMode == BuildModePlugin {
addgostring(ctxt, ldr, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) addgostring(ctxt, ldr, moduledata, "go:link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
pkghashes := ldr.CreateSymForUpdate("go.link.pkghashes", 0) pkghashes := ldr.CreateSymForUpdate("go:link.pkghashes", 0)
pkghashes.SetLocal(true) pkghashes.SetLocal(true)
pkghashes.SetType(sym.SRODATA) pkghashes.SetType(sym.SRODATA)
for i, l := range ctxt.Library { for i, l := range ctxt.Library {
// pkghashes[i].name // pkghashes[i].name
addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkgname.%d", i), l.Pkg)
// pkghashes[i].linktimehash // pkghashes[i].linktimehash
addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), string(l.Fingerprint[:])) addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go:link.pkglinkhash.%d", i), string(l.Fingerprint[:]))
// pkghashes[i].runtimehash // pkghashes[i].runtimehash
hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0) hash := ldr.Lookup("go:link.pkghash."+l.Pkg, 0)
pkghashes.AddAddr(ctxt.Arch, hash) pkghashes.AddAddr(ctxt.Arch, hash)
} }
moduledata.AddAddr(ctxt.Arch, pkghashes.Sym()) moduledata.AddAddr(ctxt.Arch, pkghashes.Sym())
@ -765,22 +765,22 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
// it something slightly more comprehensible. // it something slightly more comprehensible.
thismodulename = "the executable" thismodulename = "the executable"
} }
addgostring(ctxt, ldr, moduledata, "go.link.thismodulename", thismodulename) addgostring(ctxt, ldr, moduledata, "go:link.thismodulename", thismodulename)
modulehashes := ldr.CreateSymForUpdate("go.link.abihashes", 0) modulehashes := ldr.CreateSymForUpdate("go:link.abihashes", 0)
modulehashes.SetLocal(true) modulehashes.SetLocal(true)
modulehashes.SetType(sym.SRODATA) modulehashes.SetType(sym.SRODATA)
for i, shlib := range ctxt.Shlibs { for i, shlib := range ctxt.Shlibs {
// modulehashes[i].modulename // modulehashes[i].modulename
modulename := filepath.Base(shlib.Path) modulename := filepath.Base(shlib.Path)
addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.libname.%d", i), modulename)
// modulehashes[i].linktimehash // modulehashes[i].linktimehash
addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go:link.linkhash.%d", i), string(shlib.Hash))
// modulehashes[i].runtimehash // modulehashes[i].runtimehash
abihash := ldr.LookupOrCreateSym("go.link.abihash."+modulename, 0) abihash := ldr.LookupOrCreateSym("go:link.abihash."+modulename, 0)
ldr.SetAttrReachable(abihash, true) ldr.SetAttrReachable(abihash, true)
modulehashes.AddAddr(ctxt.Arch, abihash) modulehashes.AddAddr(ctxt.Arch, abihash)
} }
@ -807,7 +807,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
// When linking an object that does not contain the runtime we are // When linking an object that does not contain the runtime we are
// creating the moduledata from scratch and it does not have a // creating the moduledata from scratch and it does not have a
// compiler-provided size, so read it from the type data. // compiler-provided size, so read it from the type data.
moduledatatype := ldr.Lookup("type.runtime.moduledata", 0) moduledatatype := ldr.Lookup("type:runtime.moduledata", 0)
moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype))) moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
moduledata.Grow(moduledata.Size()) moduledata.Grow(moduledata.Size())
@ -873,7 +873,7 @@ func mangleABIName(ctxt *Link, ldr *loader.Loader, x loader.Sym, name string) st
// except symbols that are exported to C. Type symbols are always // except symbols that are exported to C. Type symbols are always
// ABIInternal so they are not mangled. // ABIInternal so they are not mangled.
if ctxt.IsShared() { if ctxt.IsShared() {
if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type.") { if ldr.SymType(x) == sym.STEXT && ldr.SymVersion(x) == sym.SymVerABIInternal && !ldr.AttrCgoExport(x) && !strings.HasPrefix(name, "type:") {
name = fmt.Sprintf("%s.abiinternal", name) name = fmt.Sprintf("%s.abiinternal", name)
} }
} }

View File

@ -598,16 +598,16 @@ func xcoffUpdateOuterSize(ctxt *Link, size int64, stype sym.SymKind) {
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
// runtime.types size must be removed, as it's a real symbol. // runtime.types size must be removed, as it's a real symbol.
tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0)) tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
outerSymSize["type.*"] = size - tsize outerSymSize["type:*"] = size - tsize
} }
case sym.SGOSTRING: case sym.SGOSTRING:
outerSymSize["go.string.*"] = size outerSymSize["go:string.*"] = size
case sym.SGOFUNC: case sym.SGOFUNC:
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
outerSymSize["go.func.*"] = size outerSymSize["go:func.*"] = size
} }
case sym.SGOFUNCRELRO: case sym.SGOFUNCRELRO:
outerSymSize["go.funcrel.*"] = size outerSymSize["go:funcrel.*"] = size
case sym.SGCBITS: case sym.SGCBITS:
outerSymSize["runtime.gcbits.*"] = size outerSymSize["runtime.gcbits.*"] = size
case sym.SPCLNTAB: case sym.SPCLNTAB:
@ -893,7 +893,7 @@ func putaixsym(ctxt *Link, x loader.Sym, t SymbolType) {
syms = xfile.writeSymbolFunc(ctxt, x) syms = xfile.writeSymbolFunc(ctxt, x)
} else { } else {
// Only runtime.text and runtime.etext come through this way // Only runtime.text and runtime.etext come through this way
if name != "runtime.text" && name != "runtime.etext" && name != "go.buildid" { if name != "runtime.text" && name != "runtime.etext" && name != "go:buildid" {
Exitf("putaixsym: unknown text symbol %s", name) Exitf("putaixsym: unknown text symbol %s", name)
} }
s := &XcoffSymEnt64{ s := &XcoffSymEnt64{

View File

@ -722,9 +722,9 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
// here is that we get different line numbers on formal // here is that we get different line numbers on formal
// params; I am guessing that the pos is being inherited // params; I am guessing that the pos is being inherited
// from the spot where the wrapper is needed. // from the spot where the wrapper is needed.
allowed := strings.HasPrefix(name, "go.info.go.interface") || allowed := strings.HasPrefix(name, "go:info.go.interface") ||
strings.HasPrefix(name, "go.info.go.builtin") || strings.HasPrefix(name, "go:info.go.builtin") ||
strings.HasPrefix(name, "go.debuglines") strings.HasPrefix(name, "go:debuglines")
if !allowed { if !allowed {
l.strictDupMsgs++ l.strictDupMsgs++
} }
@ -1704,7 +1704,7 @@ func (l *Loader) OuterSym(i Sym) Sym {
// SubSym gets the subsymbol for host object loaded symbols. // SubSym gets the subsymbol for host object loaded symbols.
func (l *Loader) SubSym(i Sym) Sym { func (l *Loader) SubSym(i Sym) Sym {
// NB: note -- no check for l.isExternal(), since I am pretty sure // NB: note -- no check for l.isExternal(), since I am pretty sure
// that later phases in the linker set subsym for "type." syms // that later phases in the linker set subsym for "type:" syms
return l.sub[i] return l.sub[i]
} }
@ -1717,7 +1717,7 @@ func (l *Loader) SubSym(i Sym) Sym {
// emits named string symbols (type SGOSTRING) when compiling a // emits named string symbols (type SGOSTRING) when compiling a
// package; after being deduplicated, these symbols are collected into // package; after being deduplicated, these symbols are collected into
// a single unit by assigning them a new carrier symbol named // a single unit by assigning them a new carrier symbol named
// "go.string.*" (which appears in the final symbol table for the // "go:string.*" (which appears in the final symbol table for the
// output load module). // output load module).
func (l *Loader) SetCarrierSym(s Sym, c Sym) { func (l *Loader) SetCarrierSym(s Sym, c Sym) {
if c == 0 { if c == 0 {
@ -2133,7 +2133,7 @@ func (st *loadState) preloadSyms(r *oReader, kind int) {
l.SetAttrUsedInIface(gi, true) l.SetAttrUsedInIface(gi, true)
} }
if strings.HasPrefix(name, "runtime.") || if strings.HasPrefix(name, "runtime.") ||
(loadingRuntimePkg && strings.HasPrefix(name, "type.")) { (loadingRuntimePkg && strings.HasPrefix(name, "type:")) {
if bi := goobj.BuiltinIdx(name, int(osym.ABI())); bi != -1 { if bi := goobj.BuiltinIdx(name, int(osym.ABI())); bi != -1 {
// This is a definition of a builtin symbol. Record where it is. // This is a definition of a builtin symbol. Record where it is.
l.builtinSyms[bi] = gi l.builtinSyms[bi] = gi

View File

@ -39,9 +39,9 @@ func TestAddMaterializedSymbol(t *testing.T) {
or := &dummyOreader or := &dummyOreader
// Create some syms from a dummy object file symbol to get things going. // Create some syms from a dummy object file symbol to get things going.
ts1 := addDummyObjSym(t, ldr, or, "type.uint8") ts1 := addDummyObjSym(t, ldr, or, "type:uint8")
ts2 := addDummyObjSym(t, ldr, or, "mumble") ts2 := addDummyObjSym(t, ldr, or, "mumble")
ts3 := addDummyObjSym(t, ldr, or, "type.string") ts3 := addDummyObjSym(t, ldr, or, "type:string")
// Create some external symbols. // Create some external symbols.
es1 := ldr.LookupOrCreateSym("extnew1", 0) es1 := ldr.LookupOrCreateSym("extnew1", 0)
@ -52,7 +52,7 @@ func TestAddMaterializedSymbol(t *testing.T) {
if es1x != es1 { if es1x != es1 {
t.Fatalf("LookupOrCreateSym lookup: expected %d got %d for second lookup", es1, es1x) t.Fatalf("LookupOrCreateSym lookup: expected %d got %d for second lookup", es1, es1x)
} }
es2 := ldr.LookupOrCreateSym("go.info.type.uint8", 0) es2 := ldr.LookupOrCreateSym("go:info.type.uint8", 0)
if es2 == 0 { if es2 == 0 {
t.Fatalf("LookupOrCreateSym failed for go.info.type.uint8") t.Fatalf("LookupOrCreateSym failed for go.info.type.uint8")
} }
@ -252,7 +252,7 @@ func TestAddDataMethods(t *testing.T) {
or := &dummyOreader or := &dummyOreader
// Populate loader with some symbols. // Populate loader with some symbols.
addDummyObjSym(t, ldr, or, "type.uint8") addDummyObjSym(t, ldr, or, "type:uint8")
ldr.LookupOrCreateSym("hello", 0) ldr.LookupOrCreateSym("hello", 0)
arch := sys.ArchAMD64 arch := sys.ArchAMD64
@ -371,7 +371,7 @@ func TestOuterSub(t *testing.T) {
or := &dummyOreader or := &dummyOreader
// Populate loader with some symbols. // Populate loader with some symbols.
addDummyObjSym(t, ldr, or, "type.uint8") addDummyObjSym(t, ldr, or, "type:uint8")
es1 := ldr.LookupOrCreateSym("outer", 0) es1 := ldr.LookupOrCreateSym("outer", 0)
ldr.MakeSymbolUpdater(es1).SetSize(101) ldr.MakeSymbolUpdater(es1).SetSize(101)
es2 := ldr.LookupOrCreateSym("sub1", 0) es2 := ldr.LookupOrCreateSym("sub1", 0)

View File

@ -156,7 +156,7 @@ func asmb2(ctxt *ld.Link, ldr *loader.Loader) {
fns := make([]*wasmFunc, len(ctxt.Textp)) fns := make([]*wasmFunc, len(ctxt.Textp))
for i, fn := range ctxt.Textp { for i, fn := range ctxt.Textp {
wfn := new(bytes.Buffer) wfn := new(bytes.Buffer)
if ldr.SymName(fn) == "go.buildid" { if ldr.SymName(fn) == "go:buildid" {
writeUleb128(wfn, 0) // number of sets of locals writeUleb128(wfn, 0) // number of sets of locals
writeI32Const(wfn, 0) writeI32Const(wfn, 0)
wfn.WriteByte(0x0b) // end wfn.WriteByte(0x0b) // end
@ -248,7 +248,7 @@ func writeSecSize(ctxt *ld.Link, sizeOffset int64) {
func writeBuildID(ctxt *ld.Link, buildid []byte) { func writeBuildID(ctxt *ld.Link, buildid []byte) {
sizeOffset := writeSecHeader(ctxt, sectionCustom) sizeOffset := writeSecHeader(ctxt, sectionCustom)
writeName(ctxt.Out, "go.buildid") writeName(ctxt.Out, "go:buildid")
ctxt.Out.Write(buildid) ctxt.Out.Write(buildid)
writeSecSize(ctxt, sizeOffset) writeSecSize(ctxt, sizeOffset)
} }

View File

@ -36,8 +36,8 @@ func main() {}
`, `,
bad: []string{ bad: []string{
"tls.(*Conn)", "tls.(*Conn)",
"type.crypto/tls.clientHandshakeState", "type:crypto/tls.clientHandshakeState",
"type.crypto/tls.serverHandshakeState", "type:crypto/tls.serverHandshakeState",
}, },
}, },
{ {

View File

@ -24,6 +24,7 @@ const (
ver12 ver12
ver116 ver116
ver118 ver118
ver120
) )
// A LineTable is a data structure mapping program counters to line numbers. // A LineTable is a data structure mapping program counters to line numbers.
@ -173,6 +174,7 @@ const (
go12magic = 0xfffffffb go12magic = 0xfffffffb
go116magic = 0xfffffffa go116magic = 0xfffffffa
go118magic = 0xfffffff0 go118magic = 0xfffffff0
go120magic = 0xfffffff1
) )
// uintptr returns the pointer-sized value encoded at b. // uintptr returns the pointer-sized value encoded at b.
@ -229,6 +231,10 @@ func (t *LineTable) parsePclnTab() {
t.binary, possibleVersion = binary.LittleEndian, ver118 t.binary, possibleVersion = binary.LittleEndian, ver118
case beMagic == go118magic: case beMagic == go118magic:
t.binary, possibleVersion = binary.BigEndian, ver118 t.binary, possibleVersion = binary.BigEndian, ver118
case leMagic == go120magic:
t.binary, possibleVersion = binary.LittleEndian, ver120
case beMagic == go120magic:
t.binary, possibleVersion = binary.BigEndian, ver120
default: default:
return return
} }
@ -246,7 +252,7 @@ func (t *LineTable) parsePclnTab() {
} }
switch possibleVersion { switch possibleVersion {
case ver118: case ver118, ver120:
t.nfunctab = uint32(offset(0)) t.nfunctab = uint32(offset(0))
t.nfiletab = uint32(offset(1)) t.nfiletab = uint32(offset(1))
t.textStart = t.PC // use the start PC instead of reading from the table, which may be unrelocated t.textStart = t.PC // use the start PC instead of reading from the table, which may be unrelocated
@ -527,7 +533,7 @@ func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum,
fileStartPC := filePC fileStartPC := filePC
for t.step(&fp, &filePC, &fileVal, filePC == entry) { for t.step(&fp, &filePC, &fileVal, filePC == entry) {
fileIndex := fileVal fileIndex := fileVal
if t.version == ver116 || t.version == ver118 { if t.version == ver116 || t.version == ver118 || t.version == ver120 {
fileIndex = int32(t.binary.Uint32(cutab[fileVal*4:])) fileIndex = int32(t.binary.Uint32(cutab[fileVal*4:]))
} }
if fileIndex == filenum && fileStartPC < filePC { if fileIndex == filenum && fileStartPC < filePC {
@ -626,7 +632,7 @@ func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) {
entry := f.entryPC() entry := f.entryPC()
filetab := f.pcfile() filetab := f.pcfile()
linetab := f.pcln() linetab := f.pcln()
if t.version == ver116 || t.version == ver118 { if t.version == ver116 || t.version == ver118 || t.version == ver120 {
if f.cuOffset() == ^uint32(0) { if f.cuOffset() == ^uint32(0) {
// skip functions without compilation unit (not real function, or linker generated) // skip functions without compilation unit (not real function, or linker generated)
continue continue

View File

@ -27,6 +27,8 @@ type Sym struct {
GoType uint64 GoType uint64
// If this symbol is a function symbol, the corresponding Func // If this symbol is a function symbol, the corresponding Func
Func *Func Func *Func
goVersion version
} }
// Static reports whether this symbol is static (not visible outside its file). // Static reports whether this symbol is static (not visible outside its file).
@ -55,9 +57,16 @@ func (s *Sym) nameWithoutInst() string {
func (s *Sym) PackageName() string { func (s *Sym) PackageName() string {
name := s.nameWithoutInst() name := s.nameWithoutInst()
// A prefix of "type." and "go." is a compiler-generated symbol that doesn't belong to any package. // Since go1.20, a prefix of "type:" and "go:" is a compiler-generated symbol,
// See variable reservedimports in cmd/compile/internal/gc/subr.go // they do not belong to any package.
if strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.") { //
// See cmd/compile/internal/base/link.go:ReservedImports variable.
if s.goVersion >= ver120 && (strings.HasPrefix(name, "go:") || strings.HasPrefix(name, "type:")) {
return ""
}
// For go1.18 and below, the prefix are "type." and "go." instead.
if s.goVersion <= ver118 && (strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.")) {
return "" return ""
} }
@ -350,6 +359,7 @@ func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
ts.Type = s.typ ts.Type = s.typ
ts.Value = s.value ts.Value = s.value
ts.GoType = s.gotype ts.GoType = s.gotype
ts.goVersion = pcln.version
switch s.typ { switch s.typ {
default: default:
// rewrite name to use . instead of · (c2 b7) // rewrite name to use . instead of · (c2 b7)

View File

@ -62,16 +62,26 @@ func TestRemotePackage(t *testing.T) {
} }
func TestIssue29551(t *testing.T) { func TestIssue29551(t *testing.T) {
symNames := []string{ tests := []struct {
"type..eq.[9]debug/elf.intName", sym Sym
"type..hash.debug/elf.ProgHeader", pkgName string
"type..eq.runtime._panic", }{
"type..hash.struct { runtime.gList; runtime.n int32 }", {Sym{goVersion: ver120, Name: "type:.eq.[9]debug/elf.intName"}, ""},
"go.(*struct { sync.Mutex; math/big.table [64]math/big", {Sym{goVersion: ver120, Name: "type:.hash.debug/elf.ProgHeader"}, ""},
{Sym{goVersion: ver120, Name: "type:.eq.runtime._panic"}, ""},
{Sym{goVersion: ver120, Name: "type:.hash.struct { runtime.gList; runtime.n int32 }"}, ""},
{Sym{goVersion: ver120, Name: "go:(*struct { sync.Mutex; math/big.table [64]math/big"}, ""},
{Sym{goVersion: ver120, Name: "go.uber.org/zap/buffer.(*Buffer).AppendString"}, "go.uber.org/zap/buffer"},
{Sym{goVersion: ver118, Name: "type..eq.[9]debug/elf.intName"}, ""},
{Sym{goVersion: ver118, Name: "type..hash.debug/elf.ProgHeader"}, ""},
{Sym{goVersion: ver118, Name: "type..eq.runtime._panic"}, ""},
{Sym{goVersion: ver118, Name: "type..hash.struct { runtime.gList; runtime.n int32 }"}, ""},
{Sym{goVersion: ver118, Name: "go.(*struct { sync.Mutex; math/big.table [64]math/big"}, ""},
// unfortunate
{Sym{goVersion: ver118, Name: "go.uber.org/zap/buffer.(*Buffer).AppendString"}, ""},
} }
for _, symName := range symNames { for _, tc := range tests {
s := Sym{Name: symName} assertString(t, fmt.Sprintf("package of %q", tc.sym.Name), tc.sym.PackageName(), tc.pkgName)
assertString(t, fmt.Sprintf("package of %q", s.Name), s.PackageName(), "")
} }
} }

View File

@ -393,7 +393,7 @@ const (
// pcHeader holds data used by the pclntab lookups. // pcHeader holds data used by the pclntab lookups.
type pcHeader struct { type pcHeader struct {
magic uint32 // 0xFFFFFFF0 magic uint32 // 0xFFFFFFF1
pad1, pad2 uint8 // 0,0 pad1, pad2 uint8 // 0,0
minLC uint8 // min instruction size minLC uint8 // min instruction size
ptrSize uint8 // size of a ptr in bytes ptrSize uint8 // size of a ptr in bytes
@ -599,7 +599,7 @@ const debugPcln = false
func moduledataverify1(datap *moduledata) { func moduledataverify1(datap *moduledata) {
// Check that the pclntab's format is valid. // Check that the pclntab's format is valid.
hdr := datap.pcHeader hdr := datap.pcHeader
if hdr.magic != 0xfffffff0 || hdr.pad1 != 0 || hdr.pad2 != 0 || if hdr.magic != 0xfffffff1 || hdr.pad1 != 0 || hdr.pad2 != 0 ||
hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize || hdr.textStart != datap.text { hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize || hdr.textStart != datap.text {
println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2, println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2,
"minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pcHeader.textStart=", hex(hdr.textStart), "minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pcHeader.textStart=", hex(hdr.textStart),

View File

@ -15,7 +15,7 @@ func CountRunes(s string) int { // Issue #24923
} }
func ToByteSlice() []byte { // Issue #24698 func ToByteSlice() []byte { // Issue #24698
// amd64:`LEAQ\ttype\.\[3\]uint8` // amd64:`LEAQ\ttype:\[3\]uint8`
// amd64:`CALL\truntime\.newobject` // amd64:`CALL\truntime\.newobject`
// amd64:-`.*runtime.stringtoslicebyte` // amd64:-`.*runtime.stringtoslicebyte`
return []byte("foo") return []byte("foo")

View File

@ -22,14 +22,14 @@
// The type names for these types are as follows. Because we truncate // The type names for these types are as follows. Because we truncate
// the name at depth 250, the last few names are all identical: // the name at depth 250, the last few names are all identical:
// //
// type.[]*"".pwn // type:[]*"".pwn
// type.[][]*"".pwn // type:[][]*"".pwn
// ... // ...
// type.[][]...[][]*pwn - 249 total "[]" // type:[][]...[][]*pwn - 249 total "[]"
// type.[][]...[][][]*<...> - 250 total "[]" // type:[][]...[][][]*<...> - 250 total "[]"
// type.[][]...[][][][]<...> - 251 total "[]" // type:[][]...[][][][]<...> - 251 total "[]"
// type.[][]...[][][][]<...> - 252 total "[]" (but only 251 "[]" in the name) // type:[][]...[][][][]<...> - 252 total "[]" (but only 251 "[]" in the name)
// type.[][]...[][][][]<...> - 253 total "[]" (but only 251 "[]" in the name) // type:[][]...[][][][]<...> - 253 total "[]" (but only 251 "[]" in the name)
// //
// Because the names of the last 3 types are all identical, the // Because the names of the last 3 types are all identical, the
// compiler will generate only a single runtime.slicetype data // compiler will generate only a single runtime.slicetype data
@ -37,7 +37,7 @@
// generates just the 251-entry one. There aren't any // generates just the 251-entry one. There aren't any
// runtime.slicetypes generated for the final two types. // runtime.slicetypes generated for the final two types.
// //
// The compiler passes type.[]...[]<...> (251 total "[]") to // The compiler passes type:[]...[]<...> (251 total "[]") to
// fmt.Sprintf (instead of the correct 253 one). But the data // fmt.Sprintf (instead of the correct 253 one). But the data
// structure at runtime actually has 253 nesting levels. So we end up // structure at runtime actually has 253 nesting levels. So we end up
// calling String on something that is of type [][]*pwn instead of // calling String on something that is of type [][]*pwn instead of