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