github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/backend/isa/arm64/unwind_stack_test.go (about) 1 package arm64 2 3 import ( 4 "encoding/binary" 5 "testing" 6 "unsafe" 7 8 "github.com/wasilibs/wazerox/internal/testing/require" 9 ) 10 11 func TestUnwindStack(t *testing.T) { 12 for _, tc := range []struct { 13 name string 14 contents []uint64 15 exp []uintptr 16 }{ 17 { 18 name: "top / with frame and arg-ret-space", 19 contents: []uint64{ 20 32, // Frame size: 16 byte-aligned. 21 0, // reserved. 22 0xffffffffffffffff, // in frame. 23 0xffffffffffffffff, // in frame. 24 0xffffffffffffffff, // in frame. 25 0xffffffffffffffff, // in frame. 26 0xaa, // return address. 27 48, // size_of_arg_ret: 16-byte aligned. 28 0xeeeeeeeeeeeeeeee, // in arg-ret space. 29 0xeeeeeeeeeeeeeeee, // in arg-ret space. 30 0xeeeeeeeeeeeeeeee, // in arg-ret space. 31 0xeeeeeeeeeeeeeeee, // in arg-ret space. 32 0xeeeeeeeeeeeeeeee, // in arg-ret space. 33 0xeeeeeeeeeeeeeeee, // in arg-ret space. 34 }, 35 exp: []uintptr{0xaa}, 36 }, 37 { 38 name: "top / without frame / with arg-ret-space", 39 contents: []uint64{ 40 0, // Frame size: 16 byte-aligned. 41 0, // reserved. 42 0xaa, // return address. 43 48, // size_of_arg_ret: 16-byte aligned. 44 0xeeeeeeeeeeeeeeee, // in arg-ret space. 45 0xeeeeeeeeeeeeeeee, // in arg-ret space. 46 0xeeeeeeeeeeeeeeee, // in arg-ret space. 47 0xeeeeeeeeeeeeeeee, // in arg-ret space. 48 0xeeeeeeeeeeeeeeee, // in arg-ret space. 49 0xeeeeeeeeeeeeeeee, // in arg-ret space. 50 }, 51 exp: []uintptr{0xaa}, 52 }, 53 { 54 name: "top / without frame and arg-ret-space", 55 contents: []uint64{ 56 0, // Frame size: 16 byte-aligned. 57 0, // reserved. 58 0xaa, // return address. 59 0, // size_of_arg_ret: 16-byte aligned. 60 }, 61 exp: []uintptr{0xaa}, 62 }, 63 { 64 name: "three frames", 65 contents: []uint64{ 66 // ------------ first frame ------------- 67 32, // Frame size: 16 byte-aligned. 68 0, // reserved. 69 0xffffffffffffffff, // in frame. 70 0xffffffffffffffff, // in frame. 71 0xffffffffffffffff, // in frame. 72 0xffffffffffffffff, // in frame. 73 0xaa, // return address. 74 48, // size_of_arg_ret: 16-byte aligned. 75 0xeeeeeeeeeeeeeeee, // in arg-ret space. 76 0xeeeeeeeeeeeeeeee, // in arg-ret space. 77 0xeeeeeeeeeeeeeeee, // in arg-ret space. 78 0xeeeeeeeeeeeeeeee, // in arg-ret space. 79 0xeeeeeeeeeeeeeeee, // in arg-ret space. 80 0xeeeeeeeeeeeeeeee, // in arg-ret space. 81 // ------------ second frame ----------------- 82 0, // Frame size: 16 byte-aligned. 83 0, // reserved. 84 0xbb, // return address. 85 48, // size_of_arg_ret: 16-byte aligned. 86 0xeeeeeeeeeeeeeeee, // in arg-ret space. 87 0xeeeeeeeeeeeeeeee, // in arg-ret space. 88 0xeeeeeeeeeeeeeeee, // in arg-ret space. 89 0xeeeeeeeeeeeeeeee, // in arg-ret space. 90 0xeeeeeeeeeeeeeeee, // in arg-ret space. 91 0xeeeeeeeeeeeeeeee, // in arg-ret space. 92 // ------------ third frame ----------------- 93 0, // Frame size: 16 byte-aligned. 94 0, // reserved. 95 0xcc, // return address. 96 0, // size_of_arg_ret: 16-byte aligned. 97 }, 98 exp: []uintptr{0xaa, 0xbb, 0xcc}, 99 }, 100 } { 101 tc := tc 102 t.Run(tc.name, func(t *testing.T) { 103 buf := make([]byte, len(tc.contents)*8+1) 104 for i, v := range tc.contents { 105 binary.LittleEndian.PutUint64(buf[i*8:], v) 106 } 107 sp := uintptr(unsafe.Pointer(&buf[0])) 108 returnAddresses := UnwindStack(sp, uintptr(unsafe.Pointer(&buf[len(buf)-1])), nil) 109 require.Equal(t, tc.exp, returnAddresses) 110 }) 111 } 112 }