Source file
src/runtime/stkframe.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/goarch"
10 "internal/runtime/sys"
11 "unsafe"
12 )
13
14
15 type stkframe struct {
16
17
18 fn funcInfo
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 pc uintptr
45
46
47
48
49
50
51
52
53
54 continpc uintptr
55
56 lr uintptr
57 sp uintptr
58 fp uintptr
59 varp uintptr
60 argp uintptr
61 }
62
63
64
65 type reflectMethodValue struct {
66 fn uintptr
67 stack *bitvector
68 argLen uintptr
69 }
70
71
72 func (frame *stkframe) argBytes() uintptr {
73 if frame.fn.args != abi.ArgsSizeUnknown {
74 return uintptr(frame.fn.args)
75 }
76
77
78 argMap, _ := frame.argMapInternal()
79 return uintptr(argMap.n) * goarch.PtrSize
80 }
81
82
83
84
85
86
87
88
89
90
91
92
93
94 func (frame *stkframe) argMapInternal() (argMap bitvector, hasReflectStackObj bool) {
95 f := frame.fn
96 if f.args != abi.ArgsSizeUnknown {
97 argMap.n = f.args / goarch.PtrSize
98 return
99 }
100
101 switch funcname(f) {
102 case "reflect.makeFuncStub", "reflect.methodValueCall":
103
104
105
106 arg0 := frame.sp + sys.MinFrameSize
107
108 minSP := frame.fp
109 if !usesLR {
110
111
112 minSP -= goarch.PtrSize
113 }
114 if arg0 >= minSP {
115
116
117
118
119
120
121
122
123
124
125
126 if frame.pc != f.entry() {
127 print("runtime: confused by ", funcname(f), ": no frame (sp=", hex(frame.sp), " fp=", hex(frame.fp), ") at entry+", hex(frame.pc-f.entry()), "\n")
128 throw("reflect mismatch")
129 }
130 return bitvector{}, false
131 }
132 hasReflectStackObj = true
133 mv := *(**reflectMethodValue)(unsafe.Pointer(arg0))
134
135
136
137 retValid := *(*bool)(unsafe.Pointer(arg0 + 4*goarch.PtrSize))
138 if mv.fn != f.entry() {
139 print("runtime: confused by ", funcname(f), "\n")
140 throw("reflect mismatch")
141 }
142 argMap = *mv.stack
143 if !retValid {
144
145
146 n := int32((mv.argLen &^ (goarch.PtrSize - 1)) / goarch.PtrSize)
147 if n < argMap.n {
148 argMap.n = n
149 }
150 }
151 }
152 return
153 }
154
155
156
157 func (frame *stkframe) getStackMap(debug bool) (locals, args bitvector, objs []stackObjectRecord) {
158 targetpc := frame.continpc
159 if targetpc == 0 {
160
161 return
162 }
163
164 f := frame.fn
165 pcdata := int32(-1)
166 if targetpc != f.entry() {
167
168
169
170
171 targetpc--
172 pcdata = pcdatavalue(f, abi.PCDATA_StackMapIndex, targetpc)
173 }
174 if pcdata == -1 {
175
176
177
178 pcdata = 0
179 }
180
181
182 size := frame.varp - frame.sp
183 var minsize uintptr
184 switch goarch.ArchFamily {
185 case goarch.ARM64:
186 minsize = sys.StackAlign
187 default:
188 minsize = sys.MinFrameSize
189 }
190 if size > minsize {
191 stackid := pcdata
192 stkmap := (*stackmap)(funcdata(f, abi.FUNCDATA_LocalsPointerMaps))
193 if stkmap == nil || stkmap.n <= 0 {
194 print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
195 throw("missing stackmap")
196 }
197
198 if stkmap.nbit > 0 {
199 if stackid < 0 || stackid >= stkmap.n {
200
201 print("runtime: pcdata is ", stackid, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
202 throw("bad symbol table")
203 }
204 locals = stackmapdata(stkmap, stackid)
205 if stackDebug >= 3 && debug {
206 print(" locals ", stackid, "/", stkmap.n, " ", locals.n, " words ", locals.bytedata, "\n")
207 }
208 } else if stackDebug >= 3 && debug {
209 print(" no locals to adjust\n")
210 }
211 }
212
213
214 var isReflect bool
215 args, isReflect = frame.argMapInternal()
216 if args.n > 0 && args.bytedata == nil {
217
218
219 stackmap := (*stackmap)(funcdata(f, abi.FUNCDATA_ArgsPointerMaps))
220 if stackmap == nil || stackmap.n <= 0 {
221 print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(args.n*goarch.PtrSize), "\n")
222 throw("missing stackmap")
223 }
224 if pcdata < 0 || pcdata >= stackmap.n {
225
226 print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", hex(targetpc), ")\n")
227 throw("bad symbol table")
228 }
229 if stackmap.nbit == 0 {
230 args.n = 0
231 } else {
232 args = stackmapdata(stackmap, pcdata)
233 }
234 }
235
236
237 if (GOARCH == "amd64" || GOARCH == "arm64" || GOARCH == "loong64" || GOARCH == "ppc64" || GOARCH == "ppc64le" || GOARCH == "riscv64") &&
238 unsafe.Sizeof(abi.RegArgs{}) > 0 && isReflect {
239
240
241
242
243 objs = methodValueCallFrameObjs[:]
244 } else {
245 p := funcdata(f, abi.FUNCDATA_StackObjects)
246 if p != nil {
247 n := *(*uintptr)(p)
248 p = add(p, goarch.PtrSize)
249 r0 := (*stackObjectRecord)(noescape(p))
250 objs = unsafe.Slice(r0, int(n))
251
252
253
254
255
256 }
257 }
258
259 return
260 }
261
262 var methodValueCallFrameObjs [1]stackObjectRecord
263
264 func stkobjinit() {
265 var abiRegArgsEface any = abi.RegArgs{}
266 abiRegArgsType := efaceOf(&abiRegArgsEface)._type
267 if abiRegArgsType.Kind_&abi.KindGCProg != 0 {
268 throw("abiRegArgsType needs GC Prog, update methodValueCallFrameObjs")
269 }
270
271
272 ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0]))
273 var mod *moduledata
274 for datap := &firstmoduledata; datap != nil; datap = datap.next {
275 if datap.gofunc <= ptr && ptr < datap.end {
276 mod = datap
277 break
278 }
279 }
280 if mod == nil {
281 throw("methodValueCallFrameObjs is not in a module")
282 }
283 methodValueCallFrameObjs[0] = stackObjectRecord{
284 off: -int32(alignUp(abiRegArgsType.Size_, 8)),
285 size: int32(abiRegArgsType.Size_),
286 _ptrdata: int32(abiRegArgsType.PtrBytes),
287 gcdataoff: uint32(uintptr(unsafe.Pointer(abiRegArgsType.GCData)) - mod.rodata),
288 }
289 }
290
View as plain text