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