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  }