90 lines
2.7 KiB
Go
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
|
|
}
|