From 55bd193575152ea09db3a0bd33f9dda49725d8f4 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 26 Jan 2023 15:12:00 -0500 Subject: [PATCH] cmd/internal/obj: flag init functions in object file Introduce a flag in the object file indicating whether a given function corresponds to a compiler-generated (not user-written) init function, such as "os.init" or "syscall.init". Add code to the compiler to fill in the correct value for the flag, and add support to the loader package in the linker for testing the flag. The new loader API is currently unused, but will be needed in the next CL in this stack. Updates #2559. Updates #36021. Updates #14840. Change-Id: Iea7ad2adda487e4af7a44f062f9817977c53b394 Reviewed-on: https://go-review.googlesource.com/c/go/+/463855 Reviewed-by: Cherry Mui Run-TryBot: Than McIntosh TryBot-Result: Gopher Robot --- src/cmd/compile/internal/ir/abi.go | 3 +++ src/cmd/compile/internal/ir/func.go | 3 +++ src/cmd/compile/internal/pkginit/init.go | 1 + src/cmd/internal/goobj/objfile.go | 2 ++ src/cmd/internal/obj/link.go | 5 +++++ src/cmd/internal/obj/objfile.go | 3 +++ src/cmd/internal/obj/plist.go | 1 + src/cmd/internal/obj/textflag.go | 3 +++ src/cmd/link/internal/loader/loader.go | 9 +++++++++ 9 files changed, 30 insertions(+) diff --git a/src/cmd/compile/internal/ir/abi.go b/src/cmd/compile/internal/ir/abi.go index 8cd1606e660eab..041448fb296390 100644 --- a/src/cmd/compile/internal/ir/abi.go +++ b/src/cmd/compile/internal/ir/abi.go @@ -53,6 +53,9 @@ func setupTextLSym(f *Func, flag int) { if f.ReflectMethod() { flag |= obj.REFLECTMETHOD } + if f.IsPackageInit() { + flag |= obj.PKGINIT + } // Clumsy but important. // For functions that could be on the path of invoking a deferred diff --git a/src/cmd/compile/internal/ir/func.go b/src/cmd/compile/internal/ir/func.go index 8f56c6f2f6862c..fba62283d5bad3 100644 --- a/src/cmd/compile/internal/ir/func.go +++ b/src/cmd/compile/internal/ir/func.go @@ -204,6 +204,7 @@ const ( funcInstrumentBody // add race/msan/asan instrumentation during SSA construction funcOpenCodedDeferDisallowed // can't do open-coded defers funcClosureCalled // closure is only immediately called; used by escape analysis + funcPackageInit // compiler emitted .init func for package ) type SymAndPos struct { @@ -225,6 +226,7 @@ func (f *Func) ExportInline() bool { return f.flags&funcExportInline func (f *Func) InstrumentBody() bool { return f.flags&funcInstrumentBody != 0 } func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 } func (f *Func) ClosureCalled() bool { return f.flags&funcClosureCalled != 0 } +func (f *Func) IsPackageInit() bool { return f.flags&funcPackageInit != 0 } func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) } func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) } @@ -240,6 +242,7 @@ func (f *Func) SetExportInline(b bool) { f.flags.set(funcExportInlin func (f *Func) SetInstrumentBody(b bool) { f.flags.set(funcInstrumentBody, b) } func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) } func (f *Func) SetClosureCalled(b bool) { f.flags.set(funcClosureCalled, b) } +func (f *Func) SetIsPackageInit(b bool) { f.flags.set(funcPackageInit, b) } func (f *Func) SetWBPos(pos src.XPos) { if base.Debug.WB != 0 { diff --git a/src/cmd/compile/internal/pkginit/init.go b/src/cmd/compile/internal/pkginit/init.go index 9d4c4357643d5d..fac1ad790f352a 100644 --- a/src/cmd/compile/internal/pkginit/init.go +++ b/src/cmd/compile/internal/pkginit/init.go @@ -36,6 +36,7 @@ func MakeInit() { } fn.Dcl = append(fn.Dcl, typecheck.InitTodoFunc.Dcl...) typecheck.InitTodoFunc.Dcl = nil + fn.SetIsPackageInit(true) // Suppress useless "can inline" diagnostics. // Init functions are only called dynamically. diff --git a/src/cmd/internal/goobj/objfile.go b/src/cmd/internal/goobj/objfile.go index 7b985fae53b89a..547b8264950f45 100644 --- a/src/cmd/internal/goobj/objfile.go +++ b/src/cmd/internal/goobj/objfile.go @@ -303,6 +303,7 @@ const ( SymFlagUsedInIface = 1 << iota SymFlagItab SymFlagDict + SymFlagPkgInit ) // Returns the length of the name of the symbol. @@ -333,6 +334,7 @@ func (s *Sym) IsGoType() bool { return s.Flag()&SymFlagGoType != 0 } func (s *Sym) UsedInIface() bool { return s.Flag2()&SymFlagUsedInIface != 0 } func (s *Sym) IsItab() bool { return s.Flag2()&SymFlagItab != 0 } func (s *Sym) IsDict() bool { return s.Flag2()&SymFlagDict != 0 } +func (s *Sym) IsPkgInit() bool { return s.Flag2()&SymFlagPkgInit != 0 } func (s *Sym) SetName(x string, w *Writer) { binary.LittleEndian.PutUint32(s[:], uint32(len(x))) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 6d40b334afda37..d153afbfae0f0a 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -724,6 +724,9 @@ const ( // IsPcdata indicates this is a pcdata symbol. AttrPcdata + // PkgInit indicates this is a compiler-generated package init func. + AttrPkgInit + // attrABIBase is the value at which the ABI is encoded in // Attribute. This must be last; all bits after this are // assumed to be an ABI value. @@ -752,6 +755,7 @@ func (a *Attribute) UsedInIface() bool { return a.load()&AttrUsedInIface func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddressable != 0 } func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 } func (a *Attribute) IsPcdata() bool { return a.load()&AttrPcdata != 0 } +func (a *Attribute) IsPkgInit() bool { return a.load()&AttrPkgInit != 0 } func (a *Attribute) Set(flag Attribute, value bool) { for { @@ -800,6 +804,7 @@ var textAttrStrings = [...]struct { {bit: AttrIndexed, s: ""}, {bit: AttrContentAddressable, s: ""}, {bit: AttrABIWrapper, s: "ABIWRAPPER"}, + {bit: AttrPkgInit, s: "PKGINIT"}, } // String formats a for printing in as part of a TEXT prog. diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 85e49e248c13bc..73c29d9686590b 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -344,6 +344,9 @@ func (w *writer) Sym(s *LSym) { 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) { flag2 |= goobj.SymFlagDict } + if s.IsPkgInit() { + flag2 |= goobj.SymFlagPkgInit + } name := s.Name if strings.HasPrefix(name, "gofile..") { name = filepath.ToSlash(name) diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go index fe9d2e1fb7401f..835f37f2ffc2eb 100644 --- a/src/cmd/internal/obj/plist.go +++ b/src/cmd/internal/obj/plist.go @@ -193,6 +193,7 @@ func (ctxt *Link) InitTextSym(s *LSym, flag int, start src.XPos) { s.Set(AttrABIWrapper, flag&ABIWRAPPER != 0) s.Set(AttrNeedCtxt, flag&NEEDCTXT != 0) s.Set(AttrNoFrame, flag&NOFRAME != 0) + s.Set(AttrPkgInit, flag&PKGINIT != 0) s.Type = objabi.STEXT ctxt.Text = append(ctxt.Text, s) diff --git a/src/cmd/internal/obj/textflag.go b/src/cmd/internal/obj/textflag.go index 5ae75027c2f2b5..bf9c8c99f16cdc 100644 --- a/src/cmd/internal/obj/textflag.go +++ b/src/cmd/internal/obj/textflag.go @@ -55,4 +55,7 @@ const ( // Function is an ABI wrapper. ABIWRAPPER = 4096 + + // Function is a compiler-generated package init function. + PKGINIT = 8192 ) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 2ac17f4f163a01..e3ee819a9db1b4 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -1190,6 +1190,15 @@ func (l *Loader) IsDict(i Sym) bool { return r.Sym(li).IsDict() } +// Returns whether this symbol is a compiler-generated package init func. +func (l *Loader) IsPkgInit(i Sym) bool { + if l.IsExternal(i) { + return false + } + r, li := l.toLocal(i) + return r.Sym(li).IsPkgInit() +} + // Return whether this is a trampoline of a deferreturn call. func (l *Loader) IsDeferReturnTramp(i Sym) bool { return l.deferReturnTramp[i]