1
2
3
4
5 package gc
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/noder"
11 "cmd/compile/internal/objw"
12 "cmd/compile/internal/reflectdata"
13 "cmd/compile/internal/staticdata"
14 "cmd/compile/internal/typecheck"
15 "cmd/compile/internal/types"
16 "cmd/internal/archive"
17 "cmd/internal/bio"
18 "cmd/internal/obj"
19 "cmd/internal/objabi"
20 "encoding/json"
21 "fmt"
22 )
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 const (
38 modeCompilerObj = 1 << iota
39 modeLinkerObj
40 )
41
42 func dumpobj() {
43 if base.Flag.LinkObj == "" {
44 dumpobj1(base.Flag.LowerO, modeCompilerObj|modeLinkerObj)
45 return
46 }
47 dumpobj1(base.Flag.LowerO, modeCompilerObj)
48 dumpobj1(base.Flag.LinkObj, modeLinkerObj)
49 }
50
51 func dumpobj1(outfile string, mode int) {
52 bout, err := bio.Create(outfile)
53 if err != nil {
54 base.FlushErrors()
55 fmt.Printf("can't create %s: %v\n", outfile, err)
56 base.ErrorExit()
57 }
58 defer bout.Close()
59 bout.WriteString("!<arch>\n")
60
61 if mode&modeCompilerObj != 0 {
62 start := startArchiveEntry(bout)
63 dumpCompilerObj(bout)
64 finishArchiveEntry(bout, start, "__.PKGDEF")
65 }
66 if mode&modeLinkerObj != 0 {
67 start := startArchiveEntry(bout)
68 dumpLinkerObj(bout)
69 finishArchiveEntry(bout, start, "_go_.o")
70 }
71 }
72
73 func printObjHeader(bout *bio.Writer) {
74 bout.WriteString(objabi.HeaderString())
75 if base.Flag.BuildID != "" {
76 fmt.Fprintf(bout, "build id %q\n", base.Flag.BuildID)
77 }
78 if types.LocalPkg.Name == "main" {
79 fmt.Fprintf(bout, "main\n")
80 }
81 fmt.Fprintf(bout, "\n")
82 }
83
84 func startArchiveEntry(bout *bio.Writer) int64 {
85 var arhdr [archive.HeaderSize]byte
86 bout.Write(arhdr[:])
87 return bout.Offset()
88 }
89
90 func finishArchiveEntry(bout *bio.Writer, start int64, name string) {
91 bout.Flush()
92 size := bout.Offset() - start
93 if size&1 != 0 {
94 bout.WriteByte(0)
95 }
96 bout.MustSeek(start-archive.HeaderSize, 0)
97
98 var arhdr [archive.HeaderSize]byte
99 archive.FormatHeader(arhdr[:], name, size)
100 bout.Write(arhdr[:])
101 bout.Flush()
102 bout.MustSeek(start+size+(size&1), 0)
103 }
104
105 func dumpCompilerObj(bout *bio.Writer) {
106 printObjHeader(bout)
107 noder.WriteExports(bout)
108 }
109
110 func dumpdata() {
111 numExterns := len(typecheck.Target.Externs)
112 numDecls := len(typecheck.Target.Decls)
113
114 dumpglobls(typecheck.Target.Externs)
115 reflectdata.CollectPTabs()
116 numExports := len(typecheck.Target.Exports)
117 addsignats(typecheck.Target.Externs)
118 reflectdata.WriteRuntimeTypes()
119 reflectdata.WriteTabs()
120 numPTabs := reflectdata.CountPTabs()
121 reflectdata.WriteImportStrings()
122 reflectdata.WriteBasicTypes()
123 dumpembeds()
124
125
126
127
128
129
130
131
132 for {
133 for i := numDecls; i < len(typecheck.Target.Decls); i++ {
134 if n, ok := typecheck.Target.Decls[i].(*ir.Func); ok {
135 enqueueFunc(n)
136 }
137 }
138 numDecls = len(typecheck.Target.Decls)
139 compileFunctions()
140 reflectdata.WriteRuntimeTypes()
141 if numDecls == len(typecheck.Target.Decls) {
142 break
143 }
144 }
145
146
147 dumpglobls(typecheck.Target.Externs[numExterns:])
148
149 if reflectdata.ZeroSize > 0 {
150 zero := base.PkgLinksym("go.map", "zero", obj.ABI0)
151 objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
152 zero.Set(obj.AttrStatic, true)
153 }
154
155 staticdata.WriteFuncSyms()
156 addGCLocals()
157
158 if numExports != len(typecheck.Target.Exports) {
159 base.Fatalf("Target.Exports changed after compile functions loop")
160 }
161 newNumPTabs := reflectdata.CountPTabs()
162 if newNumPTabs != numPTabs {
163 base.Fatalf("ptabs changed after compile functions loop")
164 }
165 }
166
167 func dumpLinkerObj(bout *bio.Writer) {
168 printObjHeader(bout)
169
170 if len(typecheck.Target.CgoPragmas) != 0 {
171
172 fmt.Fprintf(bout, "\n$$\n\n$$\n\n")
173 fmt.Fprintf(bout, "\n$$ // cgo\n")
174 if err := json.NewEncoder(bout).Encode(typecheck.Target.CgoPragmas); err != nil {
175 base.Fatalf("serializing pragcgobuf: %v", err)
176 }
177 fmt.Fprintf(bout, "\n$$\n\n")
178 }
179
180 fmt.Fprintf(bout, "\n!\n")
181
182 obj.WriteObjFile(base.Ctxt, bout)
183 }
184
185 func dumpGlobal(n *ir.Name) {
186 if n.Type() == nil {
187 base.Fatalf("external %v nil type\n", n)
188 }
189 if n.Class == ir.PFUNC {
190 return
191 }
192 if n.Sym().Pkg != types.LocalPkg {
193 return
194 }
195 types.CalcSize(n.Type())
196 ggloblnod(n)
197 base.Ctxt.DwarfGlobal(base.Ctxt.Pkgpath, types.TypeSymName(n.Type()), n.Linksym())
198 }
199
200 func dumpGlobalConst(n ir.Node) {
201
202 t := n.Type()
203 if t == nil {
204 return
205 }
206 if n.Sym().Pkg != types.LocalPkg {
207 return
208 }
209
210 if !t.IsInteger() {
211 return
212 }
213 v := n.Val()
214 if t.IsUntyped() {
215
216 t = types.Types[types.TINT]
217 if ir.ConstOverflow(v, t) {
218 return
219 }
220 } else {
221
222
223 _ = reflectdata.TypeLinksym(t)
224 }
225 base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
226 }
227
228 func dumpglobls(externs []ir.Node) {
229
230 for _, n := range externs {
231 switch n.Op() {
232 case ir.ONAME:
233 dumpGlobal(n.(*ir.Name))
234 case ir.OLITERAL:
235 dumpGlobalConst(n)
236 }
237 }
238 }
239
240
241
242
243
244 func addGCLocals() {
245 for _, s := range base.Ctxt.Text {
246 fn := s.Func()
247 if fn == nil {
248 continue
249 }
250 for _, gcsym := range []*obj.LSym{fn.GCArgs, fn.GCLocals} {
251 if gcsym != nil && !gcsym.OnList() {
252 objw.Global(gcsym, int32(len(gcsym.P)), obj.RODATA|obj.DUPOK)
253 }
254 }
255 if x := fn.StackObjects; x != nil {
256 objw.Global(x, int32(len(x.P)), obj.RODATA)
257 x.Set(obj.AttrStatic, true)
258 }
259 if x := fn.OpenCodedDeferInfo; x != nil {
260 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
261 }
262 if x := fn.ArgInfo; x != nil {
263 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
264 x.Set(obj.AttrStatic, true)
265 }
266 if x := fn.ArgLiveInfo; x != nil {
267 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
268 x.Set(obj.AttrStatic, true)
269 }
270 if x := fn.WrapInfo; x != nil && !x.OnList() {
271 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
272 x.Set(obj.AttrStatic, true)
273 }
274 }
275 }
276
277 func ggloblnod(nam *ir.Name) {
278 s := nam.Linksym()
279 s.Gotype = reflectdata.TypeLinksym(nam.Type())
280 flags := 0
281 if nam.Readonly() {
282 flags = obj.RODATA
283 }
284 if nam.Type() != nil && !nam.Type().HasPointers() {
285 flags |= obj.NOPTR
286 }
287 base.Ctxt.Globl(s, nam.Type().Size(), flags)
288 if nam.LibfuzzerExtraCounter() {
289 s.Type = objabi.SLIBFUZZER_EXTRA_COUNTER
290 }
291 if nam.Sym().Linkname != "" {
292
293
294
295 s.Pkg = "_"
296 }
297 }
298
299 func dumpembeds() {
300 for _, v := range typecheck.Target.Embeds {
301 staticdata.WriteEmbed(v)
302 }
303 }
304
305 func addsignats(dcls []ir.Node) {
306
307 for _, n := range dcls {
308 if n.Op() == ir.OTYPE {
309 reflectdata.NeedRuntimeType(n.Type())
310 }
311 }
312 }
313
View as plain text