119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===// 219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// The LLVM Compiler Infrastructure 419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source 619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details. 719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCWin64EH.h" 1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCStreamer.h" 1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCContext.h" 1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCObjectFileInfo.h" 1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCSymbol.h" 1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCSectionCOFF.h" 1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/MC/MCExpr.h" 1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/ADT/Twine.h" 1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace llvm { 2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// NOTE: All relocations generated here are 4-byte image-relative. 2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic uint8_t CountOfUnwindCodes(std::vector<MCWin64EHInstruction> &instArray){ 2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint8_t count = 0; 2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (std::vector<MCWin64EHInstruction>::const_iterator I = instArray.begin(), 2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman E = instArray.end(); I != E; ++I) { 2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman switch (I->getOperation()) { 2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_PushNonVol: 2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_AllocSmall: 3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SetFPReg: 3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_PushMachFrame: 3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman count += 1; 3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveNonVol: 3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveXMM128: 3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman count += 2; 3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveNonVolBig: 3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveXMM128Big: 4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman count += 3; 4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_AllocLarge: 4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (I->getSize() > 512*1024-8) 4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman count += 3; 4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else 4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman count += 2; 4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return count; 5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic void EmitAbsDifference(MCStreamer &streamer, MCSymbol *lhs, 5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCSymbol *rhs) { 5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context = streamer.getContext(); 5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCExpr *diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create( 5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman lhs, context), 5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCSymbolRefExpr::Create( 5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman rhs, context), 6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman context); 6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitAbsValue(diff, 1); 6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, 6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCWin64EHInstruction &inst) { 6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint8_t b1, b2; 6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint16_t w; 6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 = (inst.getOperation() & 0x0F); 7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman switch (inst.getOperation()) { 7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_PushNonVol: 7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, inst.getLabel(), begin); 7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 |= (inst.getRegister() & 0x0F) << 4; 7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_AllocLarge: 7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, inst.getLabel(), begin); 7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (inst.getSize() > 512*1024-8) { 7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 |= 0x10; 8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getSize() & 0xFFF8; 8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(w, 2); 8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getSize() >> 16; 8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } else { 8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getSize() >> 3; 8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(w, 2); 8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_AllocSmall: 9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 |= (((inst.getSize()-8) >> 3) & 0x0F) << 4; 9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, inst.getLabel(), begin); 9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SetFPReg: 9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b1 = inst.getOffset() & 0xF0; 9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b1, 1); 9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveNonVol: 10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveXMM128: 10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 |= (inst.getRegister() & 0x0F) << 4; 10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, inst.getLabel(), begin); 10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getOffset() >> 3; 10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (inst.getOperation() == Win64EH::UOP_SaveXMM128) 10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w >>= 1; 10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(w, 2); 10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveNonVolBig: 11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_SaveXMM128Big: 11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 |= (inst.getRegister() & 0x0F) << 4; 11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, inst.getLabel(), begin); 11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (inst.getOperation() == Win64EH::UOP_SaveXMM128Big) 11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getOffset() & 0xFFF0; 11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else 11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getOffset() & 0xFFF8; 11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(w, 2); 12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman w = inst.getOffset() >> 16; 12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(w, 2); 12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman case Win64EH::UOP_PushMachFrame: 12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (inst.isPushCodeFrame()) 12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman b2 |= 0x10; 12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, inst.getLabel(), begin); 12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(b2, 1); 12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic void EmitRuntimeFunction(MCStreamer &streamer, 13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCWin64EHUnwindInfo *info) { 13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context = streamer.getContext(); 13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitValueToAlignment(4); 13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitValue(MCSymbolRefExpr::Create(info->Begin, context), 4); 13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitValue(MCSymbolRefExpr::Create(info->End, context), 4); 13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitValue(MCSymbolRefExpr::Create(info->Symbol, context), 4); 14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) { 14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // If this UNWIND_INFO already has a symbol, it's already been emitted. 14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (info->Symbol) return; 14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context = streamer.getContext(); 14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitValueToAlignment(4); 14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Upper 3 bits are the version number (currently 1). 14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint8_t flags = 0x01; 15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman info->Symbol = context.CreateTempSymbol(); 15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitLabel(info->Symbol); 15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (info->ChainedParent) 15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman flags |= Win64EH::UNW_ChainInfo << 3; 15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else { 15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (info->HandlesUnwind) 15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman flags |= Win64EH::UNW_TerminateHandler << 3; 15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (info->HandlesExceptions) 15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman flags |= Win64EH::UNW_ExceptionHandler << 3; 16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(flags, 1); 16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (info->PrologEnd) 16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitAbsDifference(streamer, info->PrologEnd, info->Begin); 16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else 16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(0, 1); 16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint8_t numCodes = CountOfUnwindCodes(info->Instructions); 16919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(numCodes, 1); 17019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint8_t frame = 0; 17219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (info->LastFrameInst >= 0) { 17319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst]; 17419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman assert(frameInst.getOperation() == Win64EH::UOP_SetFPReg); 17519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman frame = (frameInst.getRegister() & 0x0F) | 17619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman (frameInst.getOffset() & 0xF0); 17719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 17819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(frame, 1); 17919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 18019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Emit unwind instructions (in reverse order). 18119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint8_t numInst = info->Instructions.size(); 18219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (uint8_t c = 0; c < numInst; ++c) { 18319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCWin64EHInstruction inst = info->Instructions.back(); 18419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman info->Instructions.pop_back(); 18519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitUnwindCode(streamer, info->Begin, inst); 18619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 18719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 18819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (flags & (Win64EH::UNW_ChainInfo << 3)) 18919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitRuntimeFunction(streamer, info->ChainedParent); 19019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else if (flags & 19119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman ((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3)) 19219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, context), 19319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 4); 19419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else if (numCodes < 2) { 19519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not 19619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // a chained unwind info, if there is no handler, and if there are fewer 19719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // than 2 slots used in the unwind code array, we have to pad to 8 bytes. 19819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (numCodes == 1) 19919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(0, 2); 20019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman else 20119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.EmitIntValue(0, 4); 20219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 20319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 20419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 20519bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanStringRef MCWin64EHUnwindEmitter::GetSectionSuffix(const MCSymbol *func) { 20619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!func || !func->isInSection()) return ""; 20719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCSection *section = &func->getSection(); 20819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCSectionCOFF *COFFSection; 20919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if ((COFFSection = dyn_cast<MCSectionCOFF>(section))) { 21019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman StringRef name = COFFSection->getSectionName(); 21119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman size_t dollar = name.find('$'); 21219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman size_t dot = name.find('.', 1); 21319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (dollar == StringRef::npos && dot == StringRef::npos) 21419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return ""; 21519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (dot == StringRef::npos) 21619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return name.substr(dollar); 21719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (dollar == StringRef::npos || dot < dollar) 21819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return name.substr(dot); 21919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return name.substr(dollar); 22019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 22119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return ""; 22219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 22319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 22419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic const MCSection *getWin64EHTableSection(StringRef suffix, 22519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context) { 22619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (suffix == "") 22719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return context.getObjectFileInfo()->getXDataSection(); 22819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 22919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return context.getCOFFSection((".xdata"+suffix).str(), 23019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 23119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman COFF::IMAGE_SCN_MEM_READ | 23219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman COFF::IMAGE_SCN_MEM_WRITE, 23319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SectionKind::getDataRel()); 23419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 23519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 23619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanstatic const MCSection *getWin64EHFuncTableSection(StringRef suffix, 23719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context) { 23819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (suffix == "") 23919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return context.getObjectFileInfo()->getPDataSection(); 24019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return context.getCOFFSection((".pdata"+suffix).str(), 24119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 24219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman COFF::IMAGE_SCN_MEM_READ | 24319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman COFF::IMAGE_SCN_MEM_WRITE, 24419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman SectionKind::getDataRel()); 24519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 24619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 24719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, 24819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCWin64EHUnwindInfo *info) { 24919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Switch sections (the static function above is meant to be called from 25019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // here and from Emit(). 25119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context = streamer.getContext(); 25219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCSection *xdataSect = 25319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman getWin64EHTableSection(GetSectionSuffix(info->Function), context); 25419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.SwitchSection(xdataSect); 25519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 25619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman llvm::EmitUnwindInfo(streamer, info); 25719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 25819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 25919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid MCWin64EHUnwindEmitter::Emit(MCStreamer &streamer) { 26019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCContext &context = streamer.getContext(); 26119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Emit the unwind info structs first. 26219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { 26319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); 26419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCSection *xdataSect = 26519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman getWin64EHTableSection(GetSectionSuffix(info.Function), context); 26619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.SwitchSection(xdataSect); 26719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman llvm::EmitUnwindInfo(streamer, &info); 26819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 26919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Now emit RUNTIME_FUNCTION entries. 27019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0; i < streamer.getNumW64UnwindInfos(); ++i) { 27119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman MCWin64EHUnwindInfo &info = streamer.getW64UnwindInfo(i); 27219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const MCSection *pdataSect = 27319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman getWin64EHFuncTableSection(GetSectionSuffix(info.Function), context); 27419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman streamer.SwitchSection(pdataSect); 27519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman EmitRuntimeFunction(streamer, &info); 27619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 27719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 27819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 27919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // End of namespace llvm 28019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 281