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