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, unsigned PadTo) const { 47 if (isVerbose() && Desc) 48 OutStreamer->AddComment(Desc); 49 50 OutStreamer->EmitULEB128IntValue(Value, PadTo); 51 } 52 53 /// Emit something like ".uleb128 Hi-Lo". 54 void AsmPrinter::EmitLabelDifferenceAsULEB128(const MCSymbol *Hi, 55 const MCSymbol *Lo) const { 56 OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo); 57 } 58 59 static const char *DecodeDWARFEncoding(unsigned Encoding) { 60 switch (Encoding) { 61 case dwarf::DW_EH_PE_absptr: 62 return "absptr"; 63 case dwarf::DW_EH_PE_omit: 64 return "omit"; 65 case dwarf::DW_EH_PE_pcrel: 66 return "pcrel"; 67 case dwarf::DW_EH_PE_uleb128: 68 return "uleb128"; 69 case dwarf::DW_EH_PE_sleb128: 70 return "sleb128"; 71 case dwarf::DW_EH_PE_udata4: 72 return "udata4"; 73 case dwarf::DW_EH_PE_udata8: 74 return "udata8"; 75 case dwarf::DW_EH_PE_sdata4: 76 return "sdata4"; 77 case dwarf::DW_EH_PE_sdata8: 78 return "sdata8"; 79 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: 80 return "pcrel udata4"; 81 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: 82 return "pcrel sdata4"; 83 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: 84 return "pcrel udata8"; 85 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: 86 return "pcrel sdata8"; 87 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4 88 : 89 return "indirect pcrel udata4"; 90 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 91 : 92 return "indirect pcrel sdata4"; 93 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8 94 : 95 return "indirect pcrel udata8"; 96 case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8 97 : 98 return "indirect pcrel sdata8"; 99 } 100 101 return "<unknown encoding>"; 102 } 103 104 /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an 105 /// encoding. If verbose assembly output is enabled, we output comments 106 /// describing the encoding. Desc is an optional string saying what the 107 /// encoding is specifying (e.g. "LSDA"). 108 void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { 109 if (isVerbose()) { 110 if (Desc) 111 OutStreamer->AddComment(Twine(Desc) + " Encoding = " + 112 Twine(DecodeDWARFEncoding(Val))); 113 else 114 OutStreamer->AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); 115 } 116 117 OutStreamer->EmitIntValue(Val, 1); 118 } 119 120 /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. 121 unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { 122 if (Encoding == dwarf::DW_EH_PE_omit) 123 return 0; 124 125 switch (Encoding & 0x07) { 126 default: 127 llvm_unreachable("Invalid encoded value."); 128 case dwarf::DW_EH_PE_absptr: 129 return MF->getDataLayout().getPointerSize(); 130 case dwarf::DW_EH_PE_udata2: 131 return 2; 132 case dwarf::DW_EH_PE_udata4: 133 return 4; 134 case dwarf::DW_EH_PE_udata8: 135 return 8; 136 } 137 } 138 139 void AsmPrinter::EmitTTypeReference(const GlobalValue *GV, 140 unsigned Encoding) const { 141 if (GV) { 142 const TargetLoweringObjectFile &TLOF = getObjFileLowering(); 143 144 const MCExpr *Exp = 145 TLOF.getTTypeGlobalReference(GV, Encoding, TM, MMI, *OutStreamer); 146 OutStreamer->EmitValue(Exp, GetSizeOfEncodedValue(Encoding)); 147 } else 148 OutStreamer->EmitIntValue(0, GetSizeOfEncodedValue(Encoding)); 149 } 150 151 void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label, 152 bool ForceOffset) const { 153 if (!ForceOffset) { 154 // On COFF targets, we have to emit the special .secrel32 directive. 155 if (MAI->needsDwarfSectionOffsetDirective()) { 156 OutStreamer->EmitCOFFSecRel32(Label, /*Offset=*/0); 157 return; 158 } 159 160 // If the format uses relocations with dwarf, refer to the symbol directly. 161 if (MAI->doesDwarfUseRelocationsAcrossSections()) { 162 OutStreamer->EmitSymbolValue(Label, 4); 163 return; 164 } 165 } 166 167 // Otherwise, emit it as a label difference from the start of the section. 168 EmitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4); 169 } 170 171 void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const { 172 if (MAI->doesDwarfUseRelocationsAcrossSections()) { 173 assert(S.Symbol && "No symbol available"); 174 emitDwarfSymbolReference(S.Symbol); 175 return; 176 } 177 178 // Just emit the offset directly; no need for symbol math. 179 emitInt32(S.Offset); 180 } 181 182 void AsmPrinter::EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const { 183 EmitLabelPlusOffset(Label, Offset, MAI->getCodePointerSize()); 184 } 185 186 void AsmPrinter::EmitCallSiteOffset(const MCSymbol *Hi, 187 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, 197 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 } 250 } 251 252 void AsmPrinter::emitDwarfDIE(const DIE &Die) const { 253 // Emit the code (index) for the abbreviation. 254 if (isVerbose()) 255 OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + 256 Twine::utohexstr(Die.getOffset()) + ":0x" + 257 Twine::utohexstr(Die.getSize()) + " " + 258 dwarf::TagString(Die.getTag())); 259 EmitULEB128(Die.getAbbrevNumber()); 260 261 // Emit the DIE attribute values. 262 for (const auto &V : Die.values()) { 263 dwarf::Attribute Attr = V.getAttribute(); 264 assert(V.getForm() && "Too many attributes for DIE (check abbreviation)"); 265 266 if (isVerbose()) { 267 OutStreamer->AddComment(dwarf::AttributeString(Attr)); 268 if (Attr == dwarf::DW_AT_accessibility) 269 OutStreamer->AddComment( 270 dwarf::AccessibilityString(V.getDIEInteger().getValue())); 271 } 272 273 // Emit an attribute using the defined form. 274 V.EmitValue(this); 275 } 276 277 // Emit the DIE children if any. 278 if (Die.hasChildren()) { 279 for (auto &Child : Die.children()) 280 emitDwarfDIE(Child); 281 282 OutStreamer->AddComment("End Of Children Mark"); 283 emitInt8(0); 284 } 285 } 286 287 void AsmPrinter::emitDwarfAbbrev(const DIEAbbrev &Abbrev) const { 288 // Emit the abbreviations code (base 1 index.) 289 EmitULEB128(Abbrev.getNumber(), "Abbreviation Code"); 290 291 // Emit the abbreviations data. 292 Abbrev.Emit(this); 293 } 294