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