1//===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/MC/MCDwarf.h" 11#include "llvm/ADT/Hashing.h" 12#include "llvm/ADT/SmallString.h" 13#include "llvm/ADT/Twine.h" 14#include "llvm/Config/config.h" 15#include "llvm/MC/MCAsmInfo.h" 16#include "llvm/MC/MCContext.h" 17#include "llvm/MC/MCExpr.h" 18#include "llvm/MC/MCObjectFileInfo.h" 19#include "llvm/MC/MCObjectWriter.h" 20#include "llvm/MC/MCRegisterInfo.h" 21#include "llvm/MC/MCStreamer.h" 22#include "llvm/MC/MCSymbol.h" 23#include "llvm/Support/Debug.h" 24#include "llvm/Support/ErrorHandling.h" 25#include "llvm/Support/LEB128.h" 26#include "llvm/Support/Path.h" 27#include "llvm/Support/SourceMgr.h" 28#include "llvm/Support/raw_ostream.h" 29using namespace llvm; 30 31// Given a special op, return the address skip amount (in units of 32// DWARF2_LINE_MIN_INSN_LENGTH. 33#define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) 34 35// The maximum address skip amount that can be encoded with a special op. 36#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) 37 38// First special line opcode - leave room for the standard opcodes. 39// Note: If you want to change this, you'll have to update the 40// "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). 41#define DWARF2_LINE_OPCODE_BASE 13 42 43// Minimum line offset in a special line info. opcode. This value 44// was chosen to give a reasonable range of values. 45#define DWARF2_LINE_BASE -5 46 47// Range of line offsets in a special line info. opcode. 48#define DWARF2_LINE_RANGE 14 49 50// Define the architecture-dependent minimum instruction length (in bytes). 51// This value should be rather too small than too big. 52#define DWARF2_LINE_MIN_INSN_LENGTH 1 53 54// Note: when DWARF2_LINE_MIN_INSN_LENGTH == 1 which is the current setting, 55// this routine is a nop and will be optimized away. 56static inline uint64_t ScaleAddrDelta(uint64_t AddrDelta) { 57 if (DWARF2_LINE_MIN_INSN_LENGTH == 1) 58 return AddrDelta; 59 if (AddrDelta % DWARF2_LINE_MIN_INSN_LENGTH != 0) { 60 // TODO: report this error, but really only once. 61 ; 62 } 63 return AddrDelta / DWARF2_LINE_MIN_INSN_LENGTH; 64} 65 66// 67// This is called when an instruction is assembled into the specified section 68// and if there is information from the last .loc directive that has yet to have 69// a line entry made for it is made. 70// 71void MCLineEntry::Make(MCStreamer *MCOS, const MCSection *Section) { 72 if (!MCOS->getContext().getDwarfLocSeen()) 73 return; 74 75 // Create a symbol at in the current section for use in the line entry. 76 MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol(); 77 // Set the value of the symbol to use for the MCLineEntry. 78 MCOS->EmitLabel(LineSym); 79 80 // Get the current .loc info saved in the context. 81 const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); 82 83 // Create a (local) line entry with the symbol and the current .loc info. 84 MCLineEntry LineEntry(LineSym, DwarfLoc); 85 86 // clear DwarfLocSeen saying the current .loc info is now used. 87 MCOS->getContext().ClearDwarfLocSeen(); 88 89 // Get the MCLineSection for this section, if one does not exist for this 90 // section create it. 91 const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = 92 MCOS->getContext().getMCLineSections(); 93 MCLineSection *LineSection = MCLineSections.lookup(Section); 94 if (!LineSection) { 95 // Create a new MCLineSection. This will be deleted after the dwarf line 96 // table is created using it by iterating through the MCLineSections 97 // DenseMap. 98 LineSection = new MCLineSection; 99 // Save a pointer to the new LineSection into the MCLineSections DenseMap. 100 MCOS->getContext().addMCLineSection(Section, LineSection); 101 } 102 103 // Add the line entry to this section's entries. 104 LineSection->addLineEntry(LineEntry, 105 MCOS->getContext().getDwarfCompileUnitID()); 106} 107 108// 109// This helper routine returns an expression of End - Start + IntVal . 110// 111static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, 112 const MCSymbol &Start, 113 const MCSymbol &End, 114 int IntVal) { 115 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 116 const MCExpr *Res = 117 MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext()); 118 const MCExpr *RHS = 119 MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext()); 120 const MCExpr *Res1 = 121 MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); 122 const MCExpr *Res2 = 123 MCConstantExpr::Create(IntVal, MCOS.getContext()); 124 const MCExpr *Res3 = 125 MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); 126 return Res3; 127} 128 129// 130// This emits the Dwarf line table for the specified section from the entries 131// in the LineSection. 132// 133static inline void EmitDwarfLineTable(MCStreamer *MCOS, 134 const MCSection *Section, 135 const MCLineSection *LineSection, 136 unsigned CUID) { 137 // This LineSection does not contain any LineEntry for the given Compile Unit. 138 if (!LineSection->containEntriesForID(CUID)) 139 return; 140 141 unsigned FileNum = 1; 142 unsigned LastLine = 1; 143 unsigned Column = 0; 144 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 145 unsigned Isa = 0; 146 MCSymbol *LastLabel = NULL; 147 148 // Loop through each MCLineEntry and encode the dwarf line number table. 149 for (MCLineSection::const_iterator 150 it = LineSection->getMCLineEntries(CUID).begin(), 151 ie = LineSection->getMCLineEntries(CUID).end(); it != ie; ++it) { 152 153 if (FileNum != it->getFileNum()) { 154 FileNum = it->getFileNum(); 155 MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); 156 MCOS->EmitULEB128IntValue(FileNum); 157 } 158 if (Column != it->getColumn()) { 159 Column = it->getColumn(); 160 MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); 161 MCOS->EmitULEB128IntValue(Column); 162 } 163 if (Isa != it->getIsa()) { 164 Isa = it->getIsa(); 165 MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); 166 MCOS->EmitULEB128IntValue(Isa); 167 } 168 if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 169 Flags = it->getFlags(); 170 MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); 171 } 172 if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) 173 MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); 174 if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) 175 MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); 176 if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 177 MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); 178 179 int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine; 180 MCSymbol *Label = it->getLabel(); 181 182 // At this point we want to emit/create the sequence to encode the delta in 183 // line numbers and the increment of the address from the previous Label 184 // and the current Label. 185 const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo(); 186 MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 187 asmInfo.getPointerSize()); 188 189 LastLine = it->getLine(); 190 LastLabel = Label; 191 } 192 193 // Emit a DW_LNE_end_sequence for the end of the section. 194 // Using the pointer Section create a temporary label at the end of the 195 // section and use that and the LastLabel to compute the address delta 196 // and use INT64_MAX as the line delta which is the signal that this is 197 // actually a DW_LNE_end_sequence. 198 199 // Switch to the section to be able to create a symbol at its end. 200 // TODO: keep track of the last subsection so that this symbol appears in the 201 // correct place. 202 MCOS->SwitchSection(Section); 203 204 MCContext &context = MCOS->getContext(); 205 // Create a symbol at the end of the section. 206 MCSymbol *SectionEnd = context.CreateTempSymbol(); 207 // Set the value of the symbol, as we are at the end of the section. 208 MCOS->EmitLabel(SectionEnd); 209 210 // Switch back the dwarf line section. 211 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); 212 213 const MCAsmInfo &asmInfo = MCOS->getContext().getAsmInfo(); 214 MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, 215 asmInfo.getPointerSize()); 216} 217 218// 219// This emits the Dwarf file and the line tables. 220// 221const MCSymbol *MCDwarfFileTable::Emit(MCStreamer *MCOS) { 222 MCContext &context = MCOS->getContext(); 223 // Switch to the section where the table will be emitted into. 224 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); 225 226 const DenseMap<unsigned, MCSymbol *> &MCLineTableSymbols = 227 MCOS->getContext().getMCLineTableSymbols(); 228 // CUID and MCLineTableSymbols are set in DwarfDebug, when DwarfDebug does 229 // not exist, CUID will be 0 and MCLineTableSymbols will be empty. 230 // Handle Compile Unit 0, the line table start symbol is the section symbol. 231 const MCSymbol *LineStartSym = EmitCU(MCOS, 0); 232 // Handle the rest of the Compile Units. 233 for (unsigned Is = 1, Ie = MCLineTableSymbols.size(); Is < Ie; Is++) 234 EmitCU(MCOS, Is); 235 236 // Now delete the MCLineSections that were created in MCLineEntry::Make() 237 // and used to emit the line table. 238 const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = 239 MCOS->getContext().getMCLineSections(); 240 for (DenseMap<const MCSection *, MCLineSection *>::const_iterator it = 241 MCLineSections.begin(), ie = MCLineSections.end(); it != ie; 242 ++it) 243 delete it->second; 244 245 return LineStartSym; 246} 247 248const MCSymbol *MCDwarfFileTable::EmitCU(MCStreamer *MCOS, unsigned CUID) { 249 MCContext &context = MCOS->getContext(); 250 251 // Create a symbol at the beginning of the line table. 252 MCSymbol *LineStartSym = MCOS->getContext().getMCLineTableSymbol(CUID); 253 if (!LineStartSym) 254 LineStartSym = context.CreateTempSymbol(); 255 // Set the value of the symbol, as we are at the start of the line table. 256 MCOS->EmitLabel(LineStartSym); 257 258 // Create a symbol for the end of the section (to be set when we get there). 259 MCSymbol *LineEndSym = context.CreateTempSymbol(); 260 261 // The first 4 bytes is the total length of the information for this 262 // compilation unit (not including these 4 bytes for the length). 263 MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4), 264 4); 265 266 // Next 2 bytes is the Version, which is Dwarf 2. 267 MCOS->EmitIntValue(2, 2); 268 269 // Create a symbol for the end of the prologue (to be set when we get there). 270 MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end 271 272 // Length of the prologue, is the next 4 bytes. Which is the start of the 273 // section to the end of the prologue. Not including the 4 bytes for the 274 // total length, the 2 bytes for the version, and these 4 bytes for the 275 // length of the prologue. 276 MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, 277 (4 + 2 + 4)), 4, 0); 278 279 // Parameters of the state machine, are next. 280 MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); 281 MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); 282 MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); 283 MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); 284 MCOS->EmitIntValue(DWARF2_LINE_OPCODE_BASE, 1); 285 286 // Standard opcode lengths 287 MCOS->EmitIntValue(0, 1); // length of DW_LNS_copy 288 MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_pc 289 MCOS->EmitIntValue(1, 1); // length of DW_LNS_advance_line 290 MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_file 291 MCOS->EmitIntValue(1, 1); // length of DW_LNS_set_column 292 MCOS->EmitIntValue(0, 1); // length of DW_LNS_negate_stmt 293 MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_basic_block 294 MCOS->EmitIntValue(0, 1); // length of DW_LNS_const_add_pc 295 MCOS->EmitIntValue(1, 1); // length of DW_LNS_fixed_advance_pc 296 MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_prologue_end 297 MCOS->EmitIntValue(0, 1); // length of DW_LNS_set_epilogue_begin 298 MCOS->EmitIntValue(1, 1); // DW_LNS_set_isa 299 300 // Put out the directory and file tables. 301 302 // First the directory table. 303 const SmallVectorImpl<StringRef> &MCDwarfDirs = 304 context.getMCDwarfDirs(CUID); 305 for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { 306 MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName 307 MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string 308 } 309 MCOS->EmitIntValue(0, 1); // Terminate the directory list 310 311 // Second the file table. 312 const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = 313 MCOS->getContext().getMCDwarfFiles(CUID); 314 for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { 315 MCOS->EmitBytes(MCDwarfFiles[i]->getName()); // FileName 316 MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string 317 // the Directory num 318 MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex()); 319 MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) 320 MCOS->EmitIntValue(0, 1); // filesize (always 0) 321 } 322 MCOS->EmitIntValue(0, 1); // Terminate the file list 323 324 // This is the end of the prologue, so set the value of the symbol at the 325 // end of the prologue (that was used in a previous expression). 326 MCOS->EmitLabel(ProEndSym); 327 328 // Put out the line tables. 329 const DenseMap<const MCSection *, MCLineSection *> &MCLineSections = 330 MCOS->getContext().getMCLineSections(); 331 const std::vector<const MCSection *> &MCLineSectionOrder = 332 MCOS->getContext().getMCLineSectionOrder(); 333 for (std::vector<const MCSection*>::const_iterator it = 334 MCLineSectionOrder.begin(), ie = MCLineSectionOrder.end(); it != ie; 335 ++it) { 336 const MCSection *Sec = *it; 337 const MCLineSection *Line = MCLineSections.lookup(Sec); 338 EmitDwarfLineTable(MCOS, Sec, Line, CUID); 339 } 340 341 if (MCOS->getContext().getAsmInfo().getLinkerRequiresNonEmptyDwarfLines() 342 && MCLineSectionOrder.begin() == MCLineSectionOrder.end()) { 343 // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures 344 // it requires: 345 // total_length >= prologue_length + 10 346 // We are 4 bytes short, since we have total_length = 51 and 347 // prologue_length = 45 348 349 // The regular end_sequence should be sufficient. 350 MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); 351 } 352 353 // This is the end of the section, so set the value of the symbol at the end 354 // of this section (that was used in a previous expression). 355 MCOS->EmitLabel(LineEndSym); 356 357 return LineStartSym; 358} 359 360/// Utility function to write the encoding to an object writer. 361void MCDwarfLineAddr::Write(MCObjectWriter *OW, int64_t LineDelta, 362 uint64_t AddrDelta) { 363 SmallString<256> Tmp; 364 raw_svector_ostream OS(Tmp); 365 MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); 366 OW->WriteBytes(OS.str()); 367} 368 369/// Utility function to emit the encoding to a streamer. 370void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, 371 uint64_t AddrDelta) { 372 SmallString<256> Tmp; 373 raw_svector_ostream OS(Tmp); 374 MCDwarfLineAddr::Encode(LineDelta, AddrDelta, OS); 375 MCOS->EmitBytes(OS.str()); 376} 377 378/// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 379void MCDwarfLineAddr::Encode(int64_t LineDelta, uint64_t AddrDelta, 380 raw_ostream &OS) { 381 uint64_t Temp, Opcode; 382 bool NeedCopy = false; 383 384 // Scale the address delta by the minimum instruction length. 385 AddrDelta = ScaleAddrDelta(AddrDelta); 386 387 // A LineDelta of INT64_MAX is a signal that this is actually a 388 // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the 389 // end_sequence to emit the matrix entry. 390 if (LineDelta == INT64_MAX) { 391 if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) 392 OS << char(dwarf::DW_LNS_const_add_pc); 393 else { 394 OS << char(dwarf::DW_LNS_advance_pc); 395 encodeULEB128(AddrDelta, OS); 396 } 397 OS << char(dwarf::DW_LNS_extended_op); 398 OS << char(1); 399 OS << char(dwarf::DW_LNE_end_sequence); 400 return; 401 } 402 403 // Bias the line delta by the base. 404 Temp = LineDelta - DWARF2_LINE_BASE; 405 406 // If the line increment is out of range of a special opcode, we must encode 407 // it with DW_LNS_advance_line. 408 if (Temp >= DWARF2_LINE_RANGE) { 409 OS << char(dwarf::DW_LNS_advance_line); 410 encodeSLEB128(LineDelta, OS); 411 412 LineDelta = 0; 413 Temp = 0 - DWARF2_LINE_BASE; 414 NeedCopy = true; 415 } 416 417 // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. 418 if (LineDelta == 0 && AddrDelta == 0) { 419 OS << char(dwarf::DW_LNS_copy); 420 return; 421 } 422 423 // Bias the opcode by the special opcode base. 424 Temp += DWARF2_LINE_OPCODE_BASE; 425 426 // Avoid overflow when addr_delta is large. 427 if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { 428 // Try using a special opcode. 429 Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; 430 if (Opcode <= 255) { 431 OS << char(Opcode); 432 return; 433 } 434 435 // Try using DW_LNS_const_add_pc followed by special op. 436 Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; 437 if (Opcode <= 255) { 438 OS << char(dwarf::DW_LNS_const_add_pc); 439 OS << char(Opcode); 440 return; 441 } 442 } 443 444 // Otherwise use DW_LNS_advance_pc. 445 OS << char(dwarf::DW_LNS_advance_pc); 446 encodeULEB128(AddrDelta, OS); 447 448 if (NeedCopy) 449 OS << char(dwarf::DW_LNS_copy); 450 else 451 OS << char(Temp); 452} 453 454void MCDwarfFile::print(raw_ostream &OS) const { 455 OS << '"' << getName() << '"'; 456} 457 458#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 459void MCDwarfFile::dump() const { 460 print(dbgs()); 461} 462#endif 463 464// Utility function to write a tuple for .debug_abbrev. 465static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) { 466 MCOS->EmitULEB128IntValue(Name); 467 MCOS->EmitULEB128IntValue(Form); 468} 469 470// When generating dwarf for assembly source files this emits 471// the data for .debug_abbrev section which contains three DIEs. 472static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { 473 MCContext &context = MCOS->getContext(); 474 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); 475 476 // DW_TAG_compile_unit DIE abbrev (1). 477 MCOS->EmitULEB128IntValue(1); 478 MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); 479 MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); 480 EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); 481 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); 482 EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); 483 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); 484 EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); 485 StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); 486 if (!DwarfDebugFlags.empty()) 487 EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string); 488 EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string); 489 EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2); 490 EmitAbbrev(MCOS, 0, 0); 491 492 // DW_TAG_label DIE abbrev (2). 493 MCOS->EmitULEB128IntValue(2); 494 MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label); 495 MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); 496 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); 497 EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4); 498 EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4); 499 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); 500 EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag); 501 EmitAbbrev(MCOS, 0, 0); 502 503 // DW_TAG_unspecified_parameters DIE abbrev (3). 504 MCOS->EmitULEB128IntValue(3); 505 MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters); 506 MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1); 507 EmitAbbrev(MCOS, 0, 0); 508 509 // Terminate the abbreviations for this compilation unit. 510 MCOS->EmitIntValue(0, 1); 511} 512 513// When generating dwarf for assembly source files this emits the data for 514// .debug_aranges section. Which contains a header and a table of pairs of 515// PointerSize'ed values for the address and size of section(s) with line table 516// entries (just the default .text in our case) and a terminating pair of zeros. 517static void EmitGenDwarfAranges(MCStreamer *MCOS, 518 const MCSymbol *InfoSectionSymbol) { 519 MCContext &context = MCOS->getContext(); 520 521 // Create a symbol at the end of the section that we are creating the dwarf 522 // debugging info to use later in here as part of the expression to calculate 523 // the size of the section for the table. 524 MCOS->SwitchSection(context.getGenDwarfSection()); 525 MCSymbol *SectionEndSym = context.CreateTempSymbol(); 526 MCOS->EmitLabel(SectionEndSym); 527 context.setGenDwarfSectionEndSym(SectionEndSym); 528 529 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); 530 531 // This will be the length of the .debug_aranges section, first account for 532 // the size of each item in the header (see below where we emit these items). 533 int Length = 4 + 2 + 4 + 1 + 1; 534 535 // Figure the padding after the header before the table of address and size 536 // pairs who's values are PointerSize'ed. 537 const MCAsmInfo &asmInfo = context.getAsmInfo(); 538 int AddrSize = asmInfo.getPointerSize(); 539 int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); 540 if (Pad == 2 * AddrSize) 541 Pad = 0; 542 Length += Pad; 543 544 // Add the size of the pair of PointerSize'ed values for the address and size 545 // of the one default .text section we have in the table. 546 Length += 2 * AddrSize; 547 // And the pair of terminating zeros. 548 Length += 2 * AddrSize; 549 550 551 // Emit the header for this section. 552 // The 4 byte length not including the 4 byte value for the length. 553 MCOS->EmitIntValue(Length - 4, 4); 554 // The 2 byte version, which is 2. 555 MCOS->EmitIntValue(2, 2); 556 // The 4 byte offset to the compile unit in the .debug_info from the start 557 // of the .debug_info. 558 if (InfoSectionSymbol) 559 MCOS->EmitSymbolValue(InfoSectionSymbol, 4); 560 else 561 MCOS->EmitIntValue(0, 4); 562 // The 1 byte size of an address. 563 MCOS->EmitIntValue(AddrSize, 1); 564 // The 1 byte size of a segment descriptor, we use a value of zero. 565 MCOS->EmitIntValue(0, 1); 566 // Align the header with the padding if needed, before we put out the table. 567 for(int i = 0; i < Pad; i++) 568 MCOS->EmitIntValue(0, 1); 569 570 // Now emit the table of pairs of PointerSize'ed values for the section(s) 571 // address and size, in our case just the one default .text section. 572 const MCExpr *Addr = MCSymbolRefExpr::Create( 573 context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); 574 const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, 575 *context.getGenDwarfSectionStartSym(), *SectionEndSym, 0); 576 MCOS->EmitAbsValue(Addr, AddrSize); 577 MCOS->EmitAbsValue(Size, AddrSize); 578 579 // And finally the pair of terminating zeros. 580 MCOS->EmitIntValue(0, AddrSize); 581 MCOS->EmitIntValue(0, AddrSize); 582} 583 584// When generating dwarf for assembly source files this emits the data for 585// .debug_info section which contains three parts. The header, the compile_unit 586// DIE and a list of label DIEs. 587static void EmitGenDwarfInfo(MCStreamer *MCOS, 588 const MCSymbol *AbbrevSectionSymbol, 589 const MCSymbol *LineSectionSymbol) { 590 MCContext &context = MCOS->getContext(); 591 592 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); 593 594 // Create a symbol at the start and end of this section used in here for the 595 // expression to calculate the length in the header. 596 MCSymbol *InfoStart = context.CreateTempSymbol(); 597 MCOS->EmitLabel(InfoStart); 598 MCSymbol *InfoEnd = context.CreateTempSymbol(); 599 600 // First part: the header. 601 602 // The 4 byte total length of the information for this compilation unit, not 603 // including these 4 bytes. 604 const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); 605 MCOS->EmitAbsValue(Length, 4); 606 607 // The 2 byte DWARF version, which is 2. 608 MCOS->EmitIntValue(2, 2); 609 610 // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, 611 // it is at the start of that section so this is zero. 612 if (AbbrevSectionSymbol) { 613 MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4); 614 } else { 615 MCOS->EmitIntValue(0, 4); 616 } 617 618 const MCAsmInfo &asmInfo = context.getAsmInfo(); 619 int AddrSize = asmInfo.getPointerSize(); 620 // The 1 byte size of an address. 621 MCOS->EmitIntValue(AddrSize, 1); 622 623 // Second part: the compile_unit DIE. 624 625 // The DW_TAG_compile_unit DIE abbrev (1). 626 MCOS->EmitULEB128IntValue(1); 627 628 // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, 629 // which is at the start of that section so this is zero. 630 if (LineSectionSymbol) { 631 MCOS->EmitSymbolValue(LineSectionSymbol, 4); 632 } else { 633 MCOS->EmitIntValue(0, 4); 634 } 635 636 // AT_low_pc, the first address of the default .text section. 637 const MCExpr *Start = MCSymbolRefExpr::Create( 638 context.getGenDwarfSectionStartSym(), MCSymbolRefExpr::VK_None, context); 639 MCOS->EmitAbsValue(Start, AddrSize); 640 641 // AT_high_pc, the last address of the default .text section. 642 const MCExpr *End = MCSymbolRefExpr::Create( 643 context.getGenDwarfSectionEndSym(), MCSymbolRefExpr::VK_None, context); 644 MCOS->EmitAbsValue(End, AddrSize); 645 646 // AT_name, the name of the source file. Reconstruct from the first directory 647 // and file table entries. 648 const SmallVectorImpl<StringRef> &MCDwarfDirs = 649 context.getMCDwarfDirs(); 650 if (MCDwarfDirs.size() > 0) { 651 MCOS->EmitBytes(MCDwarfDirs[0]); 652 MCOS->EmitBytes("/"); 653 } 654 const SmallVectorImpl<MCDwarfFile *> &MCDwarfFiles = 655 MCOS->getContext().getMCDwarfFiles(); 656 MCOS->EmitBytes(MCDwarfFiles[1]->getName()); 657 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 658 659 // AT_comp_dir, the working directory the assembly was done in. 660 MCOS->EmitBytes(context.getCompilationDir()); 661 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 662 663 // AT_APPLE_flags, the command line arguments of the assembler tool. 664 StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); 665 if (!DwarfDebugFlags.empty()){ 666 MCOS->EmitBytes(DwarfDebugFlags); 667 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 668 } 669 670 // AT_producer, the version of the assembler tool. 671 StringRef DwarfDebugProducer = context.getDwarfDebugProducer(); 672 if (!DwarfDebugProducer.empty()){ 673 MCOS->EmitBytes(DwarfDebugProducer); 674 } 675 else { 676 MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM ")); 677 MCOS->EmitBytes(StringRef(PACKAGE_VERSION)); 678 MCOS->EmitBytes(StringRef(")")); 679 } 680 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 681 682 // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 683 // draft has no standard code for assembler. 684 MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2); 685 686 // Third part: the list of label DIEs. 687 688 // Loop on saved info for dwarf labels and create the DIEs for them. 689 const std::vector<const MCGenDwarfLabelEntry *> &Entries = 690 MCOS->getContext().getMCGenDwarfLabelEntries(); 691 for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it = 692 Entries.begin(), ie = Entries.end(); it != ie; 693 ++it) { 694 const MCGenDwarfLabelEntry *Entry = *it; 695 696 // The DW_TAG_label DIE abbrev (2). 697 MCOS->EmitULEB128IntValue(2); 698 699 // AT_name, of the label without any leading underbar. 700 MCOS->EmitBytes(Entry->getName()); 701 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 702 703 // AT_decl_file, index into the file table. 704 MCOS->EmitIntValue(Entry->getFileNumber(), 4); 705 706 // AT_decl_line, source line number. 707 MCOS->EmitIntValue(Entry->getLineNumber(), 4); 708 709 // AT_low_pc, start address of the label. 710 const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry->getLabel(), 711 MCSymbolRefExpr::VK_None, context); 712 MCOS->EmitAbsValue(AT_low_pc, AddrSize); 713 714 // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype. 715 MCOS->EmitIntValue(0, 1); 716 717 // The DW_TAG_unspecified_parameters DIE abbrev (3). 718 MCOS->EmitULEB128IntValue(3); 719 720 // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's. 721 MCOS->EmitIntValue(0, 1); 722 } 723 // Deallocate the MCGenDwarfLabelEntry classes that saved away the info 724 // for the dwarf labels. 725 for (std::vector<const MCGenDwarfLabelEntry *>::const_iterator it = 726 Entries.begin(), ie = Entries.end(); it != ie; 727 ++it) { 728 const MCGenDwarfLabelEntry *Entry = *it; 729 delete Entry; 730 } 731 732 // Add the NULL DIE terminating the Compile Unit DIE's. 733 MCOS->EmitIntValue(0, 1); 734 735 // Now set the value of the symbol at the end of the info section. 736 MCOS->EmitLabel(InfoEnd); 737} 738 739// 740// When generating dwarf for assembly source files this emits the Dwarf 741// sections. 742// 743void MCGenDwarfInfo::Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol) { 744 // Create the dwarf sections in this order (.debug_line already created). 745 MCContext &context = MCOS->getContext(); 746 const MCAsmInfo &AsmInfo = context.getAsmInfo(); 747 bool CreateDwarfSectionSymbols = 748 AsmInfo.doesDwarfUseRelocationsAcrossSections(); 749 if (!CreateDwarfSectionSymbols) 750 LineSectionSymbol = NULL; 751 MCSymbol *AbbrevSectionSymbol = NULL; 752 MCSymbol *InfoSectionSymbol = NULL; 753 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); 754 if (CreateDwarfSectionSymbols) { 755 InfoSectionSymbol = context.CreateTempSymbol(); 756 MCOS->EmitLabel(InfoSectionSymbol); 757 } 758 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); 759 if (CreateDwarfSectionSymbols) { 760 AbbrevSectionSymbol = context.CreateTempSymbol(); 761 MCOS->EmitLabel(AbbrevSectionSymbol); 762 } 763 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); 764 765 // If there are no line table entries then do not emit any section contents. 766 if (context.getMCLineSections().empty()) 767 return; 768 769 // Output the data for .debug_aranges section. 770 EmitGenDwarfAranges(MCOS, InfoSectionSymbol); 771 772 // Output the data for .debug_abbrev section. 773 EmitGenDwarfAbbrev(MCOS); 774 775 // Output the data for .debug_info section. 776 EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol); 777} 778 779// 780// When generating dwarf for assembly source files this is called when symbol 781// for a label is created. If this symbol is not a temporary and is in the 782// section that dwarf is being generated for, save the needed info to create 783// a dwarf label. 784// 785void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, 786 SourceMgr &SrcMgr, SMLoc &Loc) { 787 // We won't create dwarf labels for temporary symbols or symbols not in 788 // the default text. 789 if (Symbol->isTemporary()) 790 return; 791 MCContext &context = MCOS->getContext(); 792 if (context.getGenDwarfSection() != MCOS->getCurrentSection().first) 793 return; 794 795 // The dwarf label's name does not have the symbol name's leading 796 // underbar if any. 797 StringRef Name = Symbol->getName(); 798 if (Name.startswith("_")) 799 Name = Name.substr(1, Name.size()-1); 800 801 // Get the dwarf file number to be used for the dwarf label. 802 unsigned FileNumber = context.getGenDwarfFileNumber(); 803 804 // Finding the line number is the expensive part which is why we just don't 805 // pass it in as for some symbols we won't create a dwarf label. 806 int CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); 807 unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); 808 809 // We create a temporary symbol for use for the AT_high_pc and AT_low_pc 810 // values so that they don't have things like an ARM thumb bit from the 811 // original symbol. So when used they won't get a low bit set after 812 // relocation. 813 MCSymbol *Label = context.CreateTempSymbol(); 814 MCOS->EmitLabel(Label); 815 816 // Create and entry for the info and add it to the other entries. 817 MCGenDwarfLabelEntry *Entry = 818 new MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label); 819 MCOS->getContext().addMCGenDwarfLabelEntry(Entry); 820} 821 822static int getDataAlignmentFactor(MCStreamer &streamer) { 823 MCContext &context = streamer.getContext(); 824 const MCAsmInfo &asmInfo = context.getAsmInfo(); 825 int size = asmInfo.getCalleeSaveStackSlotSize(); 826 if (asmInfo.isStackGrowthDirectionUp()) 827 return size; 828 else 829 return -size; 830} 831 832static unsigned getSizeForEncoding(MCStreamer &streamer, 833 unsigned symbolEncoding) { 834 MCContext &context = streamer.getContext(); 835 unsigned format = symbolEncoding & 0x0f; 836 switch (format) { 837 default: llvm_unreachable("Unknown Encoding"); 838 case dwarf::DW_EH_PE_absptr: 839 case dwarf::DW_EH_PE_signed: 840 return context.getAsmInfo().getPointerSize(); 841 case dwarf::DW_EH_PE_udata2: 842 case dwarf::DW_EH_PE_sdata2: 843 return 2; 844 case dwarf::DW_EH_PE_udata4: 845 case dwarf::DW_EH_PE_sdata4: 846 return 4; 847 case dwarf::DW_EH_PE_udata8: 848 case dwarf::DW_EH_PE_sdata8: 849 return 8; 850 } 851} 852 853static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, 854 unsigned symbolEncoding, const char *comment = 0) { 855 MCContext &context = streamer.getContext(); 856 const MCAsmInfo &asmInfo = context.getAsmInfo(); 857 const MCExpr *v = asmInfo.getExprForFDESymbol(&symbol, 858 symbolEncoding, 859 streamer); 860 unsigned size = getSizeForEncoding(streamer, symbolEncoding); 861 if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment); 862 streamer.EmitAbsValue(v, size); 863} 864 865static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, 866 unsigned symbolEncoding) { 867 MCContext &context = streamer.getContext(); 868 const MCAsmInfo &asmInfo = context.getAsmInfo(); 869 const MCExpr *v = asmInfo.getExprForPersonalitySymbol(&symbol, 870 symbolEncoding, 871 streamer); 872 unsigned size = getSizeForEncoding(streamer, symbolEncoding); 873 streamer.EmitValue(v, size); 874} 875 876static const MachineLocation TranslateMachineLocation( 877 const MCRegisterInfo &MRI, 878 const MachineLocation &Loc) { 879 unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? 880 MachineLocation::VirtualFP : 881 unsigned(MRI.getDwarfRegNum(Loc.getReg(), true)); 882 const MachineLocation &NewLoc = Loc.isReg() ? 883 MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); 884 return NewLoc; 885} 886 887namespace { 888 class FrameEmitterImpl { 889 int CFAOffset; 890 int CIENum; 891 bool UsingCFI; 892 bool IsEH; 893 const MCSymbol *SectionStart; 894 public: 895 FrameEmitterImpl(bool usingCFI, bool isEH) 896 : CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH), 897 SectionStart(0) {} 898 899 void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } 900 901 /// EmitCompactUnwind - Emit the unwind information in a compact way. If 902 /// we're successful, return 'true'. Otherwise, return 'false' and it will 903 /// emit the normal CIE and FDE. 904 void EmitCompactUnwind(MCStreamer &streamer, 905 const MCDwarfFrameInfo &frame); 906 907 const MCSymbol &EmitCIE(MCStreamer &streamer, 908 const MCSymbol *personality, 909 unsigned personalityEncoding, 910 const MCSymbol *lsda, 911 bool IsSignalFrame, 912 unsigned lsdaEncoding); 913 MCSymbol *EmitFDE(MCStreamer &streamer, 914 const MCSymbol &cieStart, 915 const MCDwarfFrameInfo &frame); 916 void EmitCFIInstructions(MCStreamer &streamer, 917 const std::vector<MCCFIInstruction> &Instrs, 918 MCSymbol *BaseLabel); 919 void EmitCFIInstruction(MCStreamer &Streamer, 920 const MCCFIInstruction &Instr); 921 }; 922 923} // end anonymous namespace 924 925static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding, 926 StringRef Prefix) { 927 if (Streamer.isVerboseAsm()) { 928 const char *EncStr; 929 switch (Encoding) { 930 default: EncStr = "<unknown encoding>"; break; 931 case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; break; 932 case dwarf::DW_EH_PE_omit: EncStr = "omit"; break; 933 case dwarf::DW_EH_PE_pcrel: EncStr = "pcrel"; break; 934 case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; break; 935 case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; break; 936 case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; break; 937 case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; break; 938 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: 939 EncStr = "pcrel udata4"; 940 break; 941 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: 942 EncStr = "pcrel sdata4"; 943 break; 944 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: 945 EncStr = "pcrel udata8"; 946 break; 947 case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: 948 EncStr = "screl sdata8"; 949 break; 950 case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4: 951 EncStr = "indirect pcrel udata4"; 952 break; 953 case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4: 954 EncStr = "indirect pcrel sdata4"; 955 break; 956 case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8: 957 EncStr = "indirect pcrel udata8"; 958 break; 959 case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8: 960 EncStr = "indirect pcrel sdata8"; 961 break; 962 } 963 964 Streamer.AddComment(Twine(Prefix) + " = " + EncStr); 965 } 966 967 Streamer.EmitIntValue(Encoding, 1); 968} 969 970void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, 971 const MCCFIInstruction &Instr) { 972 int dataAlignmentFactor = getDataAlignmentFactor(Streamer); 973 bool VerboseAsm = Streamer.isVerboseAsm(); 974 975 switch (Instr.getOperation()) { 976 case MCCFIInstruction::OpRegister: { 977 unsigned Reg1 = Instr.getRegister(); 978 unsigned Reg2 = Instr.getRegister2(); 979 if (VerboseAsm) { 980 Streamer.AddComment("DW_CFA_register"); 981 Streamer.AddComment(Twine("Reg1 ") + Twine(Reg1)); 982 Streamer.AddComment(Twine("Reg2 ") + Twine(Reg2)); 983 } 984 Streamer.EmitIntValue(dwarf::DW_CFA_register, 1); 985 Streamer.EmitULEB128IntValue(Reg1); 986 Streamer.EmitULEB128IntValue(Reg2); 987 return; 988 } 989 case MCCFIInstruction::OpUndefined: { 990 unsigned Reg = Instr.getRegister(); 991 if (VerboseAsm) { 992 Streamer.AddComment("DW_CFA_undefined"); 993 Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 994 } 995 Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); 996 Streamer.EmitULEB128IntValue(Reg); 997 return; 998 } 999 case MCCFIInstruction::OpAdjustCfaOffset: 1000 case MCCFIInstruction::OpDefCfaOffset: { 1001 const bool IsRelative = 1002 Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset; 1003 1004 if (VerboseAsm) 1005 Streamer.AddComment("DW_CFA_def_cfa_offset"); 1006 Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); 1007 1008 if (IsRelative) 1009 CFAOffset += Instr.getOffset(); 1010 else 1011 CFAOffset = -Instr.getOffset(); 1012 1013 if (VerboseAsm) 1014 Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); 1015 Streamer.EmitULEB128IntValue(CFAOffset); 1016 1017 return; 1018 } 1019 case MCCFIInstruction::OpDefCfa: { 1020 if (VerboseAsm) 1021 Streamer.AddComment("DW_CFA_def_cfa"); 1022 Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); 1023 1024 if (VerboseAsm) 1025 Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister())); 1026 Streamer.EmitULEB128IntValue(Instr.getRegister()); 1027 1028 CFAOffset = -Instr.getOffset(); 1029 1030 if (VerboseAsm) 1031 Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); 1032 Streamer.EmitULEB128IntValue(CFAOffset); 1033 1034 return; 1035 } 1036 1037 case MCCFIInstruction::OpDefCfaRegister: { 1038 if (VerboseAsm) 1039 Streamer.AddComment("DW_CFA_def_cfa_register"); 1040 Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); 1041 1042 if (VerboseAsm) 1043 Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister())); 1044 Streamer.EmitULEB128IntValue(Instr.getRegister()); 1045 1046 return; 1047 } 1048 1049 case MCCFIInstruction::OpOffset: 1050 case MCCFIInstruction::OpRelOffset: { 1051 const bool IsRelative = 1052 Instr.getOperation() == MCCFIInstruction::OpRelOffset; 1053 1054 unsigned Reg = Instr.getRegister(); 1055 int Offset = Instr.getOffset(); 1056 if (IsRelative) 1057 Offset -= CFAOffset; 1058 Offset = Offset / dataAlignmentFactor; 1059 1060 if (Offset < 0) { 1061 if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf"); 1062 Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); 1063 if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1064 Streamer.EmitULEB128IntValue(Reg); 1065 if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); 1066 Streamer.EmitSLEB128IntValue(Offset); 1067 } else if (Reg < 64) { 1068 if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") + 1069 Twine(Reg) + ")"); 1070 Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); 1071 if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); 1072 Streamer.EmitULEB128IntValue(Offset); 1073 } else { 1074 if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended"); 1075 Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); 1076 if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1077 Streamer.EmitULEB128IntValue(Reg); 1078 if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); 1079 Streamer.EmitULEB128IntValue(Offset); 1080 } 1081 return; 1082 } 1083 case MCCFIInstruction::OpRememberState: 1084 if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state"); 1085 Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); 1086 return; 1087 case MCCFIInstruction::OpRestoreState: 1088 if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state"); 1089 Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); 1090 return; 1091 case MCCFIInstruction::OpSameValue: { 1092 unsigned Reg = Instr.getRegister(); 1093 if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value"); 1094 Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); 1095 if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1096 Streamer.EmitULEB128IntValue(Reg); 1097 return; 1098 } 1099 case MCCFIInstruction::OpRestore: { 1100 unsigned Reg = Instr.getRegister(); 1101 if (VerboseAsm) { 1102 Streamer.AddComment("DW_CFA_restore"); 1103 Streamer.AddComment(Twine("Reg ") + Twine(Reg)); 1104 } 1105 Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); 1106 return; 1107 } 1108 case MCCFIInstruction::OpEscape: 1109 if (VerboseAsm) Streamer.AddComment("Escape bytes"); 1110 Streamer.EmitBytes(Instr.getValues()); 1111 return; 1112 } 1113 llvm_unreachable("Unhandled case in switch"); 1114} 1115 1116/// EmitFrameMoves - Emit frame instructions to describe the layout of the 1117/// frame. 1118void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, 1119 const std::vector<MCCFIInstruction> &Instrs, 1120 MCSymbol *BaseLabel) { 1121 for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { 1122 const MCCFIInstruction &Instr = Instrs[i]; 1123 MCSymbol *Label = Instr.getLabel(); 1124 // Throw out move if the label is invalid. 1125 if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. 1126 1127 // Advance row if new location. 1128 if (BaseLabel && Label) { 1129 MCSymbol *ThisSym = Label; 1130 if (ThisSym != BaseLabel) { 1131 if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4"); 1132 streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); 1133 BaseLabel = ThisSym; 1134 } 1135 } 1136 1137 EmitCFIInstruction(streamer, Instr); 1138 } 1139} 1140 1141/// EmitCompactUnwind - Emit the unwind information in a compact way. If we're 1142/// successful, return 'true'. Otherwise, return 'false' and it will emit the 1143/// normal CIE and FDE. 1144void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, 1145 const MCDwarfFrameInfo &Frame) { 1146 MCContext &Context = Streamer.getContext(); 1147 const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); 1148 bool VerboseAsm = Streamer.isVerboseAsm(); 1149 1150 // range-start range-length compact-unwind-enc personality-func lsda 1151 // _foo LfooEnd-_foo 0x00000023 0 0 1152 // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1 1153 // 1154 // .section __LD,__compact_unwind,regular,debug 1155 // 1156 // # compact unwind for _foo 1157 // .quad _foo 1158 // .set L1,LfooEnd-_foo 1159 // .long L1 1160 // .long 0x01010001 1161 // .quad 0 1162 // .quad 0 1163 // 1164 // # compact unwind for _bar 1165 // .quad _bar 1166 // .set L2,LbarEnd-_bar 1167 // .long L2 1168 // .long 0x01020011 1169 // .quad __gxx_personality 1170 // .quad except_tab1 1171 1172 uint32_t Encoding = Frame.CompactUnwindEncoding; 1173 if (!Encoding) return; 1174 bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly()); 1175 1176 // The encoding needs to know we have an LSDA. 1177 if (!DwarfEHFrameOnly && Frame.Lsda) 1178 Encoding |= 0x40000000; 1179 1180 // Range Start 1181 unsigned FDEEncoding = MOFI->getFDEEncoding(UsingCFI); 1182 unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); 1183 if (VerboseAsm) Streamer.AddComment("Range Start"); 1184 Streamer.EmitSymbolValue(Frame.Function, Size); 1185 1186 // Range Length 1187 const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, 1188 *Frame.End, 0); 1189 if (VerboseAsm) Streamer.AddComment("Range Length"); 1190 Streamer.EmitAbsValue(Range, 4); 1191 1192 // Compact Encoding 1193 Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); 1194 if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding: 0x" + 1195 Twine::utohexstr(Encoding)); 1196 Streamer.EmitIntValue(Encoding, Size); 1197 1198 // Personality Function 1199 Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); 1200 if (VerboseAsm) Streamer.AddComment("Personality Function"); 1201 if (!DwarfEHFrameOnly && Frame.Personality) 1202 Streamer.EmitSymbolValue(Frame.Personality, Size); 1203 else 1204 Streamer.EmitIntValue(0, Size); // No personality fn 1205 1206 // LSDA 1207 Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); 1208 if (VerboseAsm) Streamer.AddComment("LSDA"); 1209 if (!DwarfEHFrameOnly && Frame.Lsda) 1210 Streamer.EmitSymbolValue(Frame.Lsda, Size); 1211 else 1212 Streamer.EmitIntValue(0, Size); // No LSDA 1213} 1214 1215const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, 1216 const MCSymbol *personality, 1217 unsigned personalityEncoding, 1218 const MCSymbol *lsda, 1219 bool IsSignalFrame, 1220 unsigned lsdaEncoding) { 1221 MCContext &context = streamer.getContext(); 1222 const MCRegisterInfo &MRI = context.getRegisterInfo(); 1223 const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); 1224 bool verboseAsm = streamer.isVerboseAsm(); 1225 1226 MCSymbol *sectionStart; 1227 if (MOFI->isFunctionEHFrameSymbolPrivate() || !IsEH) 1228 sectionStart = context.CreateTempSymbol(); 1229 else 1230 sectionStart = context.GetOrCreateSymbol(Twine("EH_frame") + Twine(CIENum)); 1231 1232 streamer.EmitLabel(sectionStart); 1233 CIENum++; 1234 1235 MCSymbol *sectionEnd = context.CreateTempSymbol(); 1236 1237 // Length 1238 const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, 1239 *sectionEnd, 4); 1240 if (verboseAsm) streamer.AddComment("CIE Length"); 1241 streamer.EmitAbsValue(Length, 4); 1242 1243 // CIE ID 1244 unsigned CIE_ID = IsEH ? 0 : -1; 1245 if (verboseAsm) streamer.AddComment("CIE ID Tag"); 1246 streamer.EmitIntValue(CIE_ID, 4); 1247 1248 // Version 1249 if (verboseAsm) streamer.AddComment("DW_CIE_VERSION"); 1250 streamer.EmitIntValue(dwarf::DW_CIE_VERSION, 1); 1251 1252 // Augmentation String 1253 SmallString<8> Augmentation; 1254 if (IsEH) { 1255 if (verboseAsm) streamer.AddComment("CIE Augmentation"); 1256 Augmentation += "z"; 1257 if (personality) 1258 Augmentation += "P"; 1259 if (lsda) 1260 Augmentation += "L"; 1261 Augmentation += "R"; 1262 if (IsSignalFrame) 1263 Augmentation += "S"; 1264 streamer.EmitBytes(Augmentation.str()); 1265 } 1266 streamer.EmitIntValue(0, 1); 1267 1268 // Code Alignment Factor 1269 if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor"); 1270 streamer.EmitULEB128IntValue(1); 1271 1272 // Data Alignment Factor 1273 if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor"); 1274 streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); 1275 1276 // Return Address Register 1277 if (verboseAsm) streamer.AddComment("CIE Return Address Column"); 1278 streamer.EmitULEB128IntValue(MRI.getDwarfRegNum(MRI.getRARegister(), true)); 1279 1280 // Augmentation Data Length (optional) 1281 1282 unsigned augmentationLength = 0; 1283 if (IsEH) { 1284 if (personality) { 1285 // Personality Encoding 1286 augmentationLength += 1; 1287 // Personality 1288 augmentationLength += getSizeForEncoding(streamer, personalityEncoding); 1289 } 1290 if (lsda) 1291 augmentationLength += 1; 1292 // Encoding of the FDE pointers 1293 augmentationLength += 1; 1294 1295 if (verboseAsm) streamer.AddComment("Augmentation Size"); 1296 streamer.EmitULEB128IntValue(augmentationLength); 1297 1298 // Augmentation Data (optional) 1299 if (personality) { 1300 // Personality Encoding 1301 EmitEncodingByte(streamer, personalityEncoding, 1302 "Personality Encoding"); 1303 // Personality 1304 if (verboseAsm) streamer.AddComment("Personality"); 1305 EmitPersonality(streamer, *personality, personalityEncoding); 1306 } 1307 1308 if (lsda) 1309 EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding"); 1310 1311 // Encoding of the FDE pointers 1312 EmitEncodingByte(streamer, MOFI->getFDEEncoding(UsingCFI), 1313 "FDE Encoding"); 1314 } 1315 1316 // Initial Instructions 1317 1318 const MCAsmInfo &MAI = context.getAsmInfo(); 1319 const std::vector<MachineMove> &Moves = MAI.getInitialFrameState(); 1320 std::vector<MCCFIInstruction> Instructions; 1321 1322 for (int i = 0, n = Moves.size(); i != n; ++i) { 1323 MCSymbol *Label = Moves[i].getLabel(); 1324 const MachineLocation &Dst = 1325 TranslateMachineLocation(MRI, Moves[i].getDestination()); 1326 const MachineLocation &Src = 1327 TranslateMachineLocation(MRI, Moves[i].getSource()); 1328 1329 if (Dst.isReg()) { 1330 assert(Dst.getReg() == MachineLocation::VirtualFP); 1331 assert(!Src.isReg()); 1332 MCCFIInstruction Inst = 1333 MCCFIInstruction::createDefCfa(Label, Src.getReg(), -Src.getOffset()); 1334 Instructions.push_back(Inst); 1335 } else { 1336 assert(Src.isReg()); 1337 unsigned Reg = Src.getReg(); 1338 int Offset = Dst.getOffset(); 1339 MCCFIInstruction Inst = 1340 MCCFIInstruction::createOffset(Label, Reg, Offset); 1341 Instructions.push_back(Inst); 1342 } 1343 } 1344 1345 EmitCFIInstructions(streamer, Instructions, NULL); 1346 1347 // Padding 1348 streamer.EmitValueToAlignment(IsEH 1349 ? 4 : context.getAsmInfo().getPointerSize()); 1350 1351 streamer.EmitLabel(sectionEnd); 1352 return *sectionStart; 1353} 1354 1355MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, 1356 const MCSymbol &cieStart, 1357 const MCDwarfFrameInfo &frame) { 1358 MCContext &context = streamer.getContext(); 1359 MCSymbol *fdeStart = context.CreateTempSymbol(); 1360 MCSymbol *fdeEnd = context.CreateTempSymbol(); 1361 const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); 1362 bool verboseAsm = streamer.isVerboseAsm(); 1363 1364 if (IsEH && frame.Function && !MOFI->isFunctionEHFrameSymbolPrivate()) { 1365 MCSymbol *EHSym = 1366 context.GetOrCreateSymbol(frame.Function->getName() + Twine(".eh")); 1367 streamer.EmitEHSymAttributes(frame.Function, EHSym); 1368 streamer.EmitLabel(EHSym); 1369 } 1370 1371 // Length 1372 const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); 1373 if (verboseAsm) streamer.AddComment("FDE Length"); 1374 streamer.EmitAbsValue(Length, 4); 1375 1376 streamer.EmitLabel(fdeStart); 1377 1378 // CIE Pointer 1379 const MCAsmInfo &asmInfo = context.getAsmInfo(); 1380 if (IsEH) { 1381 const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 1382 0); 1383 if (verboseAsm) streamer.AddComment("FDE CIE Offset"); 1384 streamer.EmitAbsValue(offset, 4); 1385 } else if (!asmInfo.doesDwarfUseRelocationsAcrossSections()) { 1386 const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, 1387 cieStart, 0); 1388 streamer.EmitAbsValue(offset, 4); 1389 } else { 1390 streamer.EmitSymbolValue(&cieStart, 4); 1391 } 1392 1393 // PC Begin 1394 unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI) 1395 : (unsigned)dwarf::DW_EH_PE_absptr; 1396 unsigned PCSize = getSizeForEncoding(streamer, PCEncoding); 1397 EmitSymbol(streamer, *frame.Begin, PCEncoding, "FDE initial location"); 1398 1399 // PC Range 1400 const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, 1401 *frame.End, 0); 1402 if (verboseAsm) streamer.AddComment("FDE address range"); 1403 streamer.EmitAbsValue(Range, PCSize); 1404 1405 if (IsEH) { 1406 // Augmentation Data Length 1407 unsigned augmentationLength = 0; 1408 1409 if (frame.Lsda) 1410 augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); 1411 1412 if (verboseAsm) streamer.AddComment("Augmentation size"); 1413 streamer.EmitULEB128IntValue(augmentationLength); 1414 1415 // Augmentation Data 1416 if (frame.Lsda) 1417 EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding, 1418 "Language Specific Data Area"); 1419 } 1420 1421 // Call Frame Instructions 1422 EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); 1423 1424 // Padding 1425 streamer.EmitValueToAlignment(PCSize); 1426 1427 return fdeEnd; 1428} 1429 1430namespace { 1431 struct CIEKey { 1432 static const CIEKey getEmptyKey() { return CIEKey(0, 0, -1, false); } 1433 static const CIEKey getTombstoneKey() { return CIEKey(0, -1, 0, false); } 1434 1435 CIEKey(const MCSymbol* Personality_, unsigned PersonalityEncoding_, 1436 unsigned LsdaEncoding_, bool IsSignalFrame_) : 1437 Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), 1438 LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_) { 1439 } 1440 const MCSymbol* Personality; 1441 unsigned PersonalityEncoding; 1442 unsigned LsdaEncoding; 1443 bool IsSignalFrame; 1444 }; 1445} 1446 1447namespace llvm { 1448 template <> 1449 struct DenseMapInfo<CIEKey> { 1450 static CIEKey getEmptyKey() { 1451 return CIEKey::getEmptyKey(); 1452 } 1453 static CIEKey getTombstoneKey() { 1454 return CIEKey::getTombstoneKey(); 1455 } 1456 static unsigned getHashValue(const CIEKey &Key) { 1457 return static_cast<unsigned>(hash_combine(Key.Personality, 1458 Key.PersonalityEncoding, 1459 Key.LsdaEncoding, 1460 Key.IsSignalFrame)); 1461 } 1462 static bool isEqual(const CIEKey &LHS, 1463 const CIEKey &RHS) { 1464 return LHS.Personality == RHS.Personality && 1465 LHS.PersonalityEncoding == RHS.PersonalityEncoding && 1466 LHS.LsdaEncoding == RHS.LsdaEncoding && 1467 LHS.IsSignalFrame == RHS.IsSignalFrame; 1468 } 1469 }; 1470} 1471 1472void MCDwarfFrameEmitter::Emit(MCStreamer &Streamer, 1473 bool UsingCFI, 1474 bool IsEH) { 1475 MCContext &Context = Streamer.getContext(); 1476 MCObjectFileInfo *MOFI = 1477 const_cast<MCObjectFileInfo*>(Context.getObjectFileInfo()); 1478 FrameEmitterImpl Emitter(UsingCFI, IsEH); 1479 ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getFrameInfos(); 1480 1481 // Emit the compact unwind info if available. 1482 if (IsEH && MOFI->getCompactUnwindSection()) { 1483 unsigned NumFrameInfos = Streamer.getNumFrameInfos(); 1484 bool SectionEmitted = false; 1485 1486 if (NumFrameInfos) { 1487 for (unsigned i = 0; i < NumFrameInfos; ++i) { 1488 const MCDwarfFrameInfo &Frame = Streamer.getFrameInfo(i); 1489 if (Frame.CompactUnwindEncoding == 0) continue; 1490 if (!SectionEmitted) { 1491 Streamer.SwitchSection(MOFI->getCompactUnwindSection()); 1492 Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize()); 1493 SectionEmitted = true; 1494 } 1495 Emitter.EmitCompactUnwind(Streamer, Frame); 1496 } 1497 } 1498 } 1499 1500 const MCSection &Section = IsEH ? *MOFI->getEHFrameSection() : 1501 *MOFI->getDwarfFrameSection(); 1502 Streamer.SwitchSection(&Section); 1503 MCSymbol *SectionStart = Context.CreateTempSymbol(); 1504 Streamer.EmitLabel(SectionStart); 1505 Emitter.setSectionStart(SectionStart); 1506 1507 MCSymbol *FDEEnd = NULL; 1508 DenseMap<CIEKey, const MCSymbol*> CIEStarts; 1509 1510 const MCSymbol *DummyDebugKey = NULL; 1511 for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { 1512 const MCDwarfFrameInfo &Frame = FrameArray[i]; 1513 CIEKey Key(Frame.Personality, Frame.PersonalityEncoding, 1514 Frame.LsdaEncoding, Frame.IsSignalFrame); 1515 const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; 1516 if (!CIEStart) 1517 CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality, 1518 Frame.PersonalityEncoding, Frame.Lsda, 1519 Frame.IsSignalFrame, 1520 Frame.LsdaEncoding); 1521 1522 FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame); 1523 1524 if (i != n - 1) 1525 Streamer.EmitLabel(FDEEnd); 1526 } 1527 1528 Streamer.EmitValueToAlignment(Context.getAsmInfo().getPointerSize()); 1529 if (FDEEnd) 1530 Streamer.EmitLabel(FDEEnd); 1531} 1532 1533void MCDwarfFrameEmitter::EmitAdvanceLoc(MCStreamer &Streamer, 1534 uint64_t AddrDelta) { 1535 SmallString<256> Tmp; 1536 raw_svector_ostream OS(Tmp); 1537 MCDwarfFrameEmitter::EncodeAdvanceLoc(AddrDelta, OS); 1538 Streamer.EmitBytes(OS.str()); 1539} 1540 1541void MCDwarfFrameEmitter::EncodeAdvanceLoc(uint64_t AddrDelta, 1542 raw_ostream &OS) { 1543 // FIXME: Assumes the code alignment factor is 1. 1544 if (AddrDelta == 0) { 1545 } else if (isUIntN(6, AddrDelta)) { 1546 uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; 1547 OS << Opcode; 1548 } else if (isUInt<8>(AddrDelta)) { 1549 OS << uint8_t(dwarf::DW_CFA_advance_loc1); 1550 OS << uint8_t(AddrDelta); 1551 } else if (isUInt<16>(AddrDelta)) { 1552 // FIXME: check what is the correct behavior on a big endian machine. 1553 OS << uint8_t(dwarf::DW_CFA_advance_loc2); 1554 OS << uint8_t( AddrDelta & 0xff); 1555 OS << uint8_t((AddrDelta >> 8) & 0xff); 1556 } else { 1557 // FIXME: check what is the correct behavior on a big endian machine. 1558 assert(isUInt<32>(AddrDelta)); 1559 OS << uint8_t(dwarf::DW_CFA_advance_loc4); 1560 OS << uint8_t( AddrDelta & 0xff); 1561 OS << uint8_t((AddrDelta >> 8) & 0xff); 1562 OS << uint8_t((AddrDelta >> 16) & 0xff); 1563 OS << uint8_t((AddrDelta >> 24) & 0xff); 1564 1565 } 1566} 1567