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