| 82 | #define UWOP_PUSH_MACHFRAME 10 |
| 83 | |
| 84 | static TArray<uint16_t> CreateUnwindInfoWindows(asmjit::CCFunc *func) |
| 85 | { |
| 86 | using namespace asmjit; |
| 87 | FuncFrameLayout layout; |
| 88 | Error error = layout.init(func->getDetail(), func->getFrameInfo()); |
| 89 | if (error != kErrorOk) |
| 90 | I_Error("FuncFrameLayout.init failed"); |
| 91 | |
| 92 | // We need a dummy emitter for instruction size calculations |
| 93 | CodeHolder code; |
| 94 | code.init(GetHostCodeInfo()); |
| 95 | X86Assembler assembler(&code); |
| 96 | X86Emitter *emitter = assembler.asEmitter(); |
| 97 | |
| 98 | // Build UNWIND_CODE codes: |
| 99 | |
| 100 | TArray<uint16_t> codes; |
| 101 | uint32_t opoffset, opcode, opinfo; |
| 102 | |
| 103 | // Note: this must match exactly what X86Internal::emitProlog does |
| 104 | |
| 105 | X86Gp zsp = emitter->zsp(); // ESP|RSP register. |
| 106 | X86Gp zbp = emitter->zsp(); // EBP|RBP register. |
| 107 | zbp.setId(X86Gp::kIdBp); |
| 108 | X86Gp gpReg = emitter->zsp(); // General purpose register (temporary). |
| 109 | X86Gp saReg = emitter->zsp(); // Stack-arguments base register. |
| 110 | uint32_t gpSaved = layout.getSavedRegs(X86Reg::kKindGp); |
| 111 | |
| 112 | if (layout.hasPreservedFP()) |
| 113 | { |
| 114 | // Emit: 'push zbp' |
| 115 | // 'mov zbp, zsp'. |
| 116 | gpSaved &= ~Utils::mask(X86Gp::kIdBp); |
| 117 | emitter->push(zbp); |
| 118 | |
| 119 | opoffset = (uint32_t)assembler.getOffset(); |
| 120 | opcode = UWOP_PUSH_NONVOL; |
| 121 | opinfo = X86Gp::kIdBp; |
| 122 | codes.Push(opoffset | (opcode << 8) | (opinfo << 12)); |
| 123 | |
| 124 | emitter->mov(zbp, zsp); |
| 125 | } |
| 126 | |
| 127 | if (gpSaved) |
| 128 | { |
| 129 | for (uint32_t i = gpSaved, regId = 0; i; i >>= 1, regId++) |
| 130 | { |
| 131 | if (!(i & 0x1)) continue; |
| 132 | // Emit: 'push gp' sequence. |
| 133 | gpReg.setId(regId); |
| 134 | emitter->push(gpReg); |
| 135 | |
| 136 | opoffset = (uint32_t)assembler.getOffset(); |
| 137 | opcode = UWOP_PUSH_NONVOL; |
| 138 | opinfo = regId; |
| 139 | codes.Push(opoffset | (opcode << 8) | (opinfo << 12)); |
| 140 | } |
| 141 | } |
no test coverage detected