LLVM API Documentation
00001 //===- lib/MC/MCDwarf.cpp - MCDwarf implementation ------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "llvm/MC/MCDwarf.h" 00011 #include "llvm/ADT/Hashing.h" 00012 #include "llvm/ADT/STLExtras.h" 00013 #include "llvm/ADT/SmallString.h" 00014 #include "llvm/ADT/Twine.h" 00015 #include "llvm/Config/config.h" 00016 #include "llvm/MC/MCAsmInfo.h" 00017 #include "llvm/MC/MCContext.h" 00018 #include "llvm/MC/MCExpr.h" 00019 #include "llvm/MC/MCObjectFileInfo.h" 00020 #include "llvm/MC/MCObjectStreamer.h" 00021 #include "llvm/MC/MCRegisterInfo.h" 00022 #include "llvm/MC/MCSection.h" 00023 #include "llvm/MC/MCSymbol.h" 00024 #include "llvm/Support/Debug.h" 00025 #include "llvm/Support/ErrorHandling.h" 00026 #include "llvm/Support/LEB128.h" 00027 #include "llvm/Support/Path.h" 00028 #include "llvm/Support/SourceMgr.h" 00029 #include "llvm/Support/raw_ostream.h" 00030 using namespace llvm; 00031 00032 // Given a special op, return the address skip amount (in units of 00033 // DWARF2_LINE_MIN_INSN_LENGTH. 00034 #define SPECIAL_ADDR(op) (((op) - DWARF2_LINE_OPCODE_BASE)/DWARF2_LINE_RANGE) 00035 00036 // The maximum address skip amount that can be encoded with a special op. 00037 #define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255) 00038 00039 // First special line opcode - leave room for the standard opcodes. 00040 // Note: If you want to change this, you'll have to update the 00041 // "standard_opcode_lengths" table that is emitted in DwarfFileTable::Emit(). 00042 #define DWARF2_LINE_OPCODE_BASE 13 00043 00044 // Minimum line offset in a special line info. opcode. This value 00045 // was chosen to give a reasonable range of values. 00046 #define DWARF2_LINE_BASE -5 00047 00048 // Range of line offsets in a special line info. opcode. 00049 #define DWARF2_LINE_RANGE 14 00050 00051 static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) { 00052 unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment(); 00053 if (MinInsnLength == 1) 00054 return AddrDelta; 00055 if (AddrDelta % MinInsnLength != 0) { 00056 // TODO: report this error, but really only once. 00057 ; 00058 } 00059 return AddrDelta / MinInsnLength; 00060 } 00061 00062 // 00063 // This is called when an instruction is assembled into the specified section 00064 // and if there is information from the last .loc directive that has yet to have 00065 // a line entry made for it is made. 00066 // 00067 void MCLineEntry::Make(MCObjectStreamer *MCOS, const MCSection *Section) { 00068 if (!MCOS->getContext().getDwarfLocSeen()) 00069 return; 00070 00071 // Create a symbol at in the current section for use in the line entry. 00072 MCSymbol *LineSym = MCOS->getContext().CreateTempSymbol(); 00073 // Set the value of the symbol to use for the MCLineEntry. 00074 MCOS->EmitLabel(LineSym); 00075 00076 // Get the current .loc info saved in the context. 00077 const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc(); 00078 00079 // Create a (local) line entry with the symbol and the current .loc info. 00080 MCLineEntry LineEntry(LineSym, DwarfLoc); 00081 00082 // clear DwarfLocSeen saying the current .loc info is now used. 00083 MCOS->getContext().ClearDwarfLocSeen(); 00084 00085 // Add the line entry to this section's entries. 00086 MCOS->getContext() 00087 .getMCDwarfLineTable(MCOS->getContext().getDwarfCompileUnitID()) 00088 .getMCLineSections() 00089 .addLineEntry(LineEntry, Section); 00090 } 00091 00092 // 00093 // This helper routine returns an expression of End - Start + IntVal . 00094 // 00095 static inline const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS, 00096 const MCSymbol &Start, 00097 const MCSymbol &End, 00098 int IntVal) { 00099 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 00100 const MCExpr *Res = 00101 MCSymbolRefExpr::Create(&End, Variant, MCOS.getContext()); 00102 const MCExpr *RHS = 00103 MCSymbolRefExpr::Create(&Start, Variant, MCOS.getContext()); 00104 const MCExpr *Res1 = 00105 MCBinaryExpr::Create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext()); 00106 const MCExpr *Res2 = 00107 MCConstantExpr::Create(IntVal, MCOS.getContext()); 00108 const MCExpr *Res3 = 00109 MCBinaryExpr::Create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext()); 00110 return Res3; 00111 } 00112 00113 // 00114 // This emits the Dwarf line table for the specified section from the entries 00115 // in the LineSection. 00116 // 00117 static inline void 00118 EmitDwarfLineTable(MCObjectStreamer *MCOS, const MCSection *Section, 00119 const MCLineSection::MCLineEntryCollection &LineEntries) { 00120 unsigned FileNum = 1; 00121 unsigned LastLine = 1; 00122 unsigned Column = 0; 00123 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 00124 unsigned Isa = 0; 00125 unsigned Discriminator = 0; 00126 MCSymbol *LastLabel = nullptr; 00127 00128 // Loop through each MCLineEntry and encode the dwarf line number table. 00129 for (auto it = LineEntries.begin(), 00130 ie = LineEntries.end(); 00131 it != ie; ++it) { 00132 00133 if (FileNum != it->getFileNum()) { 00134 FileNum = it->getFileNum(); 00135 MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1); 00136 MCOS->EmitULEB128IntValue(FileNum); 00137 } 00138 if (Column != it->getColumn()) { 00139 Column = it->getColumn(); 00140 MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1); 00141 MCOS->EmitULEB128IntValue(Column); 00142 } 00143 if (Discriminator != it->getDiscriminator()) { 00144 Discriminator = it->getDiscriminator(); 00145 unsigned Size = getULEB128Size(Discriminator); 00146 MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); 00147 MCOS->EmitULEB128IntValue(Size + 1); 00148 MCOS->EmitIntValue(dwarf::DW_LNE_set_discriminator, 1); 00149 MCOS->EmitULEB128IntValue(Discriminator); 00150 } 00151 if (Isa != it->getIsa()) { 00152 Isa = it->getIsa(); 00153 MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); 00154 MCOS->EmitULEB128IntValue(Isa); 00155 } 00156 if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 00157 Flags = it->getFlags(); 00158 MCOS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); 00159 } 00160 if (it->getFlags() & DWARF2_FLAG_BASIC_BLOCK) 00161 MCOS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); 00162 if (it->getFlags() & DWARF2_FLAG_PROLOGUE_END) 00163 MCOS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); 00164 if (it->getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 00165 MCOS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); 00166 00167 int64_t LineDelta = static_cast<int64_t>(it->getLine()) - LastLine; 00168 MCSymbol *Label = it->getLabel(); 00169 00170 // At this point we want to emit/create the sequence to encode the delta in 00171 // line numbers and the increment of the address from the previous Label 00172 // and the current Label. 00173 const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); 00174 MCOS->EmitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 00175 asmInfo->getPointerSize()); 00176 00177 LastLine = it->getLine(); 00178 LastLabel = Label; 00179 } 00180 00181 // Emit a DW_LNE_end_sequence for the end of the section. 00182 // Using the pointer Section create a temporary label at the end of the 00183 // section and use that and the LastLabel to compute the address delta 00184 // and use INT64_MAX as the line delta which is the signal that this is 00185 // actually a DW_LNE_end_sequence. 00186 00187 // Switch to the section to be able to create a symbol at its end. 00188 // TODO: keep track of the last subsection so that this symbol appears in the 00189 // correct place. 00190 MCOS->SwitchSection(Section); 00191 00192 MCContext &context = MCOS->getContext(); 00193 // Create a symbol at the end of the section. 00194 MCSymbol *SectionEnd = context.CreateTempSymbol(); 00195 // Set the value of the symbol, as we are at the end of the section. 00196 MCOS->EmitLabel(SectionEnd); 00197 00198 // Switch back the dwarf line section. 00199 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); 00200 00201 const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo(); 00202 MCOS->EmitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, 00203 asmInfo->getPointerSize()); 00204 } 00205 00206 // 00207 // This emits the Dwarf file and the line tables. 00208 // 00209 void MCDwarfLineTable::Emit(MCObjectStreamer *MCOS) { 00210 MCContext &context = MCOS->getContext(); 00211 00212 auto &LineTables = context.getMCDwarfLineTables(); 00213 00214 // Bail out early so we don't switch to the debug_line section needlessly and 00215 // in doing so create an unnecessary (if empty) section. 00216 if (LineTables.empty()) 00217 return; 00218 00219 // Switch to the section where the table will be emitted into. 00220 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); 00221 00222 // Handle the rest of the Compile Units. 00223 for (const auto &CUIDTablePair : LineTables) 00224 CUIDTablePair.second.EmitCU(MCOS); 00225 } 00226 00227 void MCDwarfDwoLineTable::Emit(MCStreamer &MCOS) const { 00228 MCOS.EmitLabel(Header.Emit(&MCOS, None).second); 00229 } 00230 00231 std::pair<MCSymbol *, MCSymbol *> MCDwarfLineTableHeader::Emit(MCStreamer *MCOS) const { 00232 static const char StandardOpcodeLengths[] = { 00233 0, // length of DW_LNS_copy 00234 1, // length of DW_LNS_advance_pc 00235 1, // length of DW_LNS_advance_line 00236 1, // length of DW_LNS_set_file 00237 1, // length of DW_LNS_set_column 00238 0, // length of DW_LNS_negate_stmt 00239 0, // length of DW_LNS_set_basic_block 00240 0, // length of DW_LNS_const_add_pc 00241 1, // length of DW_LNS_fixed_advance_pc 00242 0, // length of DW_LNS_set_prologue_end 00243 0, // length of DW_LNS_set_epilogue_begin 00244 1 // DW_LNS_set_isa 00245 }; 00246 assert(array_lengthof(StandardOpcodeLengths) == (DWARF2_LINE_OPCODE_BASE - 1)); 00247 return Emit(MCOS, StandardOpcodeLengths); 00248 } 00249 00250 static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { 00251 MCContext &Context = OS.getContext(); 00252 assert(!isa<MCSymbolRefExpr>(Expr)); 00253 if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) 00254 return Expr; 00255 00256 MCSymbol *ABS = Context.CreateTempSymbol(); 00257 OS.EmitAssignment(ABS, Expr); 00258 return MCSymbolRefExpr::Create(ABS, Context); 00259 } 00260 00261 static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { 00262 const MCExpr *ABS = forceExpAbs(OS, Value); 00263 OS.EmitValue(ABS, Size); 00264 } 00265 00266 std::pair<MCSymbol *, MCSymbol *> 00267 MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, 00268 ArrayRef<char> StandardOpcodeLengths) const { 00269 00270 MCContext &context = MCOS->getContext(); 00271 00272 // Create a symbol at the beginning of the line table. 00273 MCSymbol *LineStartSym = Label; 00274 if (!LineStartSym) 00275 LineStartSym = context.CreateTempSymbol(); 00276 // Set the value of the symbol, as we are at the start of the line table. 00277 MCOS->EmitLabel(LineStartSym); 00278 00279 // Create a symbol for the end of the section (to be set when we get there). 00280 MCSymbol *LineEndSym = context.CreateTempSymbol(); 00281 00282 // The first 4 bytes is the total length of the information for this 00283 // compilation unit (not including these 4 bytes for the length). 00284 emitAbsValue(*MCOS, 00285 MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4); 00286 00287 // Next 2 bytes is the Version, which is Dwarf 2. 00288 MCOS->EmitIntValue(2, 2); 00289 00290 // Create a symbol for the end of the prologue (to be set when we get there). 00291 MCSymbol *ProEndSym = context.CreateTempSymbol(); // Lprologue_end 00292 00293 // Length of the prologue, is the next 4 bytes. Which is the start of the 00294 // section to the end of the prologue. Not including the 4 bytes for the 00295 // total length, the 2 bytes for the version, and these 4 bytes for the 00296 // length of the prologue. 00297 emitAbsValue( 00298 *MCOS, 00299 MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, (4 + 2 + 4)), 4); 00300 00301 // Parameters of the state machine, are next. 00302 MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1); 00303 MCOS->EmitIntValue(DWARF2_LINE_DEFAULT_IS_STMT, 1); 00304 MCOS->EmitIntValue(DWARF2_LINE_BASE, 1); 00305 MCOS->EmitIntValue(DWARF2_LINE_RANGE, 1); 00306 MCOS->EmitIntValue(StandardOpcodeLengths.size() + 1, 1); 00307 00308 // Standard opcode lengths 00309 for (char Length : StandardOpcodeLengths) 00310 MCOS->EmitIntValue(Length, 1); 00311 00312 // Put out the directory and file tables. 00313 00314 // First the directory table. 00315 for (unsigned i = 0; i < MCDwarfDirs.size(); i++) { 00316 MCOS->EmitBytes(MCDwarfDirs[i]); // the DirectoryName 00317 MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string 00318 } 00319 MCOS->EmitIntValue(0, 1); // Terminate the directory list 00320 00321 // Second the file table. 00322 for (unsigned i = 1; i < MCDwarfFiles.size(); i++) { 00323 assert(!MCDwarfFiles[i].Name.empty()); 00324 MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName 00325 MCOS->EmitBytes(StringRef("\0", 1)); // the null term. of the string 00326 // the Directory num 00327 MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); 00328 MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0) 00329 MCOS->EmitIntValue(0, 1); // filesize (always 0) 00330 } 00331 MCOS->EmitIntValue(0, 1); // Terminate the file list 00332 00333 // This is the end of the prologue, so set the value of the symbol at the 00334 // end of the prologue (that was used in a previous expression). 00335 MCOS->EmitLabel(ProEndSym); 00336 00337 return std::make_pair(LineStartSym, LineEndSym); 00338 } 00339 00340 void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS) const { 00341 MCSymbol *LineEndSym = Header.Emit(MCOS).second; 00342 00343 // Put out the line tables. 00344 for (const auto &LineSec : MCLineSections.getMCLineEntries()) 00345 EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 00346 00347 if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines() && 00348 MCLineSections.getMCLineEntries().empty()) { 00349 // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures 00350 // it requires: 00351 // total_length >= prologue_length + 10 00352 // We are 4 bytes short, since we have total_length = 51 and 00353 // prologue_length = 45 00354 00355 // The regular end_sequence should be sufficient. 00356 MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); 00357 } 00358 00359 // This is the end of the section, so set the value of the symbol at the end 00360 // of this section (that was used in a previous expression). 00361 MCOS->EmitLabel(LineEndSym); 00362 } 00363 00364 unsigned MCDwarfLineTable::getFile(StringRef &Directory, StringRef &FileName, 00365 unsigned FileNumber) { 00366 return Header.getFile(Directory, FileName, FileNumber); 00367 } 00368 00369 unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory, 00370 StringRef &FileName, 00371 unsigned FileNumber) { 00372 if (Directory == CompilationDir) 00373 Directory = ""; 00374 if (FileName.empty()) { 00375 FileName = "<stdin>"; 00376 Directory = ""; 00377 } 00378 assert(!FileName.empty()); 00379 if (FileNumber == 0) { 00380 FileNumber = SourceIdMap.size() + 1; 00381 assert((MCDwarfFiles.empty() || FileNumber == MCDwarfFiles.size()) && 00382 "Don't mix autonumbered and explicit numbered line table usage"); 00383 StringMapEntry<unsigned> &Ent = SourceIdMap.GetOrCreateValue( 00384 (Directory + Twine('\0') + FileName).str(), FileNumber); 00385 if (Ent.getValue() != FileNumber) 00386 return Ent.getValue(); 00387 } 00388 // Make space for this FileNumber in the MCDwarfFiles vector if needed. 00389 MCDwarfFiles.resize(FileNumber + 1); 00390 00391 // Get the new MCDwarfFile slot for this FileNumber. 00392 MCDwarfFile &File = MCDwarfFiles[FileNumber]; 00393 00394 // It is an error to use see the same number more than once. 00395 if (!File.Name.empty()) 00396 return 0; 00397 00398 if (Directory.empty()) { 00399 // Separate the directory part from the basename of the FileName. 00400 StringRef tFileName = sys::path::filename(FileName); 00401 if (!tFileName.empty()) { 00402 Directory = sys::path::parent_path(FileName); 00403 if (!Directory.empty()) 00404 FileName = tFileName; 00405 } 00406 } 00407 00408 // Find or make an entry in the MCDwarfDirs vector for this Directory. 00409 // Capture directory name. 00410 unsigned DirIndex; 00411 if (Directory.empty()) { 00412 // For FileNames with no directories a DirIndex of 0 is used. 00413 DirIndex = 0; 00414 } else { 00415 DirIndex = 0; 00416 for (unsigned End = MCDwarfDirs.size(); DirIndex < End; DirIndex++) { 00417 if (Directory == MCDwarfDirs[DirIndex]) 00418 break; 00419 } 00420 if (DirIndex >= MCDwarfDirs.size()) 00421 MCDwarfDirs.push_back(Directory); 00422 // The DirIndex is one based, as DirIndex of 0 is used for FileNames with 00423 // no directories. MCDwarfDirs[] is unlike MCDwarfFiles[] in that the 00424 // directory names are stored at MCDwarfDirs[DirIndex-1] where FileNames 00425 // are stored at MCDwarfFiles[FileNumber].Name . 00426 DirIndex++; 00427 } 00428 00429 File.Name = FileName; 00430 File.DirIndex = DirIndex; 00431 00432 // return the allocated FileNumber. 00433 return FileNumber; 00434 } 00435 00436 /// Utility function to emit the encoding to a streamer. 00437 void MCDwarfLineAddr::Emit(MCStreamer *MCOS, int64_t LineDelta, 00438 uint64_t AddrDelta) { 00439 MCContext &Context = MCOS->getContext(); 00440 SmallString<256> Tmp; 00441 raw_svector_ostream OS(Tmp); 00442 MCDwarfLineAddr::Encode(Context, LineDelta, AddrDelta, OS); 00443 MCOS->EmitBytes(OS.str()); 00444 } 00445 00446 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 00447 void MCDwarfLineAddr::Encode(MCContext &Context, int64_t LineDelta, 00448 uint64_t AddrDelta, raw_ostream &OS) { 00449 uint64_t Temp, Opcode; 00450 bool NeedCopy = false; 00451 00452 // Scale the address delta by the minimum instruction length. 00453 AddrDelta = ScaleAddrDelta(Context, AddrDelta); 00454 00455 // A LineDelta of INT64_MAX is a signal that this is actually a 00456 // DW_LNE_end_sequence. We cannot use special opcodes here, since we want the 00457 // end_sequence to emit the matrix entry. 00458 if (LineDelta == INT64_MAX) { 00459 if (AddrDelta == MAX_SPECIAL_ADDR_DELTA) 00460 OS << char(dwarf::DW_LNS_const_add_pc); 00461 else { 00462 OS << char(dwarf::DW_LNS_advance_pc); 00463 encodeULEB128(AddrDelta, OS); 00464 } 00465 OS << char(dwarf::DW_LNS_extended_op); 00466 OS << char(1); 00467 OS << char(dwarf::DW_LNE_end_sequence); 00468 return; 00469 } 00470 00471 // Bias the line delta by the base. 00472 Temp = LineDelta - DWARF2_LINE_BASE; 00473 00474 // If the line increment is out of range of a special opcode, we must encode 00475 // it with DW_LNS_advance_line. 00476 if (Temp >= DWARF2_LINE_RANGE) { 00477 OS << char(dwarf::DW_LNS_advance_line); 00478 encodeSLEB128(LineDelta, OS); 00479 00480 LineDelta = 0; 00481 Temp = 0 - DWARF2_LINE_BASE; 00482 NeedCopy = true; 00483 } 00484 00485 // Use DW_LNS_copy instead of a "line +0, addr +0" special opcode. 00486 if (LineDelta == 0 && AddrDelta == 0) { 00487 OS << char(dwarf::DW_LNS_copy); 00488 return; 00489 } 00490 00491 // Bias the opcode by the special opcode base. 00492 Temp += DWARF2_LINE_OPCODE_BASE; 00493 00494 // Avoid overflow when addr_delta is large. 00495 if (AddrDelta < 256 + MAX_SPECIAL_ADDR_DELTA) { 00496 // Try using a special opcode. 00497 Opcode = Temp + AddrDelta * DWARF2_LINE_RANGE; 00498 if (Opcode <= 255) { 00499 OS << char(Opcode); 00500 return; 00501 } 00502 00503 // Try using DW_LNS_const_add_pc followed by special op. 00504 Opcode = Temp + (AddrDelta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE; 00505 if (Opcode <= 255) { 00506 OS << char(dwarf::DW_LNS_const_add_pc); 00507 OS << char(Opcode); 00508 return; 00509 } 00510 } 00511 00512 // Otherwise use DW_LNS_advance_pc. 00513 OS << char(dwarf::DW_LNS_advance_pc); 00514 encodeULEB128(AddrDelta, OS); 00515 00516 if (NeedCopy) 00517 OS << char(dwarf::DW_LNS_copy); 00518 else 00519 OS << char(Temp); 00520 } 00521 00522 // Utility function to write a tuple for .debug_abbrev. 00523 static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form) { 00524 MCOS->EmitULEB128IntValue(Name); 00525 MCOS->EmitULEB128IntValue(Form); 00526 } 00527 00528 // When generating dwarf for assembly source files this emits 00529 // the data for .debug_abbrev section which contains three DIEs. 00530 static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { 00531 MCContext &context = MCOS->getContext(); 00532 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); 00533 00534 // DW_TAG_compile_unit DIE abbrev (1). 00535 MCOS->EmitULEB128IntValue(1); 00536 MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); 00537 MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); 00538 EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); 00539 if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1) { 00540 EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4); 00541 } else { 00542 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); 00543 EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr); 00544 } 00545 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); 00546 if (!context.getCompilationDir().empty()) 00547 EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string); 00548 StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); 00549 if (!DwarfDebugFlags.empty()) 00550 EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string); 00551 EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string); 00552 EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2); 00553 EmitAbbrev(MCOS, 0, 0); 00554 00555 // DW_TAG_label DIE abbrev (2). 00556 MCOS->EmitULEB128IntValue(2); 00557 MCOS->EmitULEB128IntValue(dwarf::DW_TAG_label); 00558 MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); 00559 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string); 00560 EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4); 00561 EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4); 00562 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); 00563 EmitAbbrev(MCOS, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag); 00564 EmitAbbrev(MCOS, 0, 0); 00565 00566 // DW_TAG_unspecified_parameters DIE abbrev (3). 00567 MCOS->EmitULEB128IntValue(3); 00568 MCOS->EmitULEB128IntValue(dwarf::DW_TAG_unspecified_parameters); 00569 MCOS->EmitIntValue(dwarf::DW_CHILDREN_no, 1); 00570 EmitAbbrev(MCOS, 0, 0); 00571 00572 // Terminate the abbreviations for this compilation unit. 00573 MCOS->EmitIntValue(0, 1); 00574 } 00575 00576 // When generating dwarf for assembly source files this emits the data for 00577 // .debug_aranges section. This section contains a header and a table of pairs 00578 // of PointerSize'ed values for the address and size of section(s) with line 00579 // table entries. 00580 static void EmitGenDwarfAranges(MCStreamer *MCOS, 00581 const MCSymbol *InfoSectionSymbol) { 00582 MCContext &context = MCOS->getContext(); 00583 00584 auto &Sections = context.getGenDwarfSectionSyms(); 00585 00586 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); 00587 00588 // This will be the length of the .debug_aranges section, first account for 00589 // the size of each item in the header (see below where we emit these items). 00590 int Length = 4 + 2 + 4 + 1 + 1; 00591 00592 // Figure the padding after the header before the table of address and size 00593 // pairs who's values are PointerSize'ed. 00594 const MCAsmInfo *asmInfo = context.getAsmInfo(); 00595 int AddrSize = asmInfo->getPointerSize(); 00596 int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1)); 00597 if (Pad == 2 * AddrSize) 00598 Pad = 0; 00599 Length += Pad; 00600 00601 // Add the size of the pair of PointerSize'ed values for the address and size 00602 // of each section we have in the table. 00603 Length += 2 * AddrSize * Sections.size(); 00604 // And the pair of terminating zeros. 00605 Length += 2 * AddrSize; 00606 00607 00608 // Emit the header for this section. 00609 // The 4 byte length not including the 4 byte value for the length. 00610 MCOS->EmitIntValue(Length - 4, 4); 00611 // The 2 byte version, which is 2. 00612 MCOS->EmitIntValue(2, 2); 00613 // The 4 byte offset to the compile unit in the .debug_info from the start 00614 // of the .debug_info. 00615 if (InfoSectionSymbol) 00616 MCOS->EmitSymbolValue(InfoSectionSymbol, 4, 00617 asmInfo->needsDwarfSectionOffsetDirective()); 00618 else 00619 MCOS->EmitIntValue(0, 4); 00620 // The 1 byte size of an address. 00621 MCOS->EmitIntValue(AddrSize, 1); 00622 // The 1 byte size of a segment descriptor, we use a value of zero. 00623 MCOS->EmitIntValue(0, 1); 00624 // Align the header with the padding if needed, before we put out the table. 00625 for(int i = 0; i < Pad; i++) 00626 MCOS->EmitIntValue(0, 1); 00627 00628 // Now emit the table of pairs of PointerSize'ed values for the section 00629 // addresses and sizes. 00630 for (const auto &sec : Sections) { 00631 MCSymbol *StartSymbol = sec.second.first; 00632 MCSymbol *EndSymbol = sec.second.second; 00633 assert(StartSymbol && "StartSymbol must not be NULL"); 00634 assert(EndSymbol && "EndSymbol must not be NULL"); 00635 00636 const MCExpr *Addr = MCSymbolRefExpr::Create( 00637 StartSymbol, MCSymbolRefExpr::VK_None, context); 00638 const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, 00639 *StartSymbol, *EndSymbol, 0); 00640 MCOS->EmitValue(Addr, AddrSize); 00641 emitAbsValue(*MCOS, Size, AddrSize); 00642 } 00643 00644 // And finally the pair of terminating zeros. 00645 MCOS->EmitIntValue(0, AddrSize); 00646 MCOS->EmitIntValue(0, AddrSize); 00647 } 00648 00649 // When generating dwarf for assembly source files this emits the data for 00650 // .debug_info section which contains three parts. The header, the compile_unit 00651 // DIE and a list of label DIEs. 00652 static void EmitGenDwarfInfo(MCStreamer *MCOS, 00653 const MCSymbol *AbbrevSectionSymbol, 00654 const MCSymbol *LineSectionSymbol, 00655 const MCSymbol *RangesSectionSymbol) { 00656 MCContext &context = MCOS->getContext(); 00657 00658 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); 00659 00660 // Create a symbol at the start and end of this section used in here for the 00661 // expression to calculate the length in the header. 00662 MCSymbol *InfoStart = context.CreateTempSymbol(); 00663 MCOS->EmitLabel(InfoStart); 00664 MCSymbol *InfoEnd = context.CreateTempSymbol(); 00665 00666 // First part: the header. 00667 00668 // The 4 byte total length of the information for this compilation unit, not 00669 // including these 4 bytes. 00670 const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); 00671 emitAbsValue(*MCOS, Length, 4); 00672 00673 // The 2 byte DWARF version. 00674 MCOS->EmitIntValue(context.getDwarfVersion(), 2); 00675 00676 const MCAsmInfo &AsmInfo = *context.getAsmInfo(); 00677 // The 4 byte offset to the debug abbrevs from the start of the .debug_abbrev, 00678 // it is at the start of that section so this is zero. 00679 if (AbbrevSectionSymbol == nullptr) 00680 MCOS->EmitIntValue(0, 4); 00681 else 00682 MCOS->EmitSymbolValue(AbbrevSectionSymbol, 4, 00683 AsmInfo.needsDwarfSectionOffsetDirective()); 00684 00685 const MCAsmInfo *asmInfo = context.getAsmInfo(); 00686 int AddrSize = asmInfo->getPointerSize(); 00687 // The 1 byte size of an address. 00688 MCOS->EmitIntValue(AddrSize, 1); 00689 00690 // Second part: the compile_unit DIE. 00691 00692 // The DW_TAG_compile_unit DIE abbrev (1). 00693 MCOS->EmitULEB128IntValue(1); 00694 00695 // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, 00696 // which is at the start of that section so this is zero. 00697 if (LineSectionSymbol) 00698 MCOS->EmitSymbolValue(LineSectionSymbol, 4, 00699 AsmInfo.needsDwarfSectionOffsetDirective()); 00700 else 00701 MCOS->EmitIntValue(0, 4); 00702 00703 if (RangesSectionSymbol) { 00704 // There are multiple sections containing code, so we must use the 00705 // .debug_ranges sections. 00706 00707 // AT_ranges, the 4 byte offset from the start of the .debug_ranges section 00708 // to the address range list for this compilation unit. 00709 MCOS->EmitSymbolValue(RangesSectionSymbol, 4); 00710 } else { 00711 // If we only have one non-empty code section, we can use the simpler 00712 // AT_low_pc and AT_high_pc attributes. 00713 00714 // Find the first (and only) non-empty text section 00715 auto &Sections = context.getGenDwarfSectionSyms(); 00716 const auto TextSection = Sections.begin(); 00717 assert(TextSection != Sections.end() && "No text section found"); 00718 00719 MCSymbol *StartSymbol = TextSection->second.first; 00720 MCSymbol *EndSymbol = TextSection->second.second; 00721 assert(StartSymbol && "StartSymbol must not be NULL"); 00722 assert(EndSymbol && "EndSymbol must not be NULL"); 00723 00724 // AT_low_pc, the first address of the default .text section. 00725 const MCExpr *Start = MCSymbolRefExpr::Create( 00726 StartSymbol, MCSymbolRefExpr::VK_None, context); 00727 MCOS->EmitValue(Start, AddrSize); 00728 00729 // AT_high_pc, the last address of the default .text section. 00730 const MCExpr *End = MCSymbolRefExpr::Create( 00731 EndSymbol, MCSymbolRefExpr::VK_None, context); 00732 MCOS->EmitValue(End, AddrSize); 00733 } 00734 00735 // AT_name, the name of the source file. Reconstruct from the first directory 00736 // and file table entries. 00737 const SmallVectorImpl<std::string> &MCDwarfDirs = context.getMCDwarfDirs(); 00738 if (MCDwarfDirs.size() > 0) { 00739 MCOS->EmitBytes(MCDwarfDirs[0]); 00740 MCOS->EmitBytes(sys::path::get_separator()); 00741 } 00742 const SmallVectorImpl<MCDwarfFile> &MCDwarfFiles = 00743 MCOS->getContext().getMCDwarfFiles(); 00744 MCOS->EmitBytes(MCDwarfFiles[1].Name); 00745 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 00746 00747 // AT_comp_dir, the working directory the assembly was done in. 00748 if (!context.getCompilationDir().empty()) { 00749 MCOS->EmitBytes(context.getCompilationDir()); 00750 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 00751 } 00752 00753 // AT_APPLE_flags, the command line arguments of the assembler tool. 00754 StringRef DwarfDebugFlags = context.getDwarfDebugFlags(); 00755 if (!DwarfDebugFlags.empty()){ 00756 MCOS->EmitBytes(DwarfDebugFlags); 00757 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 00758 } 00759 00760 // AT_producer, the version of the assembler tool. 00761 StringRef DwarfDebugProducer = context.getDwarfDebugProducer(); 00762 if (!DwarfDebugProducer.empty()) 00763 MCOS->EmitBytes(DwarfDebugProducer); 00764 else 00765 MCOS->EmitBytes(StringRef("llvm-mc (based on LLVM " PACKAGE_VERSION ")")); 00766 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 00767 00768 // AT_language, a 4 byte value. We use DW_LANG_Mips_Assembler as the dwarf2 00769 // draft has no standard code for assembler. 00770 MCOS->EmitIntValue(dwarf::DW_LANG_Mips_Assembler, 2); 00771 00772 // Third part: the list of label DIEs. 00773 00774 // Loop on saved info for dwarf labels and create the DIEs for them. 00775 const std::vector<MCGenDwarfLabelEntry> &Entries = 00776 MCOS->getContext().getMCGenDwarfLabelEntries(); 00777 for (const auto &Entry : Entries) { 00778 // The DW_TAG_label DIE abbrev (2). 00779 MCOS->EmitULEB128IntValue(2); 00780 00781 // AT_name, of the label without any leading underbar. 00782 MCOS->EmitBytes(Entry.getName()); 00783 MCOS->EmitIntValue(0, 1); // NULL byte to terminate the string. 00784 00785 // AT_decl_file, index into the file table. 00786 MCOS->EmitIntValue(Entry.getFileNumber(), 4); 00787 00788 // AT_decl_line, source line number. 00789 MCOS->EmitIntValue(Entry.getLineNumber(), 4); 00790 00791 // AT_low_pc, start address of the label. 00792 const MCExpr *AT_low_pc = MCSymbolRefExpr::Create(Entry.getLabel(), 00793 MCSymbolRefExpr::VK_None, context); 00794 MCOS->EmitValue(AT_low_pc, AddrSize); 00795 00796 // DW_AT_prototyped, a one byte flag value of 0 saying we have no prototype. 00797 MCOS->EmitIntValue(0, 1); 00798 00799 // The DW_TAG_unspecified_parameters DIE abbrev (3). 00800 MCOS->EmitULEB128IntValue(3); 00801 00802 // Add the NULL DIE terminating the DW_TAG_unspecified_parameters DIE's. 00803 MCOS->EmitIntValue(0, 1); 00804 } 00805 00806 // Add the NULL DIE terminating the Compile Unit DIE's. 00807 MCOS->EmitIntValue(0, 1); 00808 00809 // Now set the value of the symbol at the end of the info section. 00810 MCOS->EmitLabel(InfoEnd); 00811 } 00812 00813 // When generating dwarf for assembly source files this emits the data for 00814 // .debug_ranges section. We only emit one range list, which spans all of the 00815 // executable sections of this file. 00816 static void EmitGenDwarfRanges(MCStreamer *MCOS) { 00817 MCContext &context = MCOS->getContext(); 00818 auto &Sections = context.getGenDwarfSectionSyms(); 00819 00820 const MCAsmInfo *AsmInfo = context.getAsmInfo(); 00821 int AddrSize = AsmInfo->getPointerSize(); 00822 00823 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); 00824 00825 for (const auto sec : Sections) { 00826 00827 MCSymbol *StartSymbol = sec.second.first; 00828 MCSymbol *EndSymbol = sec.second.second; 00829 assert(StartSymbol && "StartSymbol must not be NULL"); 00830 assert(EndSymbol && "EndSymbol must not be NULL"); 00831 00832 // Emit a base address selection entry for the start of this section 00833 const MCExpr *SectionStartAddr = MCSymbolRefExpr::Create( 00834 StartSymbol, MCSymbolRefExpr::VK_None, context); 00835 MCOS->EmitFill(AddrSize, 0xFF); 00836 MCOS->EmitValue(SectionStartAddr, AddrSize); 00837 00838 // Emit a range list entry spanning this section 00839 const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, 00840 *StartSymbol, *EndSymbol, 0); 00841 MCOS->EmitIntValue(0, AddrSize); 00842 emitAbsValue(*MCOS, SectionSize, AddrSize); 00843 } 00844 00845 // Emit end of list entry 00846 MCOS->EmitIntValue(0, AddrSize); 00847 MCOS->EmitIntValue(0, AddrSize); 00848 } 00849 00850 // 00851 // When generating dwarf for assembly source files this emits the Dwarf 00852 // sections. 00853 // 00854 void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { 00855 MCContext &context = MCOS->getContext(); 00856 00857 // Create the dwarf sections in this order (.debug_line already created). 00858 const MCAsmInfo *AsmInfo = context.getAsmInfo(); 00859 bool CreateDwarfSectionSymbols = 00860 AsmInfo->doesDwarfUseRelocationsAcrossSections(); 00861 MCSymbol *LineSectionSymbol = nullptr; 00862 if (CreateDwarfSectionSymbols) 00863 LineSectionSymbol = MCOS->getDwarfLineTableSymbol(0); 00864 MCSymbol *AbbrevSectionSymbol = nullptr; 00865 MCSymbol *InfoSectionSymbol = nullptr; 00866 MCSymbol *RangesSectionSymbol = NULL; 00867 00868 // Create end symbols for each section, and remove empty sections 00869 MCOS->getContext().finalizeDwarfSections(*MCOS); 00870 00871 // If there are no sections to generate debug info for, we don't need 00872 // to do anything 00873 if (MCOS->getContext().getGenDwarfSectionSyms().empty()) 00874 return; 00875 00876 // We only need to use the .debug_ranges section if we have multiple 00877 // code sections. 00878 const bool UseRangesSection = 00879 MCOS->getContext().getGenDwarfSectionSyms().size() > 1; 00880 CreateDwarfSectionSymbols |= UseRangesSection; 00881 00882 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); 00883 if (CreateDwarfSectionSymbols) { 00884 InfoSectionSymbol = context.CreateTempSymbol(); 00885 MCOS->EmitLabel(InfoSectionSymbol); 00886 } 00887 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection()); 00888 if (CreateDwarfSectionSymbols) { 00889 AbbrevSectionSymbol = context.CreateTempSymbol(); 00890 MCOS->EmitLabel(AbbrevSectionSymbol); 00891 } 00892 if (UseRangesSection) { 00893 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfRangesSection()); 00894 if (CreateDwarfSectionSymbols) { 00895 RangesSectionSymbol = context.CreateTempSymbol(); 00896 MCOS->EmitLabel(RangesSectionSymbol); 00897 } 00898 } 00899 00900 assert((RangesSectionSymbol != NULL) || !UseRangesSection); 00901 00902 MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection()); 00903 00904 // Output the data for .debug_aranges section. 00905 EmitGenDwarfAranges(MCOS, InfoSectionSymbol); 00906 00907 if (UseRangesSection) 00908 EmitGenDwarfRanges(MCOS); 00909 00910 // Output the data for .debug_abbrev section. 00911 EmitGenDwarfAbbrev(MCOS); 00912 00913 // Output the data for .debug_info section. 00914 EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, 00915 RangesSectionSymbol); 00916 } 00917 00918 // 00919 // When generating dwarf for assembly source files this is called when symbol 00920 // for a label is created. If this symbol is not a temporary and is in the 00921 // section that dwarf is being generated for, save the needed info to create 00922 // a dwarf label. 00923 // 00924 void MCGenDwarfLabelEntry::Make(MCSymbol *Symbol, MCStreamer *MCOS, 00925 SourceMgr &SrcMgr, SMLoc &Loc) { 00926 // We won't create dwarf labels for temporary symbols. 00927 if (Symbol->isTemporary()) 00928 return; 00929 MCContext &context = MCOS->getContext(); 00930 // We won't create dwarf labels for symbols in sections that we are not 00931 // generating debug info for. 00932 if (!context.getGenDwarfSectionSyms().count(MCOS->getCurrentSection().first)) 00933 return; 00934 00935 // The dwarf label's name does not have the symbol name's leading 00936 // underbar if any. 00937 StringRef Name = Symbol->getName(); 00938 if (Name.startswith("_")) 00939 Name = Name.substr(1, Name.size()-1); 00940 00941 // Get the dwarf file number to be used for the dwarf label. 00942 unsigned FileNumber = context.getGenDwarfFileNumber(); 00943 00944 // Finding the line number is the expensive part which is why we just don't 00945 // pass it in as for some symbols we won't create a dwarf label. 00946 unsigned CurBuffer = SrcMgr.FindBufferContainingLoc(Loc); 00947 unsigned LineNumber = SrcMgr.FindLineNumber(Loc, CurBuffer); 00948 00949 // We create a temporary symbol for use for the AT_high_pc and AT_low_pc 00950 // values so that they don't have things like an ARM thumb bit from the 00951 // original symbol. So when used they won't get a low bit set after 00952 // relocation. 00953 MCSymbol *Label = context.CreateTempSymbol(); 00954 MCOS->EmitLabel(Label); 00955 00956 // Create and entry for the info and add it to the other entries. 00957 MCOS->getContext().addMCGenDwarfLabelEntry( 00958 MCGenDwarfLabelEntry(Name, FileNumber, LineNumber, Label)); 00959 } 00960 00961 static int getDataAlignmentFactor(MCStreamer &streamer) { 00962 MCContext &context = streamer.getContext(); 00963 const MCAsmInfo *asmInfo = context.getAsmInfo(); 00964 int size = asmInfo->getCalleeSaveStackSlotSize(); 00965 if (asmInfo->isStackGrowthDirectionUp()) 00966 return size; 00967 else 00968 return -size; 00969 } 00970 00971 static unsigned getSizeForEncoding(MCStreamer &streamer, 00972 unsigned symbolEncoding) { 00973 MCContext &context = streamer.getContext(); 00974 unsigned format = symbolEncoding & 0x0f; 00975 switch (format) { 00976 default: llvm_unreachable("Unknown Encoding"); 00977 case dwarf::DW_EH_PE_absptr: 00978 case dwarf::DW_EH_PE_signed: 00979 return context.getAsmInfo()->getPointerSize(); 00980 case dwarf::DW_EH_PE_udata2: 00981 case dwarf::DW_EH_PE_sdata2: 00982 return 2; 00983 case dwarf::DW_EH_PE_udata4: 00984 case dwarf::DW_EH_PE_sdata4: 00985 return 4; 00986 case dwarf::DW_EH_PE_udata8: 00987 case dwarf::DW_EH_PE_sdata8: 00988 return 8; 00989 } 00990 } 00991 00992 static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol, 00993 unsigned symbolEncoding, bool isEH) { 00994 MCContext &context = streamer.getContext(); 00995 const MCAsmInfo *asmInfo = context.getAsmInfo(); 00996 const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol, 00997 symbolEncoding, 00998 streamer); 00999 unsigned size = getSizeForEncoding(streamer, symbolEncoding); 01000 if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH) 01001 emitAbsValue(streamer, v, size); 01002 else 01003 streamer.EmitValue(v, size); 01004 } 01005 01006 static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, 01007 unsigned symbolEncoding) { 01008 MCContext &context = streamer.getContext(); 01009 const MCAsmInfo *asmInfo = context.getAsmInfo(); 01010 const MCExpr *v = asmInfo->getExprForPersonalitySymbol(&symbol, 01011 symbolEncoding, 01012 streamer); 01013 unsigned size = getSizeForEncoding(streamer, symbolEncoding); 01014 streamer.EmitValue(v, size); 01015 } 01016 01017 namespace { 01018 class FrameEmitterImpl { 01019 int CFAOffset; 01020 bool IsEH; 01021 const MCSymbol *SectionStart; 01022 public: 01023 FrameEmitterImpl(bool isEH) 01024 : CFAOffset(0), IsEH(isEH), SectionStart(nullptr) {} 01025 01026 void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } 01027 01028 /// Emit the unwind information in a compact way. 01029 void EmitCompactUnwind(MCObjectStreamer &streamer, 01030 const MCDwarfFrameInfo &frame); 01031 01032 const MCSymbol &EmitCIE(MCObjectStreamer &streamer, 01033 const MCSymbol *personality, 01034 unsigned personalityEncoding, 01035 const MCSymbol *lsda, 01036 bool IsSignalFrame, 01037 unsigned lsdaEncoding, 01038 bool IsSimple); 01039 MCSymbol *EmitFDE(MCObjectStreamer &streamer, 01040 const MCSymbol &cieStart, 01041 const MCDwarfFrameInfo &frame); 01042 void EmitCFIInstructions(MCObjectStreamer &streamer, 01043 ArrayRef<MCCFIInstruction> Instrs, 01044 MCSymbol *BaseLabel); 01045 void EmitCFIInstruction(MCObjectStreamer &Streamer, 01046 const MCCFIInstruction &Instr); 01047 }; 01048 01049 } // end anonymous namespace 01050 01051 static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) { 01052 Streamer.EmitIntValue(Encoding, 1); 01053 } 01054 01055 void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, 01056 const MCCFIInstruction &Instr) { 01057 int dataAlignmentFactor = getDataAlignmentFactor(Streamer); 01058 01059 switch (Instr.getOperation()) { 01060 case MCCFIInstruction::OpRegister: { 01061 unsigned Reg1 = Instr.getRegister(); 01062 unsigned Reg2 = Instr.getRegister2(); 01063 Streamer.EmitIntValue(dwarf::DW_CFA_register, 1); 01064 Streamer.EmitULEB128IntValue(Reg1); 01065 Streamer.EmitULEB128IntValue(Reg2); 01066 return; 01067 } 01068 case MCCFIInstruction::OpWindowSave: { 01069 Streamer.EmitIntValue(dwarf::DW_CFA_GNU_window_save, 1); 01070 return; 01071 } 01072 case MCCFIInstruction::OpUndefined: { 01073 unsigned Reg = Instr.getRegister(); 01074 Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); 01075 Streamer.EmitULEB128IntValue(Reg); 01076 return; 01077 } 01078 case MCCFIInstruction::OpAdjustCfaOffset: 01079 case MCCFIInstruction::OpDefCfaOffset: { 01080 const bool IsRelative = 01081 Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset; 01082 01083 Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); 01084 01085 if (IsRelative) 01086 CFAOffset += Instr.getOffset(); 01087 else 01088 CFAOffset = -Instr.getOffset(); 01089 01090 Streamer.EmitULEB128IntValue(CFAOffset); 01091 01092 return; 01093 } 01094 case MCCFIInstruction::OpDefCfa: { 01095 Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); 01096 Streamer.EmitULEB128IntValue(Instr.getRegister()); 01097 CFAOffset = -Instr.getOffset(); 01098 Streamer.EmitULEB128IntValue(CFAOffset); 01099 01100 return; 01101 } 01102 01103 case MCCFIInstruction::OpDefCfaRegister: { 01104 Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); 01105 Streamer.EmitULEB128IntValue(Instr.getRegister()); 01106 01107 return; 01108 } 01109 01110 case MCCFIInstruction::OpOffset: 01111 case MCCFIInstruction::OpRelOffset: { 01112 const bool IsRelative = 01113 Instr.getOperation() == MCCFIInstruction::OpRelOffset; 01114 01115 unsigned Reg = Instr.getRegister(); 01116 int Offset = Instr.getOffset(); 01117 if (IsRelative) 01118 Offset -= CFAOffset; 01119 Offset = Offset / dataAlignmentFactor; 01120 01121 if (Offset < 0) { 01122 Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); 01123 Streamer.EmitULEB128IntValue(Reg); 01124 Streamer.EmitSLEB128IntValue(Offset); 01125 } else if (Reg < 64) { 01126 Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); 01127 Streamer.EmitULEB128IntValue(Offset); 01128 } else { 01129 Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); 01130 Streamer.EmitULEB128IntValue(Reg); 01131 Streamer.EmitULEB128IntValue(Offset); 01132 } 01133 return; 01134 } 01135 case MCCFIInstruction::OpRememberState: 01136 Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); 01137 return; 01138 case MCCFIInstruction::OpRestoreState: 01139 Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); 01140 return; 01141 case MCCFIInstruction::OpSameValue: { 01142 unsigned Reg = Instr.getRegister(); 01143 Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); 01144 Streamer.EmitULEB128IntValue(Reg); 01145 return; 01146 } 01147 case MCCFIInstruction::OpRestore: { 01148 unsigned Reg = Instr.getRegister(); 01149 Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); 01150 return; 01151 } 01152 case MCCFIInstruction::OpEscape: 01153 Streamer.EmitBytes(Instr.getValues()); 01154 return; 01155 } 01156 llvm_unreachable("Unhandled case in switch"); 01157 } 01158 01159 /// Emit frame instructions to describe the layout of the frame. 01160 void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, 01161 ArrayRef<MCCFIInstruction> Instrs, 01162 MCSymbol *BaseLabel) { 01163 for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { 01164 const MCCFIInstruction &Instr = Instrs[i]; 01165 MCSymbol *Label = Instr.getLabel(); 01166 // Throw out move if the label is invalid. 01167 if (Label && !Label->isDefined()) continue; // Not emitted, in dead code. 01168 01169 // Advance row if new location. 01170 if (BaseLabel && Label) { 01171 MCSymbol *ThisSym = Label; 01172 if (ThisSym != BaseLabel) { 01173 streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); 01174 BaseLabel = ThisSym; 01175 } 01176 } 01177 01178 EmitCFIInstruction(streamer, Instr); 01179 } 01180 } 01181 01182 /// Emit the unwind information in a compact way. 01183 void FrameEmitterImpl::EmitCompactUnwind(MCObjectStreamer &Streamer, 01184 const MCDwarfFrameInfo &Frame) { 01185 MCContext &Context = Streamer.getContext(); 01186 const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); 01187 01188 // range-start range-length compact-unwind-enc personality-func lsda 01189 // _foo LfooEnd-_foo 0x00000023 0 0 01190 // _bar LbarEnd-_bar 0x00000025 __gxx_personality except_tab1 01191 // 01192 // .section __LD,__compact_unwind,regular,debug 01193 // 01194 // # compact unwind for _foo 01195 // .quad _foo 01196 // .set L1,LfooEnd-_foo 01197 // .long L1 01198 // .long 0x01010001 01199 // .quad 0 01200 // .quad 0 01201 // 01202 // # compact unwind for _bar 01203 // .quad _bar 01204 // .set L2,LbarEnd-_bar 01205 // .long L2 01206 // .long 0x01020011 01207 // .quad __gxx_personality 01208 // .quad except_tab1 01209 01210 uint32_t Encoding = Frame.CompactUnwindEncoding; 01211 if (!Encoding) return; 01212 bool DwarfEHFrameOnly = (Encoding == MOFI->getCompactUnwindDwarfEHFrameOnly()); 01213 01214 // The encoding needs to know we have an LSDA. 01215 if (!DwarfEHFrameOnly && Frame.Lsda) 01216 Encoding |= 0x40000000; 01217 01218 // Range Start 01219 unsigned FDEEncoding = MOFI->getFDEEncoding(); 01220 unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); 01221 Streamer.EmitSymbolValue(Frame.Begin, Size); 01222 01223 // Range Length 01224 const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, 01225 *Frame.End, 0); 01226 emitAbsValue(Streamer, Range, 4); 01227 01228 // Compact Encoding 01229 Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); 01230 Streamer.EmitIntValue(Encoding, Size); 01231 01232 // Personality Function 01233 Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); 01234 if (!DwarfEHFrameOnly && Frame.Personality) 01235 Streamer.EmitSymbolValue(Frame.Personality, Size); 01236 else 01237 Streamer.EmitIntValue(0, Size); // No personality fn 01238 01239 // LSDA 01240 Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); 01241 if (!DwarfEHFrameOnly && Frame.Lsda) 01242 Streamer.EmitSymbolValue(Frame.Lsda, Size); 01243 else 01244 Streamer.EmitIntValue(0, Size); // No LSDA 01245 } 01246 01247 const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, 01248 const MCSymbol *personality, 01249 unsigned personalityEncoding, 01250 const MCSymbol *lsda, 01251 bool IsSignalFrame, 01252 unsigned lsdaEncoding, 01253 bool IsSimple) { 01254 MCContext &context = streamer.getContext(); 01255 const MCRegisterInfo *MRI = context.getRegisterInfo(); 01256 const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); 01257 01258 MCSymbol *sectionStart = context.CreateTempSymbol(); 01259 streamer.EmitLabel(sectionStart); 01260 01261 MCSymbol *sectionEnd = context.CreateTempSymbol(); 01262 01263 // Length 01264 const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, 01265 *sectionEnd, 4); 01266 emitAbsValue(streamer, Length, 4); 01267 01268 // CIE ID 01269 unsigned CIE_ID = IsEH ? 0 : -1; 01270 streamer.EmitIntValue(CIE_ID, 4); 01271 01272 // Version 01273 // For DWARF2, we use CIE version 1 01274 // For DWARF3+, we use CIE version 3 01275 uint8_t CIEVersion = context.getDwarfVersion() <= 2 ? 1 : 3; 01276 streamer.EmitIntValue(CIEVersion, 1); 01277 01278 // Augmentation String 01279 SmallString<8> Augmentation; 01280 if (IsEH) { 01281 Augmentation += "z"; 01282 if (personality) 01283 Augmentation += "P"; 01284 if (lsda) 01285 Augmentation += "L"; 01286 Augmentation += "R"; 01287 if (IsSignalFrame) 01288 Augmentation += "S"; 01289 streamer.EmitBytes(Augmentation.str()); 01290 } 01291 streamer.EmitIntValue(0, 1); 01292 01293 // Code Alignment Factor 01294 streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment()); 01295 01296 // Data Alignment Factor 01297 streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); 01298 01299 // Return Address Register 01300 if (CIEVersion == 1) { 01301 assert(MRI->getRARegister() <= 255 && 01302 "DWARF 2 encodes return_address_register in one byte"); 01303 streamer.EmitIntValue(MRI->getDwarfRegNum(MRI->getRARegister(), true), 1); 01304 } else { 01305 streamer.EmitULEB128IntValue( 01306 MRI->getDwarfRegNum(MRI->getRARegister(), true)); 01307 } 01308 01309 // Augmentation Data Length (optional) 01310 01311 unsigned augmentationLength = 0; 01312 if (IsEH) { 01313 if (personality) { 01314 // Personality Encoding 01315 augmentationLength += 1; 01316 // Personality 01317 augmentationLength += getSizeForEncoding(streamer, personalityEncoding); 01318 } 01319 if (lsda) 01320 augmentationLength += 1; 01321 // Encoding of the FDE pointers 01322 augmentationLength += 1; 01323 01324 streamer.EmitULEB128IntValue(augmentationLength); 01325 01326 // Augmentation Data (optional) 01327 if (personality) { 01328 // Personality Encoding 01329 emitEncodingByte(streamer, personalityEncoding); 01330 // Personality 01331 EmitPersonality(streamer, *personality, personalityEncoding); 01332 } 01333 01334 if (lsda) 01335 emitEncodingByte(streamer, lsdaEncoding); 01336 01337 // Encoding of the FDE pointers 01338 emitEncodingByte(streamer, MOFI->getFDEEncoding()); 01339 } 01340 01341 // Initial Instructions 01342 01343 const MCAsmInfo *MAI = context.getAsmInfo(); 01344 if (!IsSimple) { 01345 const std::vector<MCCFIInstruction> &Instructions = 01346 MAI->getInitialFrameState(); 01347 EmitCFIInstructions(streamer, Instructions, nullptr); 01348 } 01349 01350 // Padding 01351 streamer.EmitValueToAlignment(IsEH ? 4 : MAI->getPointerSize()); 01352 01353 streamer.EmitLabel(sectionEnd); 01354 return *sectionStart; 01355 } 01356 01357 MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, 01358 const MCSymbol &cieStart, 01359 const MCDwarfFrameInfo &frame) { 01360 MCContext &context = streamer.getContext(); 01361 MCSymbol *fdeStart = context.CreateTempSymbol(); 01362 MCSymbol *fdeEnd = context.CreateTempSymbol(); 01363 const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); 01364 01365 // Length 01366 const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); 01367 emitAbsValue(streamer, Length, 4); 01368 01369 streamer.EmitLabel(fdeStart); 01370 01371 // CIE Pointer 01372 const MCAsmInfo *asmInfo = context.getAsmInfo(); 01373 if (IsEH) { 01374 const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 01375 0); 01376 emitAbsValue(streamer, offset, 4); 01377 } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) { 01378 const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, 01379 cieStart, 0); 01380 emitAbsValue(streamer, offset, 4); 01381 } else { 01382 streamer.EmitSymbolValue(&cieStart, 4); 01383 } 01384 01385 // PC Begin 01386 unsigned PCEncoding = 01387 IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr; 01388 unsigned PCSize = getSizeForEncoding(streamer, PCEncoding); 01389 emitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH); 01390 01391 // PC Range 01392 const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, 01393 *frame.End, 0); 01394 emitAbsValue(streamer, Range, PCSize); 01395 01396 if (IsEH) { 01397 // Augmentation Data Length 01398 unsigned augmentationLength = 0; 01399 01400 if (frame.Lsda) 01401 augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); 01402 01403 streamer.EmitULEB128IntValue(augmentationLength); 01404 01405 // Augmentation Data 01406 if (frame.Lsda) 01407 emitFDESymbol(streamer, *frame.Lsda, frame.LsdaEncoding, true); 01408 } 01409 01410 // Call Frame Instructions 01411 EmitCFIInstructions(streamer, frame.Instructions, frame.Begin); 01412 01413 // Padding 01414 streamer.EmitValueToAlignment(PCSize); 01415 01416 return fdeEnd; 01417 } 01418 01419 namespace { 01420 struct CIEKey { 01421 static const CIEKey getEmptyKey() { 01422 return CIEKey(nullptr, 0, -1, false, false); 01423 } 01424 static const CIEKey getTombstoneKey() { 01425 return CIEKey(nullptr, -1, 0, false, false); 01426 } 01427 01428 CIEKey(const MCSymbol *Personality_, unsigned PersonalityEncoding_, 01429 unsigned LsdaEncoding_, bool IsSignalFrame_, bool IsSimple_) 01430 : Personality(Personality_), PersonalityEncoding(PersonalityEncoding_), 01431 LsdaEncoding(LsdaEncoding_), IsSignalFrame(IsSignalFrame_), 01432 IsSimple(IsSimple_) {} 01433 const MCSymbol *Personality; 01434 unsigned PersonalityEncoding; 01435 unsigned LsdaEncoding; 01436 bool IsSignalFrame; 01437 bool IsSimple; 01438 }; 01439 } 01440 01441 namespace llvm { 01442 template <> 01443 struct DenseMapInfo<CIEKey> { 01444 static CIEKey getEmptyKey() { 01445 return CIEKey::getEmptyKey(); 01446 } 01447 static CIEKey getTombstoneKey() { 01448 return CIEKey::getTombstoneKey(); 01449 } 01450 static unsigned getHashValue(const CIEKey &Key) { 01451 return static_cast<unsigned>(hash_combine(Key.Personality, 01452 Key.PersonalityEncoding, 01453 Key.LsdaEncoding, 01454 Key.IsSignalFrame, 01455 Key.IsSimple)); 01456 } 01457 static bool isEqual(const CIEKey &LHS, 01458 const CIEKey &RHS) { 01459 return LHS.Personality == RHS.Personality && 01460 LHS.PersonalityEncoding == RHS.PersonalityEncoding && 01461 LHS.LsdaEncoding == RHS.LsdaEncoding && 01462 LHS.IsSignalFrame == RHS.IsSignalFrame && 01463 LHS.IsSimple == RHS.IsSimple; 01464 } 01465 }; 01466 } 01467 01468 void MCDwarfFrameEmitter::Emit(MCObjectStreamer &Streamer, MCAsmBackend *MAB, 01469 bool IsEH) { 01470 Streamer.generateCompactUnwindEncodings(MAB); 01471 01472 MCContext &Context = Streamer.getContext(); 01473 const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); 01474 FrameEmitterImpl Emitter(IsEH); 01475 ArrayRef<MCDwarfFrameInfo> FrameArray = Streamer.getDwarfFrameInfos(); 01476 01477 // Emit the compact unwind info if available. 01478 bool NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); 01479 if (IsEH && MOFI->getCompactUnwindSection()) { 01480 bool SectionEmitted = false; 01481 for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { 01482 const MCDwarfFrameInfo &Frame = FrameArray[i]; 01483 if (Frame.CompactUnwindEncoding == 0) continue; 01484 if (!SectionEmitted) { 01485 Streamer.SwitchSection(MOFI->getCompactUnwindSection()); 01486 Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); 01487 SectionEmitted = true; 01488 } 01489 NeedsEHFrameSection |= 01490 Frame.CompactUnwindEncoding == 01491 MOFI->getCompactUnwindDwarfEHFrameOnly(); 01492 Emitter.EmitCompactUnwind(Streamer, Frame); 01493 } 01494 } 01495 01496 if (!NeedsEHFrameSection) return; 01497 01498 const MCSection &Section = 01499 IsEH ? *const_cast<MCObjectFileInfo*>(MOFI)->getEHFrameSection() : 01500 *MOFI->getDwarfFrameSection(); 01501 01502 Streamer.SwitchSection(&Section); 01503 MCSymbol *SectionStart = Context.CreateTempSymbol(); 01504 Streamer.EmitLabel(SectionStart); 01505 Emitter.setSectionStart(SectionStart); 01506 01507 MCSymbol *FDEEnd = nullptr; 01508 DenseMap<CIEKey, const MCSymbol *> CIEStarts; 01509 01510 const MCSymbol *DummyDebugKey = nullptr; 01511 NeedsEHFrameSection = !MOFI->getSupportsCompactUnwindWithoutEHFrame(); 01512 for (unsigned i = 0, n = FrameArray.size(); i < n; ++i) { 01513 const MCDwarfFrameInfo &Frame = FrameArray[i]; 01514 01515 // Emit the label from the previous iteration 01516 if (FDEEnd) { 01517 Streamer.EmitLabel(FDEEnd); 01518 FDEEnd = nullptr; 01519 } 01520 01521 if (!NeedsEHFrameSection && Frame.CompactUnwindEncoding != 01522 MOFI->getCompactUnwindDwarfEHFrameOnly()) 01523 // Don't generate an EH frame if we don't need one. I.e., it's taken care 01524 // of by the compact unwind encoding. 01525 continue; 01526 01527 CIEKey Key(Frame.Personality, Frame.PersonalityEncoding, 01528 Frame.LsdaEncoding, Frame.IsSignalFrame, Frame.IsSimple); 01529 const MCSymbol *&CIEStart = IsEH ? CIEStarts[Key] : DummyDebugKey; 01530 if (!CIEStart) 01531 CIEStart = &Emitter.EmitCIE(Streamer, Frame.Personality, 01532 Frame.PersonalityEncoding, Frame.Lsda, 01533 Frame.IsSignalFrame, 01534 Frame.LsdaEncoding, 01535 Frame.IsSimple); 01536 01537 FDEEnd = Emitter.EmitFDE(Streamer, *CIEStart, Frame); 01538 } 01539 01540 Streamer.EmitValueToAlignment(Context.getAsmInfo()->getPointerSize()); 01541 if (FDEEnd) 01542 Streamer.EmitLabel(FDEEnd); 01543 } 01544 01545 void MCDwarfFrameEmitter::EmitAdvanceLoc(MCObjectStreamer &Streamer, 01546 uint64_t AddrDelta) { 01547 MCContext &Context = Streamer.getContext(); 01548 SmallString<256> Tmp; 01549 raw_svector_ostream OS(Tmp); 01550 MCDwarfFrameEmitter::EncodeAdvanceLoc(Context, AddrDelta, OS); 01551 Streamer.EmitBytes(OS.str()); 01552 } 01553 01554 void MCDwarfFrameEmitter::EncodeAdvanceLoc(MCContext &Context, 01555 uint64_t AddrDelta, 01556 raw_ostream &OS) { 01557 // Scale the address delta by the minimum instruction length. 01558 AddrDelta = ScaleAddrDelta(Context, AddrDelta); 01559 01560 if (AddrDelta == 0) { 01561 } else if (isUIntN(6, AddrDelta)) { 01562 uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta; 01563 OS << Opcode; 01564 } else if (isUInt<8>(AddrDelta)) { 01565 OS << uint8_t(dwarf::DW_CFA_advance_loc1); 01566 OS << uint8_t(AddrDelta); 01567 } else if (isUInt<16>(AddrDelta)) { 01568 // FIXME: check what is the correct behavior on a big endian machine. 01569 OS << uint8_t(dwarf::DW_CFA_advance_loc2); 01570 OS << uint8_t( AddrDelta & 0xff); 01571 OS << uint8_t((AddrDelta >> 8) & 0xff); 01572 } else { 01573 // FIXME: check what is the correct behavior on a big endian machine. 01574 assert(isUInt<32>(AddrDelta)); 01575 OS << uint8_t(dwarf::DW_CFA_advance_loc4); 01576 OS << uint8_t( AddrDelta & 0xff); 01577 OS << uint8_t((AddrDelta >> 8) & 0xff); 01578 OS << uint8_t((AddrDelta >> 16) & 0xff); 01579 OS << uint8_t((AddrDelta >> 24) & 0xff); 01580 01581 } 01582 }