Source file src/cmd/compile/internal/gc/obj.go
1
2
3
4
5 package gc
6
7 import (
8 "cmd/compile/internal/types"
9 "cmd/internal/bio"
10 "cmd/internal/obj"
11 "cmd/internal/objabi"
12 "cmd/internal/src"
13 "crypto/sha256"
14 "encoding/json"
15 "fmt"
16 "io"
17 "sort"
18 "strconv"
19 )
20
21
22 const ArhdrSize = 60
23
24 func formathdr(arhdr []byte, name string, size int64) {
25 copy(arhdr[:], fmt.Sprintf("%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, 0644, size))
26 }
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 const (
42 modeCompilerObj = 1 << iota
43 modeLinkerObj
44 )
45
46 func dumpobj() {
47 if linkobj == "" {
48 dumpobj1(outfile, modeCompilerObj|modeLinkerObj)
49 return
50 }
51 dumpobj1(outfile, modeCompilerObj)
52 dumpobj1(linkobj, modeLinkerObj)
53 }
54
55 func dumpobj1(outfile string, mode int) {
56 bout, err := bio.Create(outfile)
57 if err != nil {
58 flusherrors()
59 fmt.Printf("can't create %s: %v\n", outfile, err)
60 errorexit()
61 }
62 defer bout.Close()
63 bout.WriteString("!<arch>\n")
64
65 if mode&modeCompilerObj != 0 {
66 start := startArchiveEntry(bout)
67 dumpCompilerObj(bout)
68 finishArchiveEntry(bout, start, "__.PKGDEF")
69 }
70 if mode&modeLinkerObj != 0 {
71 start := startArchiveEntry(bout)
72 dumpLinkerObj(bout)
73 finishArchiveEntry(bout, start, "_go_.o")
74 }
75 }
76
77 func printObjHeader(bout *bio.Writer) {
78 fmt.Fprintf(bout, "go object %s %s %s %s\n", objabi.GOOS, objabi.GOARCH, objabi.Version, objabi.Expstring())
79 if buildid != "" {
80 fmt.Fprintf(bout, "build id %q\n", buildid)
81 }
82 if localpkg.Name == "main" {
83 fmt.Fprintf(bout, "main\n")
84 }
85 fmt.Fprintf(bout, "\n")
86 }
87
88 func startArchiveEntry(bout *bio.Writer) int64 {
89 var arhdr [ArhdrSize]byte
90 bout.Write(arhdr[:])
91 return bout.Offset()
92 }
93
94 func finishArchiveEntry(bout *bio.Writer, start int64, name string) {
95 bout.Flush()
96 size := bout.Offset() - start
97 if size&1 != 0 {
98 bout.WriteByte(0)
99 }
100 bout.MustSeek(start-ArhdrSize, 0)
101
102 var arhdr [ArhdrSize]byte
103 formathdr(arhdr[:], name, size)
104 bout.Write(arhdr[:])
105 bout.Flush()
106 bout.MustSeek(start+size+(size&1), 0)
107 }
108
109 func dumpCompilerObj(bout *bio.Writer) {
110 printObjHeader(bout)
111 dumpexport(bout)
112 }
113
114 func dumpLinkerObj(bout *bio.Writer) {
115 printObjHeader(bout)
116
117 if len(pragcgobuf) != 0 {
118
119 fmt.Fprintf(bout, "\n$$\n\n$$\n\n")
120 fmt.Fprintf(bout, "\n$$ // cgo\n")
121 if err := json.NewEncoder(bout).Encode(pragcgobuf); err != nil {
122 Fatalf("serializing pragcgobuf: %v", err)
123 }
124 fmt.Fprintf(bout, "\n$$\n\n")
125 }
126
127 fmt.Fprintf(bout, "\n!\n")
128
129 externs := len(externdcl)
130
131 dumpglobls()
132 addptabs()
133 addsignats(externdcl)
134 dumpsignats()
135 dumptabs()
136 dumpimportstrings()
137 dumpbasictypes()
138
139
140
141
142
143
144
145
146 for len(compilequeue) > 0 {
147 compileFunctions()
148 dumpsignats()
149 }
150
151
152 tmp := externdcl
153
154 if externdcl != nil {
155 externdcl = externdcl[externs:]
156 }
157 dumpglobls()
158 externdcl = tmp
159
160 if zerosize > 0 {
161 zero := mappkg.Lookup("zero")
162 ggloblsym(zero.Linksym(), int32(zerosize), obj.DUPOK|obj.RODATA)
163 }
164
165 addGCLocals()
166
167 obj.WriteObjFile(Ctxt, bout.Writer, myimportpath)
168 }
169
170 func addptabs() {
171 if !Ctxt.Flag_dynlink || localpkg.Name != "main" {
172 return
173 }
174 for _, exportn := range exportlist {
175 s := exportn.Sym
176 n := asNode(s.Def)
177 if n == nil {
178 continue
179 }
180 if n.Op != ONAME {
181 continue
182 }
183 if !types.IsExported(s.Name) {
184 continue
185 }
186 if s.Pkg.Name != "main" {
187 continue
188 }
189 if n.Type.Etype == TFUNC && n.Class() == PFUNC {
190
191 ptabs = append(ptabs, ptabEntry{s: s, t: asNode(s.Def).Type})
192 } else {
193
194 ptabs = append(ptabs, ptabEntry{s: s, t: types.NewPtr(asNode(s.Def).Type)})
195 }
196 }
197 }
198
199 func dumpGlobal(n *Node) {
200 if n.Type == nil {
201 Fatalf("external %v nil type\n", n)
202 }
203 if n.Class() == PFUNC {
204 return
205 }
206 if n.Sym.Pkg != localpkg {
207 return
208 }
209 dowidth(n.Type)
210 ggloblnod(n)
211 }
212
213 func dumpGlobalConst(n *Node) {
214
215 t := n.Type
216 if t == nil {
217 return
218 }
219 if n.Sym.Pkg != localpkg {
220 return
221 }
222
223 switch t.Etype {
224 case TINT8:
225 case TINT16:
226 case TINT32:
227 case TINT64:
228 case TINT:
229 case TUINT8:
230 case TUINT16:
231 case TUINT32:
232 case TUINT64:
233 case TUINT:
234 case TUINTPTR:
235
236 case TIDEAL:
237 if !Isconst(n, CTINT) {
238 return
239 }
240 x := n.Val().U.(*Mpint)
241 if x.Cmp(minintval[TINT]) < 0 || x.Cmp(maxintval[TINT]) > 0 {
242 return
243 }
244
245 t = types.Types[TINT]
246 default:
247 return
248 }
249 Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(t), n.Int64())
250 }
251
252 func dumpglobls() {
253
254 for _, n := range externdcl {
255 switch n.Op {
256 case ONAME:
257 dumpGlobal(n)
258 case OLITERAL:
259 dumpGlobalConst(n)
260 }
261 }
262
263 sort.Slice(funcsyms, func(i, j int) bool {
264 return funcsyms[i].LinksymName() < funcsyms[j].LinksymName()
265 })
266 for _, s := range funcsyms {
267 sf := s.Pkg.Lookup(funcsymname(s)).Linksym()
268 dsymptr(sf, 0, s.Linksym(), 0)
269 ggloblsym(sf, int32(Widthptr), obj.DUPOK|obj.RODATA)
270 }
271
272
273 funcsyms = nil
274 }
275
276
277
278
279
280 func addGCLocals() {
281 for _, s := range Ctxt.Text {
282 if s.Func == nil {
283 continue
284 }
285 for _, gcsym := range []*obj.LSym{s.Func.GCArgs, s.Func.GCLocals, s.Func.GCRegs} {
286 if gcsym != nil && !gcsym.OnList() {
287 ggloblsym(gcsym, int32(len(gcsym.P)), obj.RODATA|obj.DUPOK)
288 }
289 }
290 if x := s.Func.StackObjects; x != nil {
291 ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
292 }
293 }
294 }
295
296 func duintxx(s *obj.LSym, off int, v uint64, wid int) int {
297 if off&(wid-1) != 0 {
298 Fatalf("duintxxLSym: misaligned: v=%d wid=%d off=%d", v, wid, off)
299 }
300 s.WriteInt(Ctxt, int64(off), wid, int64(v))
301 return off + wid
302 }
303
304 func duint8(s *obj.LSym, off int, v uint8) int {
305 return duintxx(s, off, uint64(v), 1)
306 }
307
308 func duint16(s *obj.LSym, off int, v uint16) int {
309 return duintxx(s, off, uint64(v), 2)
310 }
311
312 func duint32(s *obj.LSym, off int, v uint32) int {
313 return duintxx(s, off, uint64(v), 4)
314 }
315
316 func duintptr(s *obj.LSym, off int, v uint64) int {
317 return duintxx(s, off, v, Widthptr)
318 }
319
320 func dbvec(s *obj.LSym, off int, bv bvec) int {
321
322 for j := 0; int32(j) < bv.n; j += 8 {
323 word := bv.b[j/32]
324 off = duint8(s, off, uint8(word>>(uint(j)%32)))
325 }
326 return off
327 }
328
329 func stringsym(pos src.XPos, s string) (data *obj.LSym) {
330 var symname string
331 if len(s) > 100 {
332
333
334
335 h := sha256.New()
336 io.WriteString(h, s)
337 symname = fmt.Sprintf(".gostring.%d.%x", len(s), h.Sum(nil))
338 } else {
339
340 symname = strconv.Quote(s)
341 }
342
343 const prefix = "go.string."
344 symdataname := prefix + symname
345
346 symdata := Ctxt.Lookup(symdataname)
347
348 if !symdata.SeenGlobl() {
349
350 off := dsname(symdata, 0, s, pos, "string")
351 ggloblsym(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
352 }
353
354 return symdata
355 }
356
357 var slicebytes_gen int
358
359 func slicebytes(nam *Node, s string, len int) {
360 slicebytes_gen++
361 symname := fmt.Sprintf(".gobytes.%d", slicebytes_gen)
362 sym := localpkg.Lookup(symname)
363 sym.Def = asTypesNode(newname(sym))
364
365 lsym := sym.Linksym()
366 off := dsname(lsym, 0, s, nam.Pos, "slice")
367 ggloblsym(lsym, int32(off), obj.NOPTR|obj.LOCAL)
368
369 if nam.Op != ONAME {
370 Fatalf("slicebytes %v", nam)
371 }
372 nsym := nam.Sym.Linksym()
373 off = int(nam.Xoffset)
374 off = dsymptr(nsym, off, lsym, 0)
375 off = duintptr(nsym, off, uint64(len))
376 duintptr(nsym, off, uint64(len))
377 }
378
379 func dsname(s *obj.LSym, off int, t string, pos src.XPos, what string) int {
380
381
382
383 if int64(len(t)) > 2e9 {
384 yyerrorl(pos, "%v with length %v is too big", what, len(t))
385 return 0
386 }
387
388 s.WriteString(Ctxt, int64(off), len(t), t)
389 return off + len(t)
390 }
391
392 func dsymptr(s *obj.LSym, off int, x *obj.LSym, xoff int) int {
393 off = int(Rnd(int64(off), int64(Widthptr)))
394 s.WriteAddr(Ctxt, int64(off), Widthptr, x, int64(xoff))
395 off += Widthptr
396 return off
397 }
398
399 func dsymptrOff(s *obj.LSym, off int, x *obj.LSym) int {
400 s.WriteOff(Ctxt, int64(off), x, 0)
401 off += 4
402 return off
403 }
404
405 func dsymptrWeakOff(s *obj.LSym, off int, x *obj.LSym) int {
406 s.WriteWeakOff(Ctxt, int64(off), x, 0)
407 off += 4
408 return off
409 }
410
411 func gdata(nam *Node, nr *Node, wid int) {
412 if nam.Op != ONAME {
413 Fatalf("gdata nam op %v", nam.Op)
414 }
415 if nam.Sym == nil {
416 Fatalf("gdata nil nam sym")
417 }
418 s := nam.Sym.Linksym()
419
420 switch nr.Op {
421 case OLITERAL:
422 switch u := nr.Val().U.(type) {
423 case bool:
424 i := int64(obj.Bool2int(u))
425 s.WriteInt(Ctxt, nam.Xoffset, wid, i)
426
427 case *Mpint:
428 s.WriteInt(Ctxt, nam.Xoffset, wid, u.Int64())
429
430 case *Mpflt:
431 f := u.Float64()
432 switch nam.Type.Etype {
433 case TFLOAT32:
434 s.WriteFloat32(Ctxt, nam.Xoffset, float32(f))
435 case TFLOAT64:
436 s.WriteFloat64(Ctxt, nam.Xoffset, f)
437 }
438
439 case *Mpcplx:
440 r := u.Real.Float64()
441 i := u.Imag.Float64()
442 switch nam.Type.Etype {
443 case TCOMPLEX64:
444 s.WriteFloat32(Ctxt, nam.Xoffset, float32(r))
445 s.WriteFloat32(Ctxt, nam.Xoffset+4, float32(i))
446 case TCOMPLEX128:
447 s.WriteFloat64(Ctxt, nam.Xoffset, r)
448 s.WriteFloat64(Ctxt, nam.Xoffset+8, i)
449 }
450
451 case string:
452 symdata := stringsym(nam.Pos, u)
453 s.WriteAddr(Ctxt, nam.Xoffset, Widthptr, symdata, 0)
454 s.WriteInt(Ctxt, nam.Xoffset+int64(Widthptr), Widthptr, int64(len(u)))
455
456 default:
457 Fatalf("gdata unhandled OLITERAL %v", nr)
458 }
459
460 case OADDR:
461 if nr.Left.Op != ONAME {
462 Fatalf("gdata ADDR left op %v", nr.Left.Op)
463 }
464 to := nr.Left
465 s.WriteAddr(Ctxt, nam.Xoffset, wid, to.Sym.Linksym(), to.Xoffset)
466
467 case ONAME:
468 if nr.Class() != PFUNC {
469 Fatalf("gdata NAME not PFUNC %d", nr.Class())
470 }
471 s.WriteAddr(Ctxt, nam.Xoffset, wid, funcsym(nr.Sym).Linksym(), nr.Xoffset)
472
473 default:
474 Fatalf("gdata unhandled op %v %v\n", nr, nr.Op)
475 }
476 }
477
View as plain text