1
2
3
4
5 package staticdata
6
7 import (
8 "crypto/sha256"
9 "fmt"
10 "go/constant"
11 "internal/buildcfg"
12 "io"
13 "io/ioutil"
14 "os"
15 "sort"
16 "strconv"
17 "sync"
18
19 "cmd/compile/internal/base"
20 "cmd/compile/internal/ir"
21 "cmd/compile/internal/objw"
22 "cmd/compile/internal/typecheck"
23 "cmd/compile/internal/types"
24 "cmd/internal/obj"
25 "cmd/internal/objabi"
26 "cmd/internal/src"
27 )
28
29
30
31 func InitAddrOffset(n *ir.Name, noff int64, lsym *obj.LSym, off int64) {
32 if n.Op() != ir.ONAME {
33 base.Fatalf("InitAddr n op %v", n.Op())
34 }
35 if n.Sym() == nil {
36 base.Fatalf("InitAddr nil n sym")
37 }
38 s := n.Linksym()
39 s.WriteAddr(base.Ctxt, noff, types.PtrSize, lsym, off)
40 }
41
42
43 func InitAddr(n *ir.Name, noff int64, lsym *obj.LSym) {
44 InitAddrOffset(n, noff, lsym, 0)
45 }
46
47
48
49 func InitSlice(n *ir.Name, noff int64, lsym *obj.LSym, lencap int64) {
50 s := n.Linksym()
51 s.WriteAddr(base.Ctxt, noff, types.PtrSize, lsym, 0)
52 s.WriteInt(base.Ctxt, noff+types.SliceLenOffset, types.PtrSize, lencap)
53 s.WriteInt(base.Ctxt, noff+types.SliceCapOffset, types.PtrSize, lencap)
54 }
55
56 func InitSliceBytes(nam *ir.Name, off int64, s string) {
57 if nam.Op() != ir.ONAME {
58 base.Fatalf("InitSliceBytes %v", nam)
59 }
60 InitSlice(nam, off, slicedata(nam.Pos(), s).Linksym(), int64(len(s)))
61 }
62
63 const (
64 stringSymPrefix = "go.string."
65 stringSymPattern = ".gostring.%d.%x"
66 )
67
68
69
70 func StringSym(pos src.XPos, s string) (data *obj.LSym) {
71 var symname string
72 if len(s) > 100 {
73
74
75
76
77 h := sha256.New()
78 io.WriteString(h, s)
79 symname = fmt.Sprintf(stringSymPattern, len(s), h.Sum(nil))
80 } else {
81
82 symname = strconv.Quote(s)
83 }
84
85 symdata := base.Ctxt.Lookup(stringSymPrefix + symname)
86 if !symdata.OnList() {
87 off := dstringdata(symdata, 0, s, pos, "string")
88 objw.Global(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
89 symdata.Set(obj.AttrContentAddressable, true)
90 }
91
92 return symdata
93 }
94
95
96
97
98
99
100
101
102 func fileStringSym(pos src.XPos, file string, readonly bool, hash []byte) (*obj.LSym, int64, error) {
103 f, err := os.Open(file)
104 if err != nil {
105 return nil, 0, err
106 }
107 defer f.Close()
108 info, err := f.Stat()
109 if err != nil {
110 return nil, 0, err
111 }
112 if !info.Mode().IsRegular() {
113 return nil, 0, fmt.Errorf("not a regular file")
114 }
115 size := info.Size()
116 if size <= 1*1024 {
117 data, err := ioutil.ReadAll(f)
118 if err != nil {
119 return nil, 0, err
120 }
121 if int64(len(data)) != size {
122 return nil, 0, fmt.Errorf("file changed between reads")
123 }
124 var sym *obj.LSym
125 if readonly {
126 sym = StringSym(pos, string(data))
127 } else {
128 sym = slicedata(pos, string(data)).Linksym()
129 }
130 if len(hash) > 0 {
131 sum := sha256.Sum256(data)
132 copy(hash, sum[:])
133 }
134 return sym, size, nil
135 }
136 if size > 2e9 {
137
138
139
140
141 return nil, 0, fmt.Errorf("file too large")
142 }
143
144
145
146 var sum []byte
147 if readonly || len(hash) > 0 {
148 h := sha256.New()
149 n, err := io.Copy(h, f)
150 if err != nil {
151 return nil, 0, err
152 }
153 if n != size {
154 return nil, 0, fmt.Errorf("file changed between reads")
155 }
156 sum = h.Sum(nil)
157 copy(hash, sum)
158 }
159
160 var symdata *obj.LSym
161 if readonly {
162 symname := fmt.Sprintf(stringSymPattern, size, sum)
163 symdata = base.Ctxt.Lookup(stringSymPrefix + symname)
164 if !symdata.OnList() {
165 info := symdata.NewFileInfo()
166 info.Name = file
167 info.Size = size
168 objw.Global(symdata, int32(size), obj.DUPOK|obj.RODATA|obj.LOCAL)
169
170
171
172 }
173 } else {
174
175
176 symdata = slicedata(pos, "").Linksym()
177 symdata.Size = size
178 symdata.Type = objabi.SNOPTRDATA
179 info := symdata.NewFileInfo()
180 info.Name = file
181 info.Size = size
182 }
183
184 return symdata, size, nil
185 }
186
187 var slicedataGen int
188
189 func slicedata(pos src.XPos, s string) *ir.Name {
190 slicedataGen++
191 symname := fmt.Sprintf(".gobytes.%d", slicedataGen)
192 sym := types.LocalPkg.Lookup(symname)
193 symnode := typecheck.NewName(sym)
194 sym.Def = symnode
195
196 lsym := symnode.Linksym()
197 off := dstringdata(lsym, 0, s, pos, "slice")
198 objw.Global(lsym, int32(off), obj.NOPTR|obj.LOCAL)
199
200 return symnode
201 }
202
203 func dstringdata(s *obj.LSym, off int, t string, pos src.XPos, what string) int {
204
205
206
207 if int64(len(t)) > 2e9 {
208 base.ErrorfAt(pos, "%v with length %v is too big", what, len(t))
209 return 0
210 }
211
212 s.WriteString(base.Ctxt, int64(off), len(t), t)
213 return off + len(t)
214 }
215
216 var (
217 funcsymsmu sync.Mutex
218 funcsyms []*ir.Name
219 )
220
221
222 func FuncLinksym(n *ir.Name) *obj.LSym {
223 if n.Op() != ir.ONAME || n.Class != ir.PFUNC {
224 base.Fatalf("expected func name: %v", n)
225 }
226 s := n.Sym()
227
228
229
230
231
232
233
234
235
236
237 funcsymsmu.Lock()
238 sf, existed := s.Pkg.LookupOK(ir.FuncSymName(s))
239
240
241
242
243 if !base.Ctxt.Flag_dynlink && !existed {
244 funcsyms = append(funcsyms, n)
245 }
246 funcsymsmu.Unlock()
247
248 return sf.Linksym()
249 }
250
251 func GlobalLinksym(n *ir.Name) *obj.LSym {
252 if n.Op() != ir.ONAME || n.Class != ir.PEXTERN {
253 base.Fatalf("expected global variable: %v", n)
254 }
255 return n.Linksym()
256 }
257
258
259
260
261
262
263
264
265
266
267 func NeedFuncSym(fn *ir.Func) {
268 if base.Ctxt.InParallel {
269
270
271 base.Fatalf("NeedFuncSym must be called in serial")
272 }
273 if fn.ABI != obj.ABIInternal && buildcfg.Experiment.RegabiWrappers {
274
275
276
277
278
279 base.Fatalf("expected ABIInternal: %v has %v", fn.Nname, fn.ABI)
280 }
281 if ir.IsBlank(fn.Nname) {
282
283
284 base.Fatalf("NeedFuncSym called for _")
285 }
286 if !base.Ctxt.Flag_dynlink {
287 return
288 }
289 s := fn.Nname.Sym()
290 if base.Flag.CompilingRuntime && (s.Name == "getg" || s.Name == "getclosureptr" || s.Name == "getcallerpc" || s.Name == "getcallersp") ||
291 (base.Ctxt.Pkgpath == "internal/abi" && (s.Name == "FuncPCABI0" || s.Name == "FuncPCABIInternal")) {
292
293
294
295 return
296 }
297 funcsyms = append(funcsyms, fn.Nname)
298 }
299
300 func WriteFuncSyms() {
301 sort.Slice(funcsyms, func(i, j int) bool {
302 return funcsyms[i].Linksym().Name < funcsyms[j].Linksym().Name
303 })
304 for _, nam := range funcsyms {
305 s := nam.Sym()
306 sf := s.Pkg.Lookup(ir.FuncSymName(s)).Linksym()
307
308
309 target := s.Linksym()
310 if target.ABI() != obj.ABIInternal {
311 base.Fatalf("expected ABIInternal: %v has %v", target, target.ABI())
312 }
313 objw.SymPtr(sf, 0, target, 0)
314 objw.Global(sf, int32(types.PtrSize), obj.DUPOK|obj.RODATA)
315 }
316 }
317
318
319
320 func InitConst(n *ir.Name, noff int64, c ir.Node, wid int) {
321 if n.Op() != ir.ONAME {
322 base.Fatalf("InitConst n op %v", n.Op())
323 }
324 if n.Sym() == nil {
325 base.Fatalf("InitConst nil n sym")
326 }
327 if c.Op() == ir.ONIL {
328 return
329 }
330 if c.Op() != ir.OLITERAL {
331 base.Fatalf("InitConst c op %v", c.Op())
332 }
333 s := n.Linksym()
334 switch u := c.Val(); u.Kind() {
335 case constant.Bool:
336 i := int64(obj.Bool2int(constant.BoolVal(u)))
337 s.WriteInt(base.Ctxt, noff, wid, i)
338
339 case constant.Int:
340 s.WriteInt(base.Ctxt, noff, wid, ir.IntVal(c.Type(), u))
341
342 case constant.Float:
343 f, _ := constant.Float64Val(u)
344 switch c.Type().Kind() {
345 case types.TFLOAT32:
346 s.WriteFloat32(base.Ctxt, noff, float32(f))
347 case types.TFLOAT64:
348 s.WriteFloat64(base.Ctxt, noff, f)
349 }
350
351 case constant.Complex:
352 re, _ := constant.Float64Val(constant.Real(u))
353 im, _ := constant.Float64Val(constant.Imag(u))
354 switch c.Type().Kind() {
355 case types.TCOMPLEX64:
356 s.WriteFloat32(base.Ctxt, noff, float32(re))
357 s.WriteFloat32(base.Ctxt, noff+4, float32(im))
358 case types.TCOMPLEX128:
359 s.WriteFloat64(base.Ctxt, noff, re)
360 s.WriteFloat64(base.Ctxt, noff+8, im)
361 }
362
363 case constant.String:
364 i := constant.StringVal(u)
365 symdata := StringSym(n.Pos(), i)
366 s.WriteAddr(base.Ctxt, noff, types.PtrSize, symdata, 0)
367 s.WriteInt(base.Ctxt, noff+int64(types.PtrSize), types.PtrSize, int64(len(i)))
368
369 default:
370 base.Fatalf("InitConst unhandled OLITERAL %v", c)
371 }
372 }
373
View as plain text