1 //===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===// 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 implements the Dwarf emissions parts of AsmPrinter. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/BinaryFormat/Dwarf.h" 15 #include "llvm/CodeGen/AsmPrinter.h" 16 #include "llvm/CodeGen/DIE.h" 17 #include "llvm/CodeGen/MachineFunction.h" 18 #include "llvm/IR/DataLayout.h" 19 #include "llvm/MC/MCAsmInfo.h" 20 #include "llvm/MC/MCDwarf.h" 21 #include "llvm/MC/MCSection.h" 22 #include "llvm/MC/MCStreamer.h" 23 #include "llvm/MC/MCSymbol.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Target/TargetLoweringObjectFile.h" 26 #include <cstdint> 27 using namespace llvm; 28 29 #define DEBUG_TYPE "asm-printer" 30 31 //===----------------------------------------------------------------------===// 32 // Dwarf Emission Helper Routines 33 //===----------------------------------------------------------------------===// 34 35 static const char *DecodeDWARFEncoding(unsigned Encoding) { 36 switch (Encoding) { 37 case dwarf::DW_EH_PE_absptr: 38 return "absptr"; 39 case dwarf::DW_EH_PE_omit: 40 return "omit"; 41 case dwarf::DW_EH_PE_pcrel: 42 return "pcrel"; 43 case dwarf::DW_EH_PE_uleb128: 44 return "uleb128"; 45 case dwarf::DW_EH_PE_sleb128: 46 return "sleb128"; 47 case dwarf::DW_EH_PE_udata4: 48 return "udata4"; 49 case dwarf::DW_EH_PE_udata8: 50 return "udata8"; 51 case dwarf::DW_EH_PE_sdata4: 52 return "sdata4"; 53 case dwarf::DW_EH_PE_sdata8: 54 return "sdata8"; 55 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: 56 return "pcrel udata4"; 57 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: 58 return "pcrel sdata4"; 59 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: 60 return "pcrel udata8"; 61 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: 62 return "pcrel sdata8"; 63 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4 64 : 65 return "indirect pcrel udata4"; 66 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 67 : 68 return "indirect pcrel sdata4"; 69 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8 70 : 71 return "indirect pcrel udata8"; 72 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8 73 : 74 return "indirect pcrel sdata8"; 75 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel | 76 dwarf::DW_EH_PE_sdata4: 77 return "indirect datarel sdata4"; 78 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_datarel | 79 dwarf::DW_EH_PE_sdata8: 80 return "indirect datarel sdata8"; 81 } 82 83 return "<unknown encoding>"; 84 } 85 86 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an 87 /// encoding. If verbose assembly output is enabled, we output comments 88 /// describing the encoding. Desc is an optional string saying what the 89 /// encoding is specifying (e.g. "LSDA"). 90 void AsmPrinter::emitEncodingByte(unsigned Val, const char *Desc) const { 91 if (isVerbose()) { 92 if (Desc) 93 OutStreamer->AddComment(Twine(Desc) + " Encoding = " + 94 Twine(DecodeDWARFEncoding(Val))); 95 else 96 OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); 97 } 98 99 OutStreamer->emitIntValue(Val, 1); 100 } 101 102 /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. 103 unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { 104 if (Encoding == dwarf::DW_EH_PE_omit) 105 return 0; 106 107 switch (Encoding & 0x07) { 108 default: 109 llvm_unreachable("Invalid encoded value."); 110 case dwarf::DW_EH_PE_absptr: 111 return MAI->getCodePointerSize(); 112 case dwarf::DW_EH_PE_udata2: 113 return 2; 114 case dwarf::DW_EH_PE_udata4: 115 return 4; 116 case dwarf::DW_EH_PE_udata8: 117 return 8; 118 } 119 } 120 121 void AsmPrinter::emitTTypeReference(const GlobalValue *GV, unsigned Encoding) { 122 if (GV) { 123 const TargetLoweringObjectFile &TLOF = getObjFileLowering(); 124 125 const MCExpr *Exp = 126 TLOF.getTTypeGlobalReference(GV, Encoding, TM, MMI, *OutStreamer); 127 OutStreamer->emitValue(Exp, GetSizeOfEncodedValue(Encoding)); 128 } else 129 OutStreamer->emitIntValue(0, GetSizeOfEncodedValue(Encoding)); 130 } 131 132 void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label, 133 bool ForceOffset) const { 134 if (!ForceOffset) { 135 // On COFF targets, we have to emit the special .secrel32 directive. 136 if (MAI->needsDwarfSectionOffsetDirective()) { 137 assert(!isDwarf64() && 138 "emitting DWARF64 is not implemented for COFF targets"); 139 OutStreamer->emitCOFFSecRel32(Label, /*Offset=*/0); 140 return; 141 } 142 143 // If the format uses relocations with dwarf, refer to the symbol directly. 144 if (doesDwarfUseRelocationsAcrossSections()) { 145 OutStreamer->emitSymbolValue(Label, getDwarfOffsetByteSize()); 146 return; 147 } 148 } 149 150 // Otherwise, emit it as a label difference from the start of the section. 151 emitLabelDifference(Label, Label->getSection().getBeginSymbol(), 152 getDwarfOffsetByteSize()); 153 } 154 155 void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { 156 if (doesDwarfUseRelocationsAcrossSections()) { 157 assert(S.Symbol && "No symbol available"); 158 emitDwarfSymbolReference(S.Symbol); 159 return; 160 } 161 162 // Just emit the offset directly; no need for symbol math. 163 OutStreamer->emitIntValue(S.Offset, getDwarfOffsetByteSize()); 164 } 165 166 void AsmPrinter::emitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { 167 emitLabelPlusOffset(Label, Offset, getDwarfOffsetByteSize()); 168 } 169 170 void AsmPrinter::emitDwarfLengthOrOffset(uint64_t Value) const { 171 assert(isDwarf64() || Value <= UINT32_MAX); 172 OutStreamer->emitIntValue(Value, getDwarfOffsetByteSize()); 173 } 174 175 void AsmPrinter::emitDwarfUnitLength(uint64_t Length, 176 const Twine &Comment) const { 177 OutStreamer->emitDwarfUnitLength(Length, Comment); 178 } 179 180 MCSymbol *AsmPrinter::emitDwarfUnitLength(const Twine &Prefix, 181 const Twine &Comment) const { 182 return OutStreamer->emitDwarfUnitLength(Prefix, Comment); 183 } 184 185 void AsmPrinter::emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, 186 unsigned Encoding) const { 187 // The least significant 3 bits specify the width of the encoding 188 if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128) 189 emitLabelDifferenceAsULEB128(Hi, Lo); 190 else 191 emitLabelDifference(Hi, Lo, GetSizeOfEncodedValue(Encoding)); 192 } 193 194 void AsmPrinter::emitCallSiteValue(uint64_t Value, unsigned Encoding) const { 195 // The least significant 3 bits specify the width of the encoding 196 if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128) 197 emitULEB128(Value); 198 else 199 OutStreamer->emitIntValue(Value, GetSizeOfEncodedValue(Encoding)); 200 } 201 202 //===----------------------------------------------------------------------===// 203 // Dwarf Lowering Routines 204 //===----------------------------------------------------------------------===// 205 206 void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { 207 SMLoc Loc = Inst.getLoc(); 208 switch (Inst.getOperation()) { 209 default: 210 llvm_unreachable("Unexpected instruction"); 211 case MCCFIInstruction::OpDefCfaOffset: 212 OutStreamer->emitCFIDefCfaOffset(Inst.getOffset(), Loc); 213 break; 214 case MCCFIInstruction::OpAdjustCfaOffset: 215 OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset(), Loc); 216 break; 217 case MCCFIInstruction::OpDefCfa: 218 OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset(), Loc); 219 break; 220 case MCCFIInstruction::OpDefCfaRegister: 221 OutStreamer->emitCFIDefCfaRegister(Inst.getRegister(), Loc); 222 break; 223 case MCCFIInstruction::OpLLVMDefAspaceCfa: 224 OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(), 225 Inst.getAddressSpace(), Loc); 226 break; 227 case MCCFIInstruction::OpOffset: 228 OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset(), Loc); 229 break; 230 case MCCFIInstruction::OpRegister: 231 OutStreamer->emitCFIRegister(Inst.getRegister(), Inst.getRegister2(), Loc); 232 break; 233 case MCCFIInstruction::OpWindowSave: 234 OutStreamer->emitCFIWindowSave(Loc); 235 break; 236 case MCCFIInstruction::OpNegateRAState: 237 OutStreamer->emitCFINegateRAState(Loc); 238 break; 239 case MCCFIInstruction::OpSameValue: 240 OutStreamer->emitCFISameValue(Inst.getRegister(), Loc); 241 break; 242 case MCCFIInstruction::OpGnuArgsSize: 243 OutStreamer->emitCFIGnuArgsSize(Inst.getOffset(), Loc); 244 break; 245 case MCCFIInstruction::OpEscape: 246 OutStreamer->AddComment(Inst.getComment()); 247 OutStreamer->emitCFIEscape(Inst.getValues(), Loc); 248 break; 249 case MCCFIInstruction::OpRestore: 250 OutStreamer->emitCFIRestore(Inst.getRegister(), Loc); 251 break; 252 case MCCFIInstruction::OpUndefined: 253 OutStreamer->emitCFIUndefined(Inst.getRegister(), Loc); 254 break; 255 case MCCFIInstruction::OpRememberState: 256 OutStreamer->emitCFIRememberState(Loc); 257 break; 258 case MCCFIInstruction::OpRestoreState: 259 OutStreamer->emitCFIRestoreState(Loc); 260 break; 261 } 262 } 263 264 void AsmPrinter::emitDwarfDIE(const DIE &Die) const { 265 // Emit the code (index) for the abbreviation. 266 if (isVerbose()) 267 OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + 268 Twine::utohexstr(Die.getOffset()) + ":0x" + 269 Twine::utohexstr(Die.getSize()) + " " + 270 dwarf::TagString(Die.getTag())); 271 emitULEB128(Die.getAbbrevNumber()); 272 273 // Emit the DIE attribute values. 274 for (const auto &V : Die.values()) { 275 dwarf::Attribute Attr = V.getAttribute(); 276 assert(V.getForm() && "Too many attributes for DIE (check abbreviation)"); 277 278 if (isVerbose()) { 279 OutStreamer->AddComment(dwarf::AttributeString(Attr)); 280 if (Attr == dwarf::DW_AT_accessibility) 281 OutStreamer->AddComment( 282 dwarf::AccessibilityString(V.getDIEInteger().getValue())); 283 } 284 285 // Emit an attribute using the defined form. 286 V.emitValue(this); 287 } 288 289 // Emit the DIE children if any. 290 if (Die.hasChildren()) { 291 for (const auto &Child : Die.children()) 292 emitDwarfDIE(Child); 293 294 OutStreamer->AddComment("End Of Children Mark"); 295 emitInt8(0); 296 } 297 } 298 299 void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { 300 // Emit the abbreviations code (base 1 index.) 301 emitULEB128(Abbrev.getNumber(), "Abbreviation Code"); 302 303 // Emit the abbreviations data. 304 Abbrev.Emit(this); 305 } 306