return
}
for _, sym := range symbols {
- if sym.Name == "go.link.abihashbytes" {
+ if sym.Name == "go:link.abihashbytes" {
hashbytes = sym
}
}
if hashbytes.Name == "" {
- t.Errorf("no symbol called go.link.abihashbytes")
+ t.Errorf("no symbol called go:link.abihashbytes")
return
}
if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL {
"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.
// 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
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() {
// 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")
// 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", "")
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)
}
b.WriteString(".")
b.WriteString(msym.Name)
b.WriteString(suffix)
-
return rpkg.LookupBytes(b.Bytes())
}
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")
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)
}
// 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
}
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)
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)
}
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)
}
// 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 == "" {
// 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 {
// 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.
//
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)
}
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))
}
}
const (
- stringSymPrefix = "go.string."
+ stringSymPrefix = "go:string."
stringSymPattern = ".gostring.%d.%s"
)
)
// 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
// entries that contain constants.
-const ConstInfoPrefix = "go.constinfo."
+const ConstInfoPrefix = "go:constinfo."
// CUInfoPrefix is the prefix for symbols containing information to
// 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"
// info entry for a function
{"runtime.morestack", 0},
{"runtime.morestackc", 0},
{"runtime.morestack_noctxt", 0},
- {"type.int8", 0},
- {"type.*int8", 0},
- {"type.uint8", 0},
- {"type.*uint8", 0},
- {"type.int16", 0},
- {"type.*int16", 0},
- {"type.uint16", 0},
- {"type.*uint16", 0},
- {"type.int32", 0},
- {"type.*int32", 0},
- {"type.uint32", 0},
- {"type.*uint32", 0},
- {"type.int64", 0},
- {"type.*int64", 0},
- {"type.uint64", 0},
- {"type.*uint64", 0},
- {"type.float32", 0},
- {"type.*float32", 0},
- {"type.float64", 0},
- {"type.*float64", 0},
- {"type.complex64", 0},
- {"type.*complex64", 0},
- {"type.complex128", 0},
- {"type.*complex128", 0},
- {"type.unsafe.Pointer", 0},
- {"type.*unsafe.Pointer", 0},
- {"type.uintptr", 0},
- {"type.*uintptr", 0},
- {"type.bool", 0},
- {"type.*bool", 0},
- {"type.string", 0},
- {"type.*string", 0},
- {"type.error", 0},
- {"type.*error", 0},
- {"type.func(error) string", 0},
- {"type.*func(error) string", 0},
+ {"type:int8", 0},
+ {"type:*int8", 0},
+ {"type:uint8", 0},
+ {"type:*uint8", 0},
+ {"type:int16", 0},
+ {"type:*int16", 0},
+ {"type:uint16", 0},
+ {"type:*uint16", 0},
+ {"type:int32", 0},
+ {"type:*int32", 0},
+ {"type:uint32", 0},
+ {"type:*uint32", 0},
+ {"type:int64", 0},
+ {"type:*int64", 0},
+ {"type:uint64", 0},
+ {"type:*uint64", 0},
+ {"type:float32", 0},
+ {"type:*float32", 0},
+ {"type:float64", 0},
+ {"type:*float64", 0},
+ {"type:complex64", 0},
+ {"type:*complex64", 0},
+ {"type:complex128", 0},
+ {"type:*complex128", 0},
+ {"type:unsafe.Pointer", 0},
+ {"type:*unsafe.Pointer", 0},
+ {"type:uintptr", 0},
+ {"type:*uintptr", 0},
+ {"type:bool", 0},
+ {"type:*bool", 0},
+ {"type:string", 0},
+ {"type:*string", 0},
+ {"type:error", 0},
+ {"type:*error", 0},
+ {"type:func(error) string", 0},
+ {"type:*func(error) string", 0},
}
extras := append(fextras[:], enumerateBasicTypes()...)
for _, b := range extras {
prefix := ""
- if !strings.HasPrefix(b.name, "type.") {
+ if !strings.HasPrefix(b.name, "type:") {
prefix = pkg + "."
}
name := prefix + b.name
"func(error) string"}
result := []extra{}
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
}
if s.ReflectMethod() {
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
}
flag2 := uint8(0)
if s.UsedInIface() {
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
}
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) {
// TODO: maybe the compiler could set the alignment for all
// data symbols more carefully.
switch {
- case strings.HasPrefix(s.Name, "go.string."),
- strings.HasPrefix(name, "type..namedata."),
- strings.HasPrefix(name, "type..importpath."),
+ case strings.HasPrefix(s.Name, "go:string."),
+ strings.HasPrefix(name, "type:.namedata."),
+ strings.HasPrefix(name, "type:.importpath."),
strings.HasPrefix(name, "runtime.gcbits."),
strings.HasSuffix(name, ".opendefer"),
strings.HasSuffix(name, ".arginfo0"),
strings.HasSuffix(name, ".wrapinfo") ||
strings.HasSuffix(name, ".args_stackmap") ||
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 0
if ldr.SymName(rs) == "main.main" || (!target.IsPlugin() && ldr.SymName(rs) == "main..inittask") {
sb := ldr.MakeSymbolUpdater(rs)
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
// DWARF info between the compiler and linker.
continue
}
if goType := l.SymGoType(s); goType == 0 {
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)
return
}
}
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
// to find one of these accidentally.
data := "\xff Go build ID: " + strconv.Quote(*flagBuildid) + "\n \xff"
}
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))
ldr.SetSymSect(s, sect)
ldr.SetSymValue(s, int64(sect.Vaddr+16))
// We redirect unreachable methods to it.
names = append(names, "runtime.unreachableMethod")
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,
// 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 {
relocs := d.ldr.Relocs(exportsIdx)
for i := 0; i < relocs.Count(); i++ {
pos, neg string // positive and negative patterns
}{
{"reflectcall", "", "main.T.M"},
- {"typedesc", "", "type.main.T"},
+ {"typedesc", "", "type:main.T"},
{"ifacemethod", "", "main.T.M"},
{"ifacemethod2", "main.T.M", ""},
{"ifacemethod3", "main.S.M", ""},
arch *sys.Arch
// 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
// This maps loader symbol for the DWARF DIE symbol generated for
- // a type (e.g. "go.info.uintptr") to the type symbol itself
- // ("type.uintptr").
+ // a type (e.g. "go:info.uintptr") to the type symbol itself
+ // ("type:uintptr").
// FIXME: try converting this map (and the next one) to a single
// array indexed by loader.Sym -- this may perform better.
rtmap map[loader.Sym]loader.Sym
- // 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")
+ // 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")
tdmap map[loader.Sym]loader.Sym
// Cache these type symbols, so as to avoid repeatedly looking them up
func (d *dwctxt) walksymtypedef(symIdx loader.Sym) loader.Sym {
// 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.
- // "type.uintptr") and then to the typedef DIE for the type.
+ // "go:info.type.uintptr". Map that first to the type symbol (e.g.
+ // "type:uintptr") and then to the typedef DIE for the type.
// FIXME: this seems clunky, maybe there is a better way to do this.
if ts, ok := d.rtmap[symIdx]; ok {
}
sn := d.ldr.SymName(gotype)
- if !strings.HasPrefix(sn, "type.") {
- d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type.\"")
+ if !strings.HasPrefix(sn, "type:") {
+ d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type:\"")
return d.mustFind("<unspecified>")
}
name := sn[5:] // could also decode from Type.string
s := decodetypeStructFieldType(d.ldr, d.arch, gotype, i)
if f == "" {
sn := d.ldr.SymName(s)
- f = sn[5:] // skip "type."
+ f = sn[5:] // skip "type:"
}
fld := d.newdie(die, dwarf.DW_ABRV_STRUCTFIELD, f)
d.newrefattr(fld, dwarf.DW_AT_type, d.defgotype(s))
// The DWARF info synthesizes pointer types that don't exist at the
// language level, like *hash<...> and *bucket<...>, and the data
// 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) {
newattr(pdie, dwarf.DW_AT_go_runtime_type, dwarf.DW_CLS_GO_TYPEREF, 0, dwSym(gts))
}
}
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 {
return
}
}
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 {
return
}
}
func (d *dwctxt) synthesizemaptypes(ctxt *Link, die *dwarf.DWDie) {
- hash := walktypedef(d.findprotodie(ctxt, "type.runtime.hmap"))
- bucket := walktypedef(d.findprotodie(ctxt, "type.runtime.bmap"))
+ hash := walktypedef(d.findprotodie(ctxt, "type:runtime.hmap"))
+ bucket := walktypedef(d.findprotodie(ctxt, "type:runtime.bmap"))
if hash == nil {
return
}
func (d *dwctxt) synthesizechantypes(ctxt *Link, die *dwarf.DWDie) {
- sudog := walktypedef(d.findprotodie(ctxt, "type.runtime.sudog"))
- waitq := walktypedef(d.findprotodie(ctxt, "type.runtime.waitq"))
- hchan := walktypedef(d.findprotodie(ctxt, "type.runtime.hchan"))
+ sudog := walktypedef(d.findprotodie(ctxt, "type:runtime.sudog"))
+ waitq := walktypedef(d.findprotodie(ctxt, "type:runtime.waitq"))
+ hchan := walktypedef(d.findprotodie(ctxt, "type:runtime.hchan"))
if sudog == nil || waitq == nil || hchan == nil {
return
}
// symbol name here?
sn := d.ldr.SymName(rsym)
tn := sn[len(dwarf.InfoPrefix):]
- ts := d.ldr.Lookup("type."+tn, 0)
+ ts := d.ldr.Lookup("type:"+tn, 0)
d.defgotype(ts)
}
}
die := d.newdie(&dwtypes, abrv, tname)
// Look up type symbol.
- gotype := d.lookupOrDiag("type." + tname)
+ gotype := d.lookupOrDiag("type:" + tname)
// Map from die sym to type sym
ds := loader.Sym(die.Sym.(dwSym))
rsn := d.ldr.SymName(rsym)
tn := rsn[len(dwarf.InfoPrefix):]
- ts := d.ldr.Lookup("type."+tn, 0)
+ ts := d.ldr.Lookup("type:"+tn, 0)
d.defgotype(ts)
}
}
tdmap: make(map[loader.Sym]loader.Sym),
rtmap: make(map[loader.Sym]loader.Sym),
}
- d.typeRuntimeEface = d.lookupOrDiag("type.runtime.eface")
- d.typeRuntimeIface = d.lookupOrDiag("type.runtime.iface")
+ d.typeRuntimeEface = d.lookupOrDiag("type:runtime.eface")
+ d.typeRuntimeIface = d.lookupOrDiag("type:runtime.iface")
if ctxt.HeadType == objabi.Haix {
// Initial map used to store package size for each DWARF section.
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_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")
// Prototypes needed for type synthesis.
prototypedies = map[string]*dwarf.DWDie{
- "type.runtime.stringStructDWARF": nil,
- "type.runtime.slice": nil,
- "type.runtime.hmap": nil,
- "type.runtime.bmap": nil,
- "type.runtime.sudog": nil,
- "type.runtime.waitq": nil,
- "type.runtime.hchan": nil,
+ "type:runtime.stringStructDWARF": nil,
+ "type:runtime.slice": nil,
+ "type:runtime.hmap": nil,
+ "type:runtime.bmap": nil,
+ "type:runtime.sudog": nil,
+ "type:runtime.waitq": nil,
+ "type:runtime.hchan": nil,
}
// Needed by the prettyprinter code for interface inspection.
for _, typ := range []string{
- "type.runtime._type",
- "type.runtime.arraytype",
- "type.runtime.chantype",
- "type.runtime.functype",
- "type.runtime.maptype",
- "type.runtime.ptrtype",
- "type.runtime.slicetype",
- "type.runtime.structtype",
- "type.runtime.interfacetype",
- "type.runtime.itab",
- "type.runtime.imethod"} {
+ "type:runtime._type",
+ "type:runtime.arraytype",
+ "type:runtime.chantype",
+ "type:runtime.functype",
+ "type:runtime.maptype",
+ "type:runtime.ptrtype",
+ "type:runtime.slicetype",
+ "type:runtime.structtype",
+ "type:runtime.interfacetype",
+ "type:runtime.itab",
+ "type:runtime.imethod"} {
d.defgotype(d.lookupOrDiag(typ))
}
if ctxt.IsShared() {
// The go.link.abihashbytes symbol will be pointed at the appropriate
// 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)
ldr.SetAttrLocal(s, true)
sb.SetType(sym.SRODATA)
func fieldtrack(arch *sys.Arch, l *loader.Loader) {
var buf bytes.Buffer
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) {
l.SetAttrSpecial(i, true)
l.SetAttrNotInSymbolTable(i, true)
// Create a new init func text symbol. Caller will populate this
// 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)
ctxt.loader.SetAttrReachable(ifs, true)
ctxt.loader.SetAttrLocal(ifs, true)
ctxt.Textp = append(ctxt.Textp, initfunc.Sym())
// 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)
ctxt.loader.SetAttrReachable(amdi, true)
ctxt.loader.SetAttrLocal(amdi, true)
// 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.
-// Leave type.runtime. symbols alone, because other parts of
+// Leave type:runtime. symbols alone, because other parts of
// the linker manipulates them.
func typeSymbolMangle(name string) string {
- if !strings.HasPrefix(name, "type.") {
+ if !strings.HasPrefix(name, "type:") {
return name
}
- if strings.HasPrefix(name, "type.runtime.") {
+ if strings.HasPrefix(name, "type:runtime.") {
return name
}
if len(name) <= 14 && !strings.Contains(name, "@") { // Issue 19529
return name
}
hash := notsha256.Sum256([]byte(name))
- prefix := "type."
+ prefix := "type:"
if name[5] == '.' {
- prefix = "type.."
+ prefix = "type:."
}
return prefix + base64.StdEncoding.EncodeToString(hash[:6])
}
continue
}
- // Symbols whose names start with "type." are compiler
- // generated, so make functions with that prefix internal.
+ // Symbols whose names start with "type:" are compiler generated,
+ // so make functions with that prefix internal.
ver := 0
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
} else if buildcfg.Experiment.RegabiWrappers && elf.ST_TYPE(elfsym.Info) == elf.STT_FUNC {
// Demangle the ABI name. Keep in sync with symtab.go:mangleABIName.
// The decodetype_* functions in decodetype.go need access to
// the type data.
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))
}
}
return true
}
name := ldr.SymName(s)
- if strings.HasPrefix(name, "go.itab.") {
+ if strings.HasPrefix(name, "go:itab.") {
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
- // export alg functions (type..*), as these
+ // export alg functions (type:.*), as these
// appear in pclntable.
return true
}
- if strings.HasPrefix(name, "go.link.pkghash") {
+ if strings.HasPrefix(name, "go:link.pkghash") {
return true
}
return ldr.SymType(s) >= sym.SFirstWritable // only writable sections
// Write header.
// 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, 7, uint8(ctxt.Arch.PtrSize))
off := header.SetUint(ctxt.Arch, 8, uint64(state.nfunc))
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
deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer)
- gofunc := ldr.Lookup("go.func.*", 0)
+ gofunc := ldr.Lookup("go:func.*", 0)
gofuncBase := ldr.SymValue(gofunc)
textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0))
funcdata := []loader.Sym{}
}
}
- // 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)
// Missing funcdata will be ^0. See runtime/symtab.go:funcdata.
off = int64(startLocations[i] + funcSize + numPCData(ldr, s, fi)*4)
}
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))
}
// Only windows/386 requires underscore prefix on external symbols.
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
}
var symtype, symtyperel loader.Sym
if !ctxt.DynlinkingGo() {
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.SetSize(0)
s.SetAlign(int32(ctxt.Arch.PtrSize))
s.SetAlign(int32(ctxt.Arch.PtrSize))
symtyperel = s.Sym()
} else {
- s = ldr.CreateSymForUpdate("type.*", 0)
+ s = ldr.CreateSymForUpdate("type:*", 0)
s.SetType(sym.STYPE)
s.SetSize(0)
s.SetAlign(int32(ctxt.Arch.PtrSize))
return s.Sym()
}
var (
- symgostring = groupSym("go.string.*", sym.SGOSTRING)
- symgofunc = groupSym("go.func.*", sym.SGOFUNC)
+ symgostring = groupSym("go:string.*", sym.SGOSTRING)
+ symgofunc = groupSym("go:func.*", sym.SGOFUNC)
symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS)
)
symgofuncrel := symgofunc
if ctxt.UseRelro() {
- symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
+ symgofuncrel = groupSym("go:funcrel.*", sym.SGOFUNCRELRO)
}
symt := ldr.CreateSymForUpdate("runtime.symtab", 0)
name := ldr.SymName(s)
switch {
- case strings.HasPrefix(name, "go.string."):
+ case strings.HasPrefix(name, "go:string."):
symGroupType[s] = sym.SGOSTRING
ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetCarrierSym(s, symgostring)
case strings.HasPrefix(name, "runtime.gcbits."),
- strings.HasPrefix(name, "type..gcprog."):
+ strings.HasPrefix(name, "type:.gcprog."):
symGroupType[s] = sym.SGCBITS
ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetCarrierSym(s, symgcbits)
liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
}
- // Note: Check for "type." prefix after checking for .arginfo1 suffix.
- // That way symbols like "type..eq.[2]interface {}.arginfo1" that belong
- // in go.func.* end up there.
- case strings.HasPrefix(name, "type."):
+ // Note: Check for "type:" prefix after checking for .arginfo1 suffix.
+ // That way symbols like "type:.eq.[2]interface {}.arginfo1" that belong
+ // in go:func.* end up there.
+ case strings.HasPrefix(name, "type:"):
if !ctxt.DynlinkingGo() {
ldr.SetAttrNotInSymbolTable(s, true)
}
}
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)
- hashsym := ldr.LookupOrCreateSym("go.link.abihashbytes", 0)
+ hashsym := ldr.LookupOrCreateSym("go:link.abihashbytes", 0)
abihashgostr.AddAddr(ctxt.Arch, hashsym)
abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym)))
}
if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
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.SetSize(int64(len(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.AddAddr(ctxt.Arch, s.Sym())
str.AddUint(ctxt.Arch, uint64(len(l.Fingerprint)))
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.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() {
// Add R_XCOFFREF relocation to prevent ld's garbage collection of
// important that the offsets we computed stay unchanged by the external
// linker, i.e. all symbols in Textp should not be removed.
// Most of them are actually referenced (our deadcode pass ensures that),
- // except go.buildid which is generated late and not used by the program.
- addRef("go.buildid")
+ // except go:buildid which is generated late and not used by the program.
+ addRef("go:buildid")
}
// text section information
moduledata.AddUint(ctxt.Arch, nitablinks)
moduledata.AddUint(ctxt.Arch, nitablinks)
// 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)
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)
moduledata.AddAddr(ctxt.Arch, ptab)
moduledata.AddUint(ctxt.Arch, 0)
}
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.SetType(sym.SRODATA)
for i, l := range ctxt.Library {
// 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
- 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
- hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0)
+ hash := ldr.Lookup("go:link.pkghash."+l.Pkg, 0)
pkghashes.AddAddr(ctxt.Arch, hash)
}
moduledata.AddAddr(ctxt.Arch, pkghashes.Sym())
// it something slightly more comprehensible.
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.SetType(sym.SRODATA)
for i, shlib := range ctxt.Shlibs {
// modulehashes[i].modulename
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
- 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
- abihash := ldr.LookupOrCreateSym("go.link.abihash."+modulename, 0)
+ abihash := ldr.LookupOrCreateSym("go:link.abihash."+modulename, 0)
ldr.SetAttrReachable(abihash, true)
modulehashes.AddAddr(ctxt.Arch, abihash)
}
// When linking an object that does not contain the runtime we are
// creating the moduledata from scratch and it does not have a
// 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.Grow(moduledata.Size())
// except symbols that are exported to C. Type symbols are always
// ABIInternal so they are not mangled.
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)
}
}
if !ctxt.DynlinkingGo() {
// runtime.types size must be removed, as it's a real symbol.
tsize := ldr.SymSize(ldr.Lookup("runtime.types", 0))
- outerSymSize["type.*"] = size - tsize
+ outerSymSize["type:*"] = size - tsize
}
case sym.SGOSTRING:
- outerSymSize["go.string.*"] = size
+ outerSymSize["go:string.*"] = size
case sym.SGOFUNC:
if !ctxt.DynlinkingGo() {
- outerSymSize["go.func.*"] = size
+ outerSymSize["go:func.*"] = size
}
case sym.SGOFUNCRELRO:
- outerSymSize["go.funcrel.*"] = size
+ outerSymSize["go:funcrel.*"] = size
case sym.SGCBITS:
outerSymSize["runtime.gcbits.*"] = size
case sym.SPCLNTAB:
syms = xfile.writeSymbolFunc(ctxt, x)
} else {
// 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)
}
s := &XcoffSymEnt64{
// here is that we get different line numbers on formal
// params; I am guessing that the pos is being inherited
// from the spot where the wrapper is needed.
- allowed := strings.HasPrefix(name, "go.info.go.interface") ||
- strings.HasPrefix(name, "go.info.go.builtin") ||
- strings.HasPrefix(name, "go.debuglines")
+ allowed := strings.HasPrefix(name, "go:info.go.interface") ||
+ strings.HasPrefix(name, "go:info.go.builtin") ||
+ strings.HasPrefix(name, "go:debuglines")
if !allowed {
l.strictDupMsgs++
}
// SubSym gets the subsymbol for host object loaded symbols.
func (l *Loader) SubSym(i Sym) Sym {
// 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]
}
// emits named string symbols (type SGOSTRING) when compiling a
// package; after being deduplicated, these symbols are collected into
// 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).
func (l *Loader) SetCarrierSym(s Sym, c Sym) {
if c == 0 {
l.SetAttrUsedInIface(gi, true)
}
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 {
// This is a definition of a builtin symbol. Record where it is.
l.builtinSyms[bi] = gi
or := &dummyOreader
// 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")
- ts3 := addDummyObjSym(t, ldr, or, "type.string")
+ ts3 := addDummyObjSym(t, ldr, or, "type:string")
// Create some external symbols.
es1 := ldr.LookupOrCreateSym("extnew1", 0)
if es1x != es1 {
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 {
t.Fatalf("LookupOrCreateSym failed for go.info.type.uint8")
}
or := &dummyOreader
// Populate loader with some symbols.
- addDummyObjSym(t, ldr, or, "type.uint8")
+ addDummyObjSym(t, ldr, or, "type:uint8")
ldr.LookupOrCreateSym("hello", 0)
arch := sys.ArchAMD64
or := &dummyOreader
// Populate loader with some symbols.
- addDummyObjSym(t, ldr, or, "type.uint8")
+ addDummyObjSym(t, ldr, or, "type:uint8")
es1 := ldr.LookupOrCreateSym("outer", 0)
ldr.MakeSymbolUpdater(es1).SetSize(101)
es2 := ldr.LookupOrCreateSym("sub1", 0)
fns := make([]*wasmFunc, len(ctxt.Textp))
for i, fn := range ctxt.Textp {
wfn := new(bytes.Buffer)
- if ldr.SymName(fn) == "go.buildid" {
+ if ldr.SymName(fn) == "go:buildid" {
writeUleb128(wfn, 0) // number of sets of locals
writeI32Const(wfn, 0)
wfn.WriteByte(0x0b) // end
func writeBuildID(ctxt *ld.Link, buildid []byte) {
sizeOffset := writeSecHeader(ctxt, sectionCustom)
- writeName(ctxt.Out, "go.buildid")
+ writeName(ctxt.Out, "go:buildid")
ctxt.Out.Write(buildid)
writeSecSize(ctxt, sizeOffset)
}
`,
bad: []string{
"tls.(*Conn)",
- "type.crypto/tls.clientHandshakeState",
- "type.crypto/tls.serverHandshakeState",
+ "type:crypto/tls.clientHandshakeState",
+ "type:crypto/tls.serverHandshakeState",
},
},
{
ver12
ver116
ver118
+ ver120
)
// A LineTable is a data structure mapping program counters to line numbers.
go12magic = 0xfffffffb
go116magic = 0xfffffffa
go118magic = 0xfffffff0
+ go120magic = 0xfffffff1
)
// uintptr returns the pointer-sized value encoded at b.
t.binary, possibleVersion = binary.LittleEndian, ver118
case beMagic == go118magic:
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:
return
}
}
switch possibleVersion {
- case ver118:
+ case ver118, ver120:
t.nfunctab = uint32(offset(0))
t.nfiletab = uint32(offset(1))
t.textStart = t.PC // use the start PC instead of reading from the table, which may be unrelocated
fileStartPC := filePC
for t.step(&fp, &filePC, &fileVal, filePC == entry) {
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:]))
}
if fileIndex == filenum && fileStartPC < filePC {
entry := f.entryPC()
filetab := f.pcfile()
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) {
// skip functions without compilation unit (not real function, or linker generated)
continue
GoType uint64
// If this symbol is a function symbol, the corresponding Func
Func *Func
+
+ goVersion version
}
// Static reports whether this symbol is static (not visible outside its file).
func (s *Sym) PackageName() string {
name := s.nameWithoutInst()
- // A prefix of "type." and "go." is a compiler-generated symbol that doesn't belong to any package.
- // See variable reservedimports in cmd/compile/internal/gc/subr.go
- if strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.") {
+ // Since go1.20, a prefix of "type:" and "go:" is a compiler-generated symbol,
+ // they do not belong to any package.
+ //
+ // 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 ""
}
ts.Type = s.typ
ts.Value = s.value
ts.GoType = s.gotype
+ ts.goVersion = pcln.version
switch s.typ {
default:
// rewrite name to use . instead of ยท (c2 b7)
}
func TestIssue29551(t *testing.T) {
- symNames := []string{
- "type..eq.[9]debug/elf.intName",
- "type..hash.debug/elf.ProgHeader",
- "type..eq.runtime._panic",
- "type..hash.struct { runtime.gList; runtime.n int32 }",
- "go.(*struct { sync.Mutex; math/big.table [64]math/big",
+ tests := []struct {
+ sym Sym
+ pkgName string
+ }{
+ {Sym{goVersion: ver120, Name: "type:.eq.[9]debug/elf.intName"}, ""},
+ {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 {
- s := Sym{Name: symName}
- assertString(t, fmt.Sprintf("package of %q", s.Name), s.PackageName(), "")
+ for _, tc := range tests {
+ assertString(t, fmt.Sprintf("package of %q", tc.sym.Name), tc.sym.PackageName(), tc.pkgName)
}
}
// pcHeader holds data used by the pclntab lookups.
type pcHeader struct {
- magic uint32 // 0xFFFFFFF0
+ magic uint32 // 0xFFFFFFF1
pad1, pad2 uint8 // 0,0
minLC uint8 // min instruction size
ptrSize uint8 // size of a ptr in bytes
func moduledataverify1(datap *moduledata) {
// Check that the pclntab's format is valid.
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 {
println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2,
"minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pcHeader.textStart=", hex(hdr.textStart),
}
func ToByteSlice() []byte { // Issue #24698
- // amd64:`LEAQ\ttype\.\[3\]uint8`
+ // amd64:`LEAQ\ttype:\[3\]uint8`
// amd64:`CALL\truntime\.newobject`
// amd64:-`.*runtime.stringtoslicebyte`
return []byte("foo")
// The type names for these types are as follows. Because we truncate
// 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.[][]...[][][]*<...> - 250 total "[]"
-// type.[][]...[][][][]<...> - 251 total "[]"
-// type.[][]...[][][][]<...> - 252 total "[]" (but only 251 "[]" in the name)
-// type.[][]...[][][][]<...> - 253 total "[]" (but only 251 "[]" in the name)
+// type:[][]...[][]*pwn - 249 total "[]"
+// type:[][]...[][][]*<...> - 250 total "[]"
+// type:[][]...[][][][]<...> - 251 total "[]"
+// type:[][]...[][][][]<...> - 252 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
// compiler will generate only a single runtime.slicetype data
// generates just the 251-entry one. There aren't any
// 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
// structure at runtime actually has 253 nesting levels. So we end up
// calling String on something that is of type [][]*pwn instead of