github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/backend/isa/arm64/unwind_stack.go (about) 1 package arm64 2 3 import ( 4 "encoding/binary" 5 "reflect" 6 "unsafe" 7 8 "github.com/tetratelabs/wazero/internal/wasmdebug" 9 ) 10 11 // UnwindStack implements wazevo.unwindStack. 12 func UnwindStack(sp, _, top uintptr, returnAddresses []uintptr) []uintptr { 13 l := int(top - sp) 14 15 var stackBuf []byte 16 { 17 // TODO: use unsafe.Slice after floor version is set to Go 1.20. 18 hdr := (*reflect.SliceHeader)(unsafe.Pointer(&stackBuf)) 19 hdr.Data = sp 20 hdr.Len = l 21 hdr.Cap = l 22 } 23 24 for i := uint64(0); i < uint64(l); { 25 // (high address) 26 // +-----------------+ 27 // | ....... | 28 // | ret Y | <----+ 29 // | ....... | | 30 // | ret 0 | | 31 // | arg X | | size_of_arg_ret 32 // | ....... | | 33 // | arg 1 | | 34 // | arg 0 | <----+ 35 // | size_of_arg_ret | 36 // | ReturnAddress | 37 // +-----------------+ <----+ 38 // | ........... | | 39 // | spill slot M | | 40 // | ............ | | 41 // | spill slot 2 | | 42 // | spill slot 1 | | frame size 43 // | spill slot 1 | | 44 // | clobbered N | | 45 // | ............ | | 46 // | clobbered 0 | <----+ 47 // | xxxxxx | ;; unused space to make it 16-byte aligned. 48 // | frame_size | 49 // +-----------------+ <---- SP 50 // (low address) 51 52 frameSize := binary.LittleEndian.Uint64(stackBuf[i:]) 53 i += frameSize + 54 16 // frame size + aligned space. 55 retAddr := binary.LittleEndian.Uint64(stackBuf[i:]) 56 i += 8 // ret addr. 57 sizeOfArgRet := binary.LittleEndian.Uint64(stackBuf[i:]) 58 i += 8 + sizeOfArgRet 59 returnAddresses = append(returnAddresses, uintptr(retAddr)) 60 if len(returnAddresses) == wasmdebug.MaxFrames { 61 break 62 } 63 } 64 return returnAddresses 65 } 66 67 // GoCallStackView implements wazevo.goCallStackView. 68 func GoCallStackView(stackPointerBeforeGoCall *uint64) []uint64 { 69 // (high address) 70 // +-----------------+ <----+ 71 // | xxxxxxxxxxx | | ;; optional unused space to make it 16-byte aligned. 72 // ^ | arg[N]/ret[M] | | 73 // sliceSize | | ............ | | sliceSize 74 // | | arg[1]/ret[1] | | 75 // v | arg[0]/ret[0] | <----+ 76 // | sliceSize | 77 // | frame_size | 78 // +-----------------+ <---- stackPointerBeforeGoCall 79 // (low address) 80 ptr := unsafe.Pointer(stackPointerBeforeGoCall) 81 size := *(*uint64)(unsafe.Add(ptr, 8)) 82 var view []uint64 83 { 84 sh := (*reflect.SliceHeader)(unsafe.Pointer(&view)) 85 sh.Data = uintptr(unsafe.Add(ptr, 16)) // skips the (frame_size, sliceSize). 86 sh.Len = int(size) 87 sh.Cap = int(size) 88 } 89 return view 90 }