// Prints one unwind code. Because an unwind code can occupy up to 3 slots in // the unwind codes array, this function requires that the correct number of // slots is provided. void Dumper::printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC) { assert(UC.size() >= getNumUsedSlots(UC[0])); SW.startLine() << format("0x%02X: ", unsigned(UC[0].u.CodeOffset)) << getUnwindCodeTypeName(UC[0].getUnwindOp()); switch (UC[0].getUnwindOp()) { case UOP_PushNonVol: OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()); break; case UOP_AllocLarge: OS << " size=" << ((UC[0].getOpInfo() == 0) ? UC[1].FrameOffset * 8 : getLargeSlotValue(UC)); break; case UOP_AllocSmall: OS << " size=" << (UC[0].getOpInfo() + 1) * 8; break; case UOP_SetFPReg: if (UI.getFrameRegister() == 0) OS << " reg=<invalid>"; else OS << " reg=" << getUnwindRegisterName(UI.getFrameRegister()) << format(", offset=0x%X", UI.getFrameOffset() * 16); break; case UOP_SaveNonVol: OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()) << format(", offset=0x%X", UC[1].FrameOffset * 8); break; case UOP_SaveNonVolBig: OS << " reg=" << getUnwindRegisterName(UC[0].getOpInfo()) << format(", offset=0x%X", getLargeSlotValue(UC)); break; case UOP_SaveXMM128: OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo()) << format(", offset=0x%X", UC[1].FrameOffset * 16); break; case UOP_SaveXMM128Big: OS << " reg=XMM" << static_cast<uint32_t>(UC[0].getOpInfo()) << format(", offset=0x%X", getLargeSlotValue(UC)); break; case UOP_PushMachFrame: OS << " errcode=" << (UC[0].getOpInfo() == 0 ? "no" : "yes"); break; } OS << "\n"; }
void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section, off_t Offset, const UnwindInfo &UI) { DictScope UIS(SW, "UnwindInfo"); SW.printNumber("Version", UI.getVersion()); SW.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags)); SW.printNumber("PrologSize", UI.PrologSize); if (UI.getFrameRegister()) { SW.printEnum("FrameRegister", UI.getFrameRegister(), makeArrayRef(UnwindOpInfo)); SW.printHex("FrameOffset", UI.getFrameOffset()); } else { SW.printString("FrameRegister", StringRef("-")); SW.printString("FrameOffset", StringRef("-")); } SW.printNumber("UnwindCodeCount", UI.NumCodes); { ListScope UCS(SW, "UnwindCodes"); ArrayRef<UnwindCode> UC(&UI.UnwindCodes[0], UI.NumCodes); for (const UnwindCode *UCI = UC.begin(), *UCE = UC.end(); UCI < UCE; ++UCI) { unsigned UsedSlots = getNumUsedSlots(*UCI); if (UsedSlots > UC.size()) { errs() << "corrupt unwind data"; return; } printUnwindCode(UI, ArrayRef<UnwindCode>(UCI, UCE)); UCI = UCI + UsedSlots - 1; } } uint64_t LSDAOffset = Offset + getOffsetOfLSDA(UI); if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { SW.printString("Handler", formatSymbol(Ctx, Section, LSDAOffset, UI.getLanguageSpecificHandlerOffset())); } else if (UI.getFlags() & UNW_ChainInfo) { if (const RuntimeFunction *Chained = UI.getChainedFunctionEntry()) { DictScope CS(SW, "Chained"); printRuntimeFunctionEntry(Ctx, Section, LSDAOffset, *Chained); } } }