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