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 // TODO: Support DWARF64 185 emitLabelPlusOffset(Label, Offset, 4); 186 } 187 188 void AsmPrinter::emitCallSiteOffset(const MCSymbol *Hi, const MCSymbol *Lo, 189 unsigned Encoding) const { 190 // The least significant 3 bits specify the width of the encoding 191 if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128) 192 emitLabelDifferenceAsULEB128(Hi, Lo); 193 else 194 emitLabelDifference(Hi, Lo, GetSizeOfEncodedValue(Encoding)); 195 } 196 197 void AsmPrinter::emitCallSiteValue(uint64_t Value, unsigned Encoding) const { 198 // The least significant 3 bits specify the width of the encoding 199 if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128) 200 emitULEB128(Value); 201 else 202 OutStreamer->emitIntValue(Value, GetSizeOfEncodedValue(Encoding)); 203 } 204 205 //===----------------------------------------------------------------------===// 206 // Dwarf Lowering Routines 207 //===----------------------------------------------------------------------===// 208 209 void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { 210 switch (Inst.getOperation()) { 211 default: 212 llvm_unreachable("Unexpected instruction"); 213 case MCCFIInstruction::OpDefCfaOffset: 214 OutStreamer->emitCFIDefCfaOffset(Inst.getOffset()); 215 break; 216 case MCCFIInstruction::OpAdjustCfaOffset: 217 OutStreamer->emitCFIAdjustCfaOffset(Inst.getOffset()); 218 break; 219 case MCCFIInstruction::OpDefCfa: 220 OutStreamer->emitCFIDefCfa(Inst.getRegister(), Inst.getOffset()); 221 break; 222 case MCCFIInstruction::OpDefCfaRegister: 223 OutStreamer->emitCFIDefCfaRegister(Inst.getRegister()); 224 break; 225 case MCCFIInstruction::OpOffset: 226 OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset()); 227 break; 228 case MCCFIInstruction::OpRegister: 229 OutStreamer->emitCFIRegister(Inst.getRegister(), Inst.getRegister2()); 230 break; 231 case MCCFIInstruction::OpWindowSave: 232 OutStreamer->emitCFIWindowSave(); 233 break; 234 case MCCFIInstruction::OpNegateRAState: 235 OutStreamer->emitCFINegateRAState(); 236 break; 237 case MCCFIInstruction::OpSameValue: 238 OutStreamer->emitCFISameValue(Inst.getRegister()); 239 break; 240 case MCCFIInstruction::OpGnuArgsSize: 241 OutStreamer->emitCFIGnuArgsSize(Inst.getOffset()); 242 break; 243 case MCCFIInstruction::OpEscape: 244 OutStreamer->emitCFIEscape(Inst.getValues()); 245 break; 246 case MCCFIInstruction::OpRestore: 247 OutStreamer->emitCFIRestore(Inst.getRegister()); 248 break; 249 case MCCFIInstruction::OpUndefined: 250 OutStreamer->emitCFIUndefined(Inst.getRegister()); 251 break; 252 } 253 } 254 255 void AsmPrinter::emitDwarfDIE(const DIE &Die) const { 256 // Emit the code (index) for the abbreviation. 257 if (isVerbose()) 258 OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + 259 Twine::utohexstr(Die.getOffset()) + ":0x" + 260 Twine::utohexstr(Die.getSize()) + " " + 261 dwarf::TagString(Die.getTag())); 262 emitULEB128(Die.getAbbrevNumber()); 263 264 // Emit the DIE attribute values. 265 for (const auto &V : Die.values()) { 266 dwarf::Attribute Attr = V.getAttribute(); 267 assert(V.getForm() && "Too many attributes for DIE (check abbreviation)"); 268 269 if (isVerbose()) { 270 OutStreamer->AddComment(dwarf::AttributeString(Attr)); 271 if (Attr == dwarf::DW_AT_accessibility) 272 OutStreamer->AddComment( 273 dwarf::AccessibilityString(V.getDIEInteger().getValue())); 274 } 275 276 // Emit an attribute using the defined form. 277 V.emitValue(this); 278 } 279 280 // Emit the DIE children if any. 281 if (Die.hasChildren()) { 282 for (auto &Child : Die.children()) 283 emitDwarfDIE(Child); 284 285 OutStreamer->AddComment("End Of Children Mark"); 286 emitInt8(0); 287 } 288 } 289 290 void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { 291 // Emit the abbreviations code (base 1 index.) 292 emitULEB128(Abbrev.getNumber(), "Abbreviation Code"); 293 294 // Emit the abbreviations data. 295 Abbrev.Emit(this); 296 } 297