Files
wazero/internal/engine/wazevo/backend/isa/arm64/unwind_stack.go
2024-06-18 13:01:46 -07:00

90 lines
2.7 KiB
Go

package arm64
import (
"encoding/binary"
"reflect"
"unsafe"
"github.com/tetratelabs/wazero/internal/wasmdebug"
)
// UnwindStack implements wazevo.unwindStack.
func UnwindStack(sp, _, top uintptr, returnAddresses []uintptr) []uintptr {
l := int(top - sp)
var stackBuf []byte
{
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&stackBuf))
hdr.Data = sp
hdr.Len = l
hdr.Cap = l
}
for i := uint64(0); i < uint64(l); {
// (high address)
// +-----------------+
// | ....... |
// | ret Y | <----+
// | ....... | |
// | ret 0 | |
// | arg X | | size_of_arg_ret
// | ....... | |
// | arg 1 | |
// | arg 0 | <----+
// | size_of_arg_ret |
// | ReturnAddress |
// +-----------------+ <----+
// | ........... | |
// | spill slot M | |
// | ............ | |
// | spill slot 2 | |
// | spill slot 1 | | frame size
// | spill slot 1 | |
// | clobbered N | |
// | ............ | |
// | clobbered 0 | <----+
// | xxxxxx | ;; unused space to make it 16-byte aligned.
// | frame_size |
// +-----------------+ <---- SP
// (low address)
frameSize := binary.LittleEndian.Uint64(stackBuf[i:])
i += frameSize +
16 // frame size + aligned space.
retAddr := binary.LittleEndian.Uint64(stackBuf[i:])
i += 8 // ret addr.
sizeOfArgRet := binary.LittleEndian.Uint64(stackBuf[i:])
i += 8 + sizeOfArgRet
returnAddresses = append(returnAddresses, uintptr(retAddr))
if len(returnAddresses) == wasmdebug.MaxFrames {
break
}
}
return returnAddresses
}
// GoCallStackView implements wazevo.goCallStackView.
func GoCallStackView(stackPointerBeforeGoCall *uint64) []uint64 {
// (high address)
// +-----------------+ <----+
// | xxxxxxxxxxx | | ;; optional unused space to make it 16-byte aligned.
// ^ | arg[N]/ret[M] | |
// sliceSize | | ............ | | sliceSize
// | | arg[1]/ret[1] | |
// v | arg[0]/ret[0] | <----+
// | sliceSize |
// | frame_size |
// +-----------------+ <---- stackPointerBeforeGoCall
// (low address)
ptr := unsafe.Pointer(stackPointerBeforeGoCall)
size := *(*uint64)(unsafe.Add(ptr, 8))
var view []uint64
{
sh := (*reflect.SliceHeader)(unsafe.Pointer(&view))
sh.Data = uintptr(unsafe.Add(ptr, 16)) // skips the (frame_size, sliceSize).
sh.Len = int(size)
sh.Cap = int(size)
}
return view
}