|  | // Copyright 2017 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package sym | 
|  |  | 
|  | import "sync/atomic" | 
|  |  | 
|  | // Attribute is a set of common symbol attributes. | 
|  | type Attribute int32 | 
|  |  | 
|  | const ( | 
|  | // AttrDuplicateOK marks a symbol that can be present in multiple object | 
|  | // files. | 
|  | AttrDuplicateOK Attribute = 1 << iota | 
|  | // AttrExternal marks function symbols loaded from host object files. | 
|  | AttrExternal | 
|  | // AttrNoSplit marks functions that cannot split the stack; the linker | 
|  | // cares because it checks that there are no call chains of nosplit | 
|  | // functions that require more than StackLimit bytes (see | 
|  | // lib.go:dostkcheck) | 
|  | AttrNoSplit | 
|  | // AttrReachable marks symbols that are transitively referenced from the | 
|  | // entry points. Unreachable symbols are not written to the output. | 
|  | AttrReachable | 
|  | // AttrCgoExportDynamic and AttrCgoExportStatic mark symbols referenced | 
|  | // by directives written by cgo (in response to //export directives in | 
|  | // the source). | 
|  | AttrCgoExportDynamic | 
|  | AttrCgoExportStatic | 
|  | // AttrSpecial marks symbols that do not have their address (i.e. Value) | 
|  | // computed by the usual mechanism of data.go:dodata() & | 
|  | // data.go:address(). | 
|  | AttrSpecial | 
|  | // AttrStackCheck is used by dostkcheck to only check each NoSplit | 
|  | // function's stack usage once. | 
|  | AttrStackCheck | 
|  | // AttrNotInSymbolTable marks symbols that are not written to the symbol table. | 
|  | AttrNotInSymbolTable | 
|  | // AttrOnList marks symbols that are on some list (such as the list of | 
|  | // all text symbols, or one of the lists of data symbols) and is | 
|  | // consulted to avoid bugs where a symbol is put on a list twice. | 
|  | AttrOnList | 
|  | // AttrLocal marks symbols that are only visible within the module | 
|  | // (executable or shared library) being linked. Only relevant when | 
|  | // dynamically linking Go code. | 
|  | AttrLocal | 
|  | // AttrReflectMethod marks certain methods from the reflect package that | 
|  | // can be used to call arbitrary methods. If no symbol with this bit set | 
|  | // is marked as reachable, more dead code elimination can be done. | 
|  | AttrReflectMethod | 
|  | // AttrMakeTypelink Amarks types that should be added to the typelink | 
|  | // table. See typelinks.go:typelinks(). | 
|  | AttrMakeTypelink | 
|  | // AttrShared marks symbols compiled with the -shared option. | 
|  | AttrShared | 
|  | // AttrVisibilityHidden symbols are ELF symbols with | 
|  | // visibility set to STV_HIDDEN. They become local symbols in | 
|  | // the final executable. Only relevant when internally linking | 
|  | // on an ELF platform. | 
|  | AttrVisibilityHidden | 
|  | // AttrSubSymbol mostly means that the symbol appears on the Sub list of some | 
|  | // other symbol.  Unfortunately, it's not 100% reliable; at least, it's not set | 
|  | // correctly for the .TOC. symbol in Link.dodata.  Usually the Outer field of the | 
|  | // symbol points to the symbol whose list it is on, but that it is not set for the | 
|  | // symbols added to .windynamic in initdynimport in pe.go. | 
|  | // | 
|  | // TODO(mwhudson): fix the inconsistencies noticed above. | 
|  | // | 
|  | // Sub lists are used when loading host objects (sections from the host object | 
|  | // become regular linker symbols and symbols go on the Sub list of their section) | 
|  | // and for constructing the global offset table when internally linking a dynamic | 
|  | // executable. | 
|  | // | 
|  | // TODO(mwhudson): perhaps a better name for this is AttrNonGoSymbol. | 
|  | AttrSubSymbol | 
|  | // AttrContainer is set on text symbols that are present as the .Outer for some | 
|  | // other symbol. | 
|  | AttrContainer | 
|  | // AttrTopFrame means that the function is an entry point and unwinders | 
|  | // should stop when they hit this function. | 
|  | AttrTopFrame | 
|  | // AttrReadOnly indicates whether the symbol's content (Symbol.P) is backed by | 
|  | // read-only memory. | 
|  | AttrReadOnly | 
|  | // 19 attributes defined so far. | 
|  | ) | 
|  |  | 
|  | func (a *Attribute) load() Attribute { return Attribute(atomic.LoadInt32((*int32)(a))) } | 
|  |  | 
|  | func (a *Attribute) DuplicateOK() bool      { return a.load()&AttrDuplicateOK != 0 } | 
|  | func (a *Attribute) External() bool         { return a.load()&AttrExternal != 0 } | 
|  | func (a *Attribute) NoSplit() bool          { return a.load()&AttrNoSplit != 0 } | 
|  | func (a *Attribute) Reachable() bool        { return a.load()&AttrReachable != 0 } | 
|  | func (a *Attribute) CgoExportDynamic() bool { return a.load()&AttrCgoExportDynamic != 0 } | 
|  | func (a *Attribute) CgoExportStatic() bool  { return a.load()&AttrCgoExportStatic != 0 } | 
|  | func (a *Attribute) Special() bool          { return a.load()&AttrSpecial != 0 } | 
|  | func (a *Attribute) StackCheck() bool       { return a.load()&AttrStackCheck != 0 } | 
|  | func (a *Attribute) NotInSymbolTable() bool { return a.load()&AttrNotInSymbolTable != 0 } | 
|  | func (a *Attribute) OnList() bool           { return a.load()&AttrOnList != 0 } | 
|  | func (a *Attribute) Local() bool            { return a.load()&AttrLocal != 0 } | 
|  | func (a *Attribute) ReflectMethod() bool    { return a.load()&AttrReflectMethod != 0 } | 
|  | func (a *Attribute) MakeTypelink() bool     { return a.load()&AttrMakeTypelink != 0 } | 
|  | func (a *Attribute) Shared() bool           { return a.load()&AttrShared != 0 } | 
|  | func (a *Attribute) VisibilityHidden() bool { return a.load()&AttrVisibilityHidden != 0 } | 
|  | func (a *Attribute) SubSymbol() bool        { return a.load()&AttrSubSymbol != 0 } | 
|  | func (a *Attribute) Container() bool        { return a.load()&AttrContainer != 0 } | 
|  | func (a *Attribute) TopFrame() bool         { return a.load()&AttrTopFrame != 0 } | 
|  | func (a *Attribute) ReadOnly() bool         { return a.load()&AttrReadOnly != 0 } | 
|  |  | 
|  | func (a *Attribute) CgoExport() bool { | 
|  | return a.CgoExportDynamic() || a.CgoExportStatic() | 
|  | } | 
|  |  | 
|  | func (a *Attribute) Set(flag Attribute, value bool) { | 
|  | // XXX it would be nice if we have atomic And, Or. | 
|  | for { | 
|  | a0 := a.load() | 
|  | var anew Attribute | 
|  | if value { | 
|  | anew = a0 | flag | 
|  | } else { | 
|  | anew = a0 &^ flag | 
|  | } | 
|  | if atomic.CompareAndSwapInt32((*int32)(a), int32(a0), int32(anew)) { | 
|  | return | 
|  | } | 
|  | } | 
|  | } |