1 //===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains support for writing DWARF exception info into asm files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "DwarfException.h" 14 #include "llvm/BinaryFormat/Dwarf.h" 15 #include "llvm/CodeGen/AsmPrinter.h" 16 #include "llvm/CodeGen/MachineFunction.h" 17 #include "llvm/CodeGen/MachineModuleInfo.h" 18 #include "llvm/MC/MCAsmInfo.h" 19 #include "llvm/MC/MCContext.h" 20 #include "llvm/MC/MCStreamer.h" 21 #include "llvm/Target/TargetLoweringObjectFile.h" 22 #include "llvm/Target/TargetMachine.h" 23 #include "llvm/Target/TargetOptions.h" 24 using namespace llvm; 25 26 DwarfCFIException::DwarfCFIException(AsmPrinter *A) : EHStreamer(A) {} 27 28 DwarfCFIException::~DwarfCFIException() = default; 29 30 void DwarfCFIException::addPersonality(const GlobalValue *Personality) { 31 if (!llvm::is_contained(Personalities, Personality)) 32 Personalities.push_back(Personality); 33 } 34 35 /// endModule - Emit all exception information that should come after the 36 /// content. 37 void DwarfCFIException::endModule() { 38 // SjLj uses this pass and it doesn't need this info. 39 if (!Asm->MAI->usesCFIForEH()) 40 return; 41 42 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 43 44 unsigned PerEncoding = TLOF.getPersonalityEncoding(); 45 46 if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) 47 return; 48 49 // Emit indirect reference table for all used personality functions 50 for (const GlobalValue *Personality : Personalities) { 51 MCSymbol *Sym = Asm->getSymbol(Personality); 52 TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym); 53 } 54 Personalities.clear(); 55 } 56 57 void DwarfCFIException::beginFunction(const MachineFunction *MF) { 58 shouldEmitPersonality = shouldEmitLSDA = false; 59 const Function &F = MF->getFunction(); 60 61 // If any landing pads survive, we need an EH table. 62 bool hasLandingPads = !MF->getLandingPads().empty(); 63 64 // See if we need frame move info. 65 bool shouldEmitMoves = 66 Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None; 67 68 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 69 unsigned PerEncoding = TLOF.getPersonalityEncoding(); 70 const GlobalValue *Per = nullptr; 71 if (F.hasPersonalityFn()) 72 Per = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); 73 74 // Emit a personality function even when there are no landing pads 75 forceEmitPersonality = 76 // ...if a personality function is explicitly specified 77 F.hasPersonalityFn() && 78 // ... and it's not known to be a noop in the absence of invokes 79 !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && 80 // ... and we're not explicitly asked not to emit it 81 F.needsUnwindTableEntry(); 82 83 shouldEmitPersonality = 84 (forceEmitPersonality || 85 (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && 86 Per; 87 88 unsigned LSDAEncoding = TLOF.getLSDAEncoding(); 89 shouldEmitLSDA = shouldEmitPersonality && 90 LSDAEncoding != dwarf::DW_EH_PE_omit; 91 92 const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); 93 if (MAI.getExceptionHandlingType() != ExceptionHandling::None) 94 shouldEmitCFI = 95 MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); 96 else 97 shouldEmitCFI = Asm->needsCFIForDebug() && shouldEmitMoves; 98 } 99 100 void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) { 101 if (!shouldEmitCFI) 102 return; 103 104 if (!hasEmittedCFISections) { 105 AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); 106 // If we don't say anything it implies `.cfi_sections .eh_frame`, so we 107 // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, 108 // we should always emit .debug_frame. 109 if (CFISecType == AsmPrinter::CFISection::Debug || 110 Asm->TM.Options.ForceDwarfFrameSection) 111 Asm->OutStreamer->emitCFISections( 112 CFISecType == AsmPrinter::CFISection::EH, true); 113 hasEmittedCFISections = true; 114 } 115 116 Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); 117 118 // Indicate personality routine, if any. 119 if (!shouldEmitPersonality) 120 return; 121 122 auto &F = MBB.getParent()->getFunction(); 123 auto *P = dyn_cast<GlobalValue>(F.getPersonalityFn()->stripPointerCasts()); 124 assert(P && "Expected personality function"); 125 // Record the personality function. 126 addPersonality(P); 127 128 const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); 129 unsigned PerEncoding = TLOF.getPersonalityEncoding(); 130 const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI); 131 Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding); 132 133 // Provide LSDA information. 134 if (shouldEmitLSDA) 135 Asm->OutStreamer->emitCFILsda(Asm->getMBBExceptionSym(MBB), 136 TLOF.getLSDAEncoding()); 137 } 138 139 void DwarfCFIException::endBasicBlockSection(const MachineBasicBlock &MBB) { 140 if (shouldEmitCFI) 141 Asm->OutStreamer->emitCFIEndProc(); 142 } 143 144 /// endFunction - Gather and emit post-function exception information. 145 /// 146 void DwarfCFIException::endFunction(const MachineFunction *MF) { 147 if (!shouldEmitPersonality) 148 return; 149 150 emitExceptionTable(); 151 } 152