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