//------------------------------------------------------------------------ // Compiler::unwindSetFrameRegCFI: Record a cfi info for a frame register set. // // Arguments: // reg - The register being set as the frame register. // offset - The offset from the current stack pointer that the frame pointer will point at. // void Compiler::unwindSetFrameRegCFI(regNumber reg, unsigned offset) { #if defined(_TARGET_ARM_) assert(compGeneratingEpilog); #else assert(compGeneratingProlog); #endif FuncInfoDsc* func = funCurrentFunc(); unsigned int cbProlog = 0; if (compGeneratingProlog) { cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); } createCfiCode(func, cbProlog, CFI_DEF_CFA_REGISTER, mapRegNumToDwarfReg(reg)); if (offset != 0) { // before: cfa = rsp + old_cfa_offset; // rbp = rsp + offset; // after: cfa should be based on rbp, but points to the old address: // rsp + old_cfa_offset == rbp + old_cfa_offset + adjust; // adjust = -offset; int adjust = -(int)offset; createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, adjust); } }
//------------------------------------------------------------------------ // Compiler::unwindPush: Record a push/save of a register. // // Arguments: // reg - The register being pushed/saved. // void Compiler::unwindPush(regNumber reg) { assert(compGeneratingProlog); FuncInfoDsc* func = funCurrentFunc(); assert(func->unwindHeader.Version == 1); // Can't call this before unwindBegProlog assert(func->unwindHeader.CountOfUnwindCodes == 0); // Can't call this after unwindReserve assert(func->unwindCodeSlot > sizeof(UNWIND_CODE)); UNWIND_CODE * code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); code->CodeOffset = (BYTE)cbProlog; if ((RBM_CALLEE_SAVED & genRegMask(reg)) #if ETW_EBP_FRAMED // In case of ETW_EBP_FRAMED defined the REG_FPBASE (RBP) // is excluded from the callee-save register list. // Make sure the register gets PUSH unwind info in this case, // since it is pushed as a frame register. || (reg == REG_FPBASE) #endif // ETW_EBP_FRAMED ) { code->UnwindOp = UWOP_PUSH_NONVOL; code->OpInfo = (BYTE)reg; } else { // Push of a volatile register is just a small stack allocation code->UnwindOp = UWOP_ALLOC_SMALL; code->OpInfo = 0; } }
void Compiler::unwindPushPopCFI(regNumber reg) { #if defined(_TARGET_ARM_) assert(compGeneratingEpilog); #else assert(compGeneratingProlog); #endif FuncInfoDsc* func = funCurrentFunc(); unsigned int cbProlog = 0; if (compGeneratingProlog) { cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, REGSIZE_BYTES == 8 ? 8 : 4); } if ((RBM_CALLEE_SAVED & genRegMask(reg)) #if defined(UNIX_AMD64_ABI) #if ETW_EBP_FRAMED // In case of ETW_EBP_FRAMED defined the REG_FPBASE (RBP) // is excluded from the callee-save register list. // Make sure the register gets PUSH unwind info in this case, // since it is pushed as a frame register. || (reg == REG_FPBASE) #endif // ETW_EBP_FRAMED #endif ) { createCfiCode(func, cbProlog, CFI_REL_OFFSET, mapRegNumToDwarfReg(reg)); } }
void Compiler::unwindAllocStackCFI(unsigned size) { assert(compGeneratingProlog); FuncInfoDsc* func = funCurrentFunc(); unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, size); }
void Compiler::unwindSaveRegCFI(regNumber reg, unsigned offset) { assert(compGeneratingProlog); if (RBM_CALLEE_SAVED & genRegMask(reg)) { FuncInfoDsc* func = funCurrentFunc(); unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); createCfiCode(func, cbProlog, CFI_REL_OFFSET, mapRegNumToDwarfReg(reg), offset); } }
void Compiler::unwindSetFrameRegCFI(regNumber reg, unsigned offset) { assert(compGeneratingProlog); FuncInfoDsc* func = funCurrentFunc(); unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); createCfiCode(func, cbProlog, CFI_DEF_CFA_REGISTER, mapRegNumToDwarfReg(reg)); if (offset != 0) { createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, offset); } }
void Compiler::unwindAllocStackCFI(unsigned size) { #if defined(_TARGET_ARM_) assert(compGeneratingEpilog); #else assert(compGeneratingProlog); #endif FuncInfoDsc* func = funCurrentFunc(); unsigned int cbProlog = 0; if (compGeneratingProlog) { cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); } createCfiCode(func, cbProlog, CFI_ADJUST_CFA_OFFSET, DWARF_REG_ILLEGAL, size); }
//------------------------------------------------------------------------ // Compiler::unwindSaveReg: Record a register save. // // Arguments: // reg - The register being saved. // offset - The offset from the current stack pointer where the register is being saved. // void Compiler::unwindSaveReg(regNumber reg, unsigned offset) { assert(compGeneratingProlog); FuncInfoDsc* func = funCurrentFunc(); assert(func->unwindHeader.Version == 1); // Can't call this before unwindBegProlog assert(func->unwindHeader.CountOfUnwindCodes == 0); // Can't call this after unwindReserve if (RBM_CALLEE_SAVED & genRegMask(reg)) { UNWIND_CODE * code; if (offset < 0x80000) { assert(func->unwindCodeSlot > (sizeof(UNWIND_CODE) + sizeof(USHORT))); USHORT * codedSize = (USHORT*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(USHORT)]; code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; // As per AMD64 ABI, if saving entire xmm reg, then offset need to be scaled by 16. if (genIsValidFloatReg(reg)) { *codedSize = (USHORT) (offset/16); code->UnwindOp = UWOP_SAVE_XMM128; } else { *codedSize = (USHORT) (offset/8); code->UnwindOp = UWOP_SAVE_NONVOL; } } else { assert(func->unwindCodeSlot > (sizeof(UNWIND_CODE) + sizeof(ULONG))); ULONG * codedSize = (ULONG*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(ULONG)]; *codedSize = offset; code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; code->UnwindOp = (genIsValidFloatReg(reg)) ? UWOP_SAVE_XMM128_FAR : UWOP_SAVE_NONVOL_FAR; } code->OpInfo = (BYTE)reg; unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); code->CodeOffset = (BYTE)cbProlog; } }
//------------------------------------------------------------------------ // Compiler::unwindSetFrameReg: Record a frame register. // // Arguments: // reg - The register being set as the frame register. // offset - The offset from the current stack pointer that the frame pointer will point at. // void Compiler::unwindSetFrameReg(regNumber reg, unsigned offset) { assert(compGeneratingProlog); FuncInfoDsc* func = funCurrentFunc(); assert(func->unwindHeader.Version == 1); // Can't call this before unwindBegProlog assert(func->unwindHeader.CountOfUnwindCodes == 0); // Can't call this after unwindReserve assert(func->unwindCodeSlot > sizeof(UNWIND_CODE)); UNWIND_CODE * code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); code->CodeOffset = (BYTE)cbProlog; code->UnwindOp = UWOP_SET_FPREG; code->OpInfo = 0; func->unwindHeader.FrameRegister = (BYTE)reg; assert(offset <= 240); assert(offset % 16 == 0); func->unwindHeader.FrameOffset = offset / 16; }
//------------------------------------------------------------------------ // Compiler::unwindAllocStack: Record a stack frame allocation (sub sp, X). // // Arguments: // size - The size of the stack frame allocation (the amount subtracted from the stack pointer). // void Compiler::unwindAllocStack(unsigned size) { assert(compGeneratingProlog); FuncInfoDsc* func = funCurrentFunc(); assert(func->unwindHeader.Version == 1); // Can't call this before unwindBegProlog assert(func->unwindHeader.CountOfUnwindCodes == 0); // Can't call this after unwindReserve assert(size % 8 == 0); // Stack size is *always* 8 byte aligned UNWIND_CODE * code; if (size <= 128) { assert(func->unwindCodeSlot > sizeof(UNWIND_CODE)); code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; code->UnwindOp = UWOP_ALLOC_SMALL; code->OpInfo = (size - 8) / 8; } else if (size <= 0x7FFF8) { assert(func->unwindCodeSlot > (sizeof(UNWIND_CODE) + sizeof(USHORT))); USHORT * codedSize = (USHORT*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(USHORT)]; *codedSize = (USHORT)(size / 8); code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; code->UnwindOp = UWOP_ALLOC_LARGE; code->OpInfo = 0; } else { assert(func->unwindCodeSlot > (sizeof(UNWIND_CODE) + sizeof(ULONG))); ULONG * codedSize = (ULONG*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(ULONG)]; *codedSize = size; code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)]; code->UnwindOp = UWOP_ALLOC_LARGE; code->OpInfo = 1; } unsigned int cbProlog = unwindGetCurrentOffset(func); noway_assert((BYTE)cbProlog == cbProlog); code->CodeOffset = (BYTE)cbProlog; }