Skip to content

Commit e769615

Browse files
authored
Merge pull request cch123#39 from wziww/master
panic - recover 补充
2 parents 1d5670b + f4e3e64 commit e769615

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

panic.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,105 @@ TEXT runtime·gogo(SB), NOSPLIT, $16-8
194194
```
195195

196196
这样所有流程就都打通了。
197+
198+
---
199+
200+
同样需要注意的是, 如多次`panic(defer)`后再利用`recover`恢复后获取到的`panic`信息仅仅为最近一次的信息, 是获取不了`_panic`整个链表中记录的所有信息的, 如果坚持想这样做, 那只能从 TLS 中获取当前的上下文, 通过基址加变址寻址的方式从当前的`g`中来获取`_panic`信息
201+
202+
go 1.14.3 为例:
203+
```assembly
204+
#include "textflag.h"
205+
// main.s
206+
// func GetPanicPtr() uintptr
207+
TEXT ·GetPanicPtr(SB), NOSPLIT, $0-8
208+
MOVQ TLS, CX
209+
MOVQ 0(CX)(TLS*1), AX
210+
MOVQ $32, BX // 32 根据不同版本 type g struct 中 _panic 字段计算偏移量即可
211+
LEAQ 0(AX)(BX*1), DX
212+
MOVQ (DX), AX
213+
MOVQ AX, ret+0(FP)
214+
RET
215+
```
216+
```go
217+
// main.go
218+
package main
219+
220+
import (
221+
"fmt"
222+
"unsafe"
223+
)
224+
225+
func GetPanicPtr() uintptr
226+
227+
type gobuf struct {
228+
// The offsets of sp, pc, and g are known to (hard-coded in) libmach.
229+
//
230+
// ctxt is unusual with respect to GC: it may be a
231+
// heap-allocated funcval, so GC needs to track it, but it
232+
// needs to be set and cleared from assembly, where it's
233+
// difficult to have write barriers. However, ctxt is really a
234+
// saved, live register, and we only ever exchange it between
235+
// the real register and the gobuf. Hence, we treat it as a
236+
// root during stack scanning, which means assembly that saves
237+
// and restores it doesn't need write barriers. It's still
238+
// typed as a pointer so that any other writes from Go get
239+
// write barriers.
240+
sp uintptr
241+
pc uintptr
242+
g uintptr
243+
ctxt unsafe.Pointer
244+
ret uint64
245+
lr uintptr
246+
bp uintptr // for GOEXPERIMENT=framepointer
247+
}
248+
type stack struct {
249+
lo uintptr
250+
hi uintptr
251+
}
252+
type g struct {
253+
// Stack parameters.
254+
// stack describes the actual stack memory: [stack.lo, stack.hi).
255+
// stackguard0 is the stack pointer compared in the Go stack growth prologue.
256+
// It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
257+
// stackguard1 is the stack pointer compared in the C stack growth prologue.
258+
// It is stack.lo+StackGuard on g0 and gsignal stacks.
259+
// It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
260+
stack stack // offset known to runtime/cgo
261+
stackguard0 uintptr // offset known to liblink
262+
stackguard1 uintptr // offset known to liblink
263+
264+
_panic uintptr // innermost panic - offset known to liblink
265+
_defer uintptr // innermost defer
266+
m uintptr // current m; offset known to arm liblink
267+
sched gobuf
268+
syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc
269+
syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc
270+
stktopsp uintptr // expected sp at top of stack, to check in traceback
271+
param unsafe.Pointer // passed parameter on wakeup
272+
atomicstatus uint32
273+
stackLock uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
274+
goid int64
275+
}
276+
type _panic struct {
277+
argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
278+
arg interface{} // argument to panic
279+
link *_panic // link to earlier panic
280+
pc uintptr // where to return to in runtime if this panic is bypassed
281+
sp unsafe.Pointer // where to return to in runtime if this panic is bypassed
282+
recovered bool // whether this panic is over
283+
aborted bool // the panic was aborted
284+
goexit bool
285+
}
286+
287+
func main() {
288+
defer func() {
289+
var __panic *_panic
290+
var _panic_ptr uintptr = GetPanicPtr()
291+
__panic = (*_panic)(unsafe.Pointer(_panic_ptr))
292+
fmt.Println(__panic)
293+
}()
294+
defer panic(3)
295+
defer panic(2)
296+
panic(1)
297+
}
298+
```

0 commit comments

Comments
 (0)