mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.regabi] cmd/compile: split out package staticdata [generated]
[git-generate] cd src/cmd/compile/internal/gc rf ' # Export API and move to its own files. mv addrsym InitAddr mv pfuncsym InitFunc mv slicesym InitSlice mv slicebytes InitSliceBytes mv stringsym StringSym mv funcsym FuncSym mv makefuncsym NeedFuncSym mv dumpfuncsyms WriteFuncSyms mv InitAddr InitFunc InitSlice InitSliceBytes stringSymPrefix \ StringSym fileStringSym slicedataGen slicedata dstringdata \ funcsyms FuncSym NeedFuncSym WriteFuncSyms \ data.go mv initEmbed WriteEmbed mv dumpembeds obj.go mv data.go embed.go cmd/compile/internal/staticdata ' Change-Id: I209c5e597c8acfa29a48527695a9ddc1e9ea8e6a Reviewed-on: https://go-review.googlesource.com/c/go/+/279474 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
fbc82f03b1
commit
4dfb5d91a8
9 changed files with 338 additions and 318 deletions
|
|
@ -8,22 +8,16 @@ import (
|
|||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/compile/internal/objw"
|
||||
"cmd/compile/internal/staticdata"
|
||||
"cmd/compile/internal/typecheck"
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/archive"
|
||||
"cmd/internal/bio"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/objabi"
|
||||
"cmd/internal/src"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// These modes say which kind of object file to generate.
|
||||
|
|
@ -117,7 +111,7 @@ func dumpdata() {
|
|||
numDecls := len(typecheck.Target.Decls)
|
||||
|
||||
dumpglobls(typecheck.Target.Externs)
|
||||
dumpfuncsyms()
|
||||
staticdata.WriteFuncSyms()
|
||||
addptabs()
|
||||
numExports := len(typecheck.Target.Exports)
|
||||
addsignats(typecheck.Target.Externs)
|
||||
|
|
@ -270,17 +264,6 @@ func dumpglobls(externs []ir.Node) {
|
|||
}
|
||||
}
|
||||
|
||||
func dumpfuncsyms() {
|
||||
sort.Slice(funcsyms, func(i, j int) bool {
|
||||
return funcsyms[i].LinksymName() < funcsyms[j].LinksymName()
|
||||
})
|
||||
for _, s := range funcsyms {
|
||||
sf := s.Pkg.Lookup(ir.FuncSymName(s)).Linksym()
|
||||
objw.SymPtr(sf, 0, s.Linksym(), 0)
|
||||
objw.Global(sf, int32(types.PtrSize), obj.DUPOK|obj.RODATA)
|
||||
}
|
||||
}
|
||||
|
||||
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
|
||||
//
|
||||
// This is done during the sequential phase after compilation, since
|
||||
|
|
@ -307,210 +290,6 @@ func addGCLocals() {
|
|||
}
|
||||
}
|
||||
|
||||
const (
|
||||
stringSymPrefix = "go.string."
|
||||
stringSymPattern = ".gostring.%d.%x"
|
||||
)
|
||||
|
||||
// stringsym returns a symbol containing the string s.
|
||||
// The symbol contains the string data, not a string header.
|
||||
func stringsym(pos src.XPos, s string) (data *obj.LSym) {
|
||||
var symname string
|
||||
if len(s) > 100 {
|
||||
// Huge strings are hashed to avoid long names in object files.
|
||||
// Indulge in some paranoia by writing the length of s, too,
|
||||
// as protection against length extension attacks.
|
||||
// Same pattern is known to fileStringSym below.
|
||||
h := sha256.New()
|
||||
io.WriteString(h, s)
|
||||
symname = fmt.Sprintf(stringSymPattern, len(s), h.Sum(nil))
|
||||
} else {
|
||||
// Small strings get named directly by their contents.
|
||||
symname = strconv.Quote(s)
|
||||
}
|
||||
|
||||
symdata := base.Ctxt.Lookup(stringSymPrefix + symname)
|
||||
if !symdata.OnList() {
|
||||
off := dstringdata(symdata, 0, s, pos, "string")
|
||||
objw.Global(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
|
||||
symdata.Set(obj.AttrContentAddressable, true)
|
||||
}
|
||||
|
||||
return symdata
|
||||
}
|
||||
|
||||
// fileStringSym returns a symbol for the contents and the size of file.
|
||||
// If readonly is true, the symbol shares storage with any literal string
|
||||
// or other file with the same content and is placed in a read-only section.
|
||||
// If readonly is false, the symbol is a read-write copy separate from any other,
|
||||
// for use as the backing store of a []byte.
|
||||
// The content hash of file is copied into hash. (If hash is nil, nothing is copied.)
|
||||
// The returned symbol contains the data itself, not a string header.
|
||||
func fileStringSym(pos src.XPos, file string, readonly bool, hash []byte) (*obj.LSym, int64, error) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
info, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return nil, 0, fmt.Errorf("not a regular file")
|
||||
}
|
||||
size := info.Size()
|
||||
if size <= 1*1024 {
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if int64(len(data)) != size {
|
||||
return nil, 0, fmt.Errorf("file changed between reads")
|
||||
}
|
||||
var sym *obj.LSym
|
||||
if readonly {
|
||||
sym = stringsym(pos, string(data))
|
||||
} else {
|
||||
sym = slicedata(pos, string(data)).Sym().Linksym()
|
||||
}
|
||||
if len(hash) > 0 {
|
||||
sum := sha256.Sum256(data)
|
||||
copy(hash, sum[:])
|
||||
}
|
||||
return sym, size, nil
|
||||
}
|
||||
if size > 2e9 {
|
||||
// ggloblsym takes an int32,
|
||||
// and probably the rest of the toolchain
|
||||
// can't handle such big symbols either.
|
||||
// See golang.org/issue/9862.
|
||||
return nil, 0, fmt.Errorf("file too large")
|
||||
}
|
||||
|
||||
// File is too big to read and keep in memory.
|
||||
// Compute hash if needed for read-only content hashing or if the caller wants it.
|
||||
var sum []byte
|
||||
if readonly || len(hash) > 0 {
|
||||
h := sha256.New()
|
||||
n, err := io.Copy(h, f)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if n != size {
|
||||
return nil, 0, fmt.Errorf("file changed between reads")
|
||||
}
|
||||
sum = h.Sum(nil)
|
||||
copy(hash, sum)
|
||||
}
|
||||
|
||||
var symdata *obj.LSym
|
||||
if readonly {
|
||||
symname := fmt.Sprintf(stringSymPattern, size, sum)
|
||||
symdata = base.Ctxt.Lookup(stringSymPrefix + symname)
|
||||
if !symdata.OnList() {
|
||||
info := symdata.NewFileInfo()
|
||||
info.Name = file
|
||||
info.Size = size
|
||||
objw.Global(symdata, int32(size), obj.DUPOK|obj.RODATA|obj.LOCAL)
|
||||
// Note: AttrContentAddressable cannot be set here,
|
||||
// because the content-addressable-handling code
|
||||
// does not know about file symbols.
|
||||
}
|
||||
} else {
|
||||
// Emit a zero-length data symbol
|
||||
// and then fix up length and content to use file.
|
||||
symdata = slicedata(pos, "").Sym().Linksym()
|
||||
symdata.Size = size
|
||||
symdata.Type = objabi.SNOPTRDATA
|
||||
info := symdata.NewFileInfo()
|
||||
info.Name = file
|
||||
info.Size = size
|
||||
}
|
||||
|
||||
return symdata, size, nil
|
||||
}
|
||||
|
||||
var slicedataGen int
|
||||
|
||||
func slicedata(pos src.XPos, s string) *ir.Name {
|
||||
slicedataGen++
|
||||
symname := fmt.Sprintf(".gobytes.%d", slicedataGen)
|
||||
sym := types.LocalPkg.Lookup(symname)
|
||||
symnode := typecheck.NewName(sym)
|
||||
sym.Def = symnode
|
||||
|
||||
lsym := sym.Linksym()
|
||||
off := dstringdata(lsym, 0, s, pos, "slice")
|
||||
objw.Global(lsym, int32(off), obj.NOPTR|obj.LOCAL)
|
||||
|
||||
return symnode
|
||||
}
|
||||
|
||||
func slicebytes(nam *ir.Name, off int64, s string) {
|
||||
if nam.Op() != ir.ONAME {
|
||||
base.Fatalf("slicebytes %v", nam)
|
||||
}
|
||||
slicesym(nam, off, slicedata(nam.Pos(), s), int64(len(s)))
|
||||
}
|
||||
|
||||
func dstringdata(s *obj.LSym, off int, t string, pos src.XPos, what string) int {
|
||||
// Objects that are too large will cause the data section to overflow right away,
|
||||
// causing a cryptic error message by the linker. Check for oversize objects here
|
||||
// and provide a useful error message instead.
|
||||
if int64(len(t)) > 2e9 {
|
||||
base.ErrorfAt(pos, "%v with length %v is too big", what, len(t))
|
||||
return 0
|
||||
}
|
||||
|
||||
s.WriteString(base.Ctxt, int64(off), len(t), t)
|
||||
return off + len(t)
|
||||
}
|
||||
|
||||
// slicesym writes a static slice symbol {&arr, lencap, lencap} to n+noff.
|
||||
// slicesym does not modify n.
|
||||
func slicesym(n *ir.Name, noff int64, arr *ir.Name, lencap int64) {
|
||||
s := n.Sym().Linksym()
|
||||
if arr.Op() != ir.ONAME {
|
||||
base.Fatalf("slicesym non-name arr %v", arr)
|
||||
}
|
||||
s.WriteAddr(base.Ctxt, noff, types.PtrSize, arr.Sym().Linksym(), 0)
|
||||
s.WriteInt(base.Ctxt, noff+types.SliceLenOffset, types.PtrSize, lencap)
|
||||
s.WriteInt(base.Ctxt, noff+types.SliceCapOffset, types.PtrSize, lencap)
|
||||
}
|
||||
|
||||
// addrsym writes the static address of a to n. a must be an ONAME.
|
||||
// Neither n nor a is modified.
|
||||
func addrsym(n *ir.Name, noff int64, a *ir.Name, aoff int64) {
|
||||
if n.Op() != ir.ONAME {
|
||||
base.Fatalf("addrsym n op %v", n.Op())
|
||||
}
|
||||
if n.Sym() == nil {
|
||||
base.Fatalf("addrsym nil n sym")
|
||||
}
|
||||
if a.Op() != ir.ONAME {
|
||||
base.Fatalf("addrsym a op %v", a.Op())
|
||||
}
|
||||
s := n.Sym().Linksym()
|
||||
s.WriteAddr(base.Ctxt, noff, types.PtrSize, a.Sym().Linksym(), aoff)
|
||||
}
|
||||
|
||||
// pfuncsym writes the static address of f to n. f must be a global function.
|
||||
// Neither n nor f is modified.
|
||||
func pfuncsym(n *ir.Name, noff int64, f *ir.Name) {
|
||||
if n.Op() != ir.ONAME {
|
||||
base.Fatalf("pfuncsym n op %v", n.Op())
|
||||
}
|
||||
if n.Sym() == nil {
|
||||
base.Fatalf("pfuncsym nil n sym")
|
||||
}
|
||||
if f.Class_ != ir.PFUNC {
|
||||
base.Fatalf("pfuncsym class not PFUNC %d", f.Class_)
|
||||
}
|
||||
s := n.Sym().Linksym()
|
||||
s.WriteAddr(base.Ctxt, noff, types.PtrSize, funcsym(f.Sym()).Linksym(), 0)
|
||||
}
|
||||
|
||||
// litsym writes the static literal c to n.
|
||||
// Neither n nor c is modified.
|
||||
func litsym(n *ir.Name, noff int64, c ir.Node, wid int) {
|
||||
|
|
@ -558,7 +337,7 @@ func litsym(n *ir.Name, noff int64, c ir.Node, wid int) {
|
|||
|
||||
case constant.String:
|
||||
i := constant.StringVal(u)
|
||||
symdata := stringsym(n.Pos(), i)
|
||||
symdata := staticdata.StringSym(n.Pos(), i)
|
||||
s.WriteAddr(base.Ctxt, noff, types.PtrSize, symdata, 0)
|
||||
s.WriteInt(base.Ctxt, noff+int64(types.PtrSize), types.PtrSize, int64(len(i)))
|
||||
|
||||
|
|
@ -588,3 +367,9 @@ func ggloblnod(nam ir.Node) {
|
|||
s.Pkg = "_"
|
||||
}
|
||||
}
|
||||
|
||||
func dumpembeds() {
|
||||
for _, v := range typecheck.Target.Embeds {
|
||||
staticdata.WriteEmbed(v)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue