LLVM API Documentation
00001 //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// 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 "DWARFDebugFrame.h" 00011 #include "llvm/ADT/SmallString.h" 00012 #include "llvm/Support/DataTypes.h" 00013 #include "llvm/Support/Dwarf.h" 00014 #include "llvm/Support/ErrorHandling.h" 00015 #include "llvm/Support/Format.h" 00016 #include "llvm/Support/raw_ostream.h" 00017 #include <string> 00018 #include <vector> 00019 00020 using namespace llvm; 00021 using namespace dwarf; 00022 00023 00024 /// \brief Abstract frame entry defining the common interface concrete 00025 /// entries implement. 00026 class llvm::FrameEntry { 00027 public: 00028 enum FrameKind {FK_CIE, FK_FDE}; 00029 FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) 00030 : Kind(K), Offset(Offset), Length(Length) {} 00031 00032 virtual ~FrameEntry() { 00033 } 00034 00035 FrameKind getKind() const { return Kind; } 00036 virtual uint64_t getOffset() const { return Offset; } 00037 00038 /// \brief Parse and store a sequence of CFI instructions from Data, 00039 /// starting at *Offset and ending at EndOffset. If everything 00040 /// goes well, *Offset should be equal to EndOffset when this method 00041 /// returns. Otherwise, an error occurred. 00042 virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, 00043 uint32_t EndOffset); 00044 00045 /// \brief Dump the entry header to the given output stream. 00046 virtual void dumpHeader(raw_ostream &OS) const = 0; 00047 00048 /// \brief Dump the entry's instructions to the given output stream. 00049 virtual void dumpInstructions(raw_ostream &OS) const; 00050 00051 protected: 00052 const FrameKind Kind; 00053 00054 /// \brief Offset of this entry in the section. 00055 uint64_t Offset; 00056 00057 /// \brief Entry length as specified in DWARF. 00058 uint64_t Length; 00059 00060 /// An entry may contain CFI instructions. An instruction consists of an 00061 /// opcode and an optional sequence of operands. 00062 typedef std::vector<uint64_t> Operands; 00063 struct Instruction { 00064 Instruction(uint8_t Opcode) 00065 : Opcode(Opcode) 00066 {} 00067 00068 uint8_t Opcode; 00069 Operands Ops; 00070 }; 00071 00072 std::vector<Instruction> Instructions; 00073 00074 /// Convenience methods to add a new instruction with the given opcode and 00075 /// operands to the Instructions vector. 00076 void addInstruction(uint8_t Opcode) { 00077 Instructions.push_back(Instruction(Opcode)); 00078 } 00079 00080 void addInstruction(uint8_t Opcode, uint64_t Operand1) { 00081 Instructions.push_back(Instruction(Opcode)); 00082 Instructions.back().Ops.push_back(Operand1); 00083 } 00084 00085 void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 00086 Instructions.push_back(Instruction(Opcode)); 00087 Instructions.back().Ops.push_back(Operand1); 00088 Instructions.back().Ops.push_back(Operand2); 00089 } 00090 }; 00091 00092 00093 // See DWARF standard v3, section 7.23 00094 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 00095 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 00096 00097 void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, 00098 uint32_t EndOffset) { 00099 while (*Offset < EndOffset) { 00100 uint8_t Opcode = Data.getU8(Offset); 00101 // Some instructions have a primary opcode encoded in the top bits. 00102 uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 00103 00104 if (Primary) { 00105 // If it's a primary opcode, the first operand is encoded in the bottom 00106 // bits of the opcode itself. 00107 uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 00108 switch (Primary) { 00109 default: llvm_unreachable("Impossible primary CFI opcode"); 00110 case DW_CFA_advance_loc: 00111 case DW_CFA_restore: 00112 addInstruction(Primary, Op1); 00113 break; 00114 case DW_CFA_offset: 00115 addInstruction(Primary, Op1, Data.getULEB128(Offset)); 00116 break; 00117 } 00118 } else { 00119 // Extended opcode - its value is Opcode itself. 00120 switch (Opcode) { 00121 default: llvm_unreachable("Invalid extended CFI opcode"); 00122 case DW_CFA_nop: 00123 case DW_CFA_remember_state: 00124 case DW_CFA_restore_state: 00125 case DW_CFA_GNU_window_save: 00126 // No operands 00127 addInstruction(Opcode); 00128 break; 00129 case DW_CFA_set_loc: 00130 // Operands: Address 00131 addInstruction(Opcode, Data.getAddress(Offset)); 00132 break; 00133 case DW_CFA_advance_loc1: 00134 // Operands: 1-byte delta 00135 addInstruction(Opcode, Data.getU8(Offset)); 00136 break; 00137 case DW_CFA_advance_loc2: 00138 // Operands: 2-byte delta 00139 addInstruction(Opcode, Data.getU16(Offset)); 00140 break; 00141 case DW_CFA_advance_loc4: 00142 // Operands: 4-byte delta 00143 addInstruction(Opcode, Data.getU32(Offset)); 00144 break; 00145 case DW_CFA_restore_extended: 00146 case DW_CFA_undefined: 00147 case DW_CFA_same_value: 00148 case DW_CFA_def_cfa_register: 00149 case DW_CFA_def_cfa_offset: 00150 // Operands: ULEB128 00151 addInstruction(Opcode, Data.getULEB128(Offset)); 00152 break; 00153 case DW_CFA_def_cfa_offset_sf: 00154 // Operands: SLEB128 00155 addInstruction(Opcode, Data.getSLEB128(Offset)); 00156 break; 00157 case DW_CFA_offset_extended: 00158 case DW_CFA_register: 00159 case DW_CFA_def_cfa: 00160 case DW_CFA_val_offset: 00161 // Operands: ULEB128, ULEB128 00162 addInstruction(Opcode, Data.getULEB128(Offset), 00163 Data.getULEB128(Offset)); 00164 break; 00165 case DW_CFA_offset_extended_sf: 00166 case DW_CFA_def_cfa_sf: 00167 case DW_CFA_val_offset_sf: 00168 // Operands: ULEB128, SLEB128 00169 addInstruction(Opcode, Data.getULEB128(Offset), 00170 Data.getSLEB128(Offset)); 00171 break; 00172 case DW_CFA_def_cfa_expression: 00173 case DW_CFA_expression: 00174 case DW_CFA_val_expression: 00175 // TODO: implement this 00176 report_fatal_error("Values with expressions not implemented yet!"); 00177 } 00178 } 00179 } 00180 } 00181 00182 00183 void FrameEntry::dumpInstructions(raw_ostream &OS) const { 00184 // TODO: at the moment only instruction names are dumped. Expand this to 00185 // dump operands as well. 00186 for (const auto &Instr : Instructions) { 00187 uint8_t Opcode = Instr.Opcode; 00188 if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 00189 Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 00190 OS << " " << CallFrameString(Opcode) << ":\n"; 00191 } 00192 } 00193 00194 00195 namespace { 00196 /// \brief DWARF Common Information Entry (CIE) 00197 class CIE : public FrameEntry { 00198 public: 00199 // CIEs (and FDEs) are simply container classes, so the only sensible way to 00200 // create them is by providing the full parsed contents in the constructor. 00201 CIE(uint64_t Offset, uint64_t Length, uint8_t Version, 00202 SmallString<8> Augmentation, uint64_t CodeAlignmentFactor, 00203 int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) 00204 : FrameEntry(FK_CIE, Offset, Length), Version(Version), 00205 Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor), 00206 DataAlignmentFactor(DataAlignmentFactor), 00207 ReturnAddressRegister(ReturnAddressRegister) {} 00208 00209 ~CIE() { 00210 } 00211 00212 void dumpHeader(raw_ostream &OS) const override { 00213 OS << format("%08x %08x %08x CIE", 00214 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) 00215 << "\n"; 00216 OS << format(" Version: %d\n", Version); 00217 OS << " Augmentation: \"" << Augmentation << "\"\n"; 00218 OS << format(" Code alignment factor: %u\n", 00219 (uint32_t)CodeAlignmentFactor); 00220 OS << format(" Data alignment factor: %d\n", 00221 (int32_t)DataAlignmentFactor); 00222 OS << format(" Return address column: %d\n", 00223 (int32_t)ReturnAddressRegister); 00224 OS << "\n"; 00225 } 00226 00227 static bool classof(const FrameEntry *FE) { 00228 return FE->getKind() == FK_CIE; 00229 } 00230 00231 private: 00232 /// The following fields are defined in section 6.4.1 of the DWARF standard v3 00233 uint8_t Version; 00234 SmallString<8> Augmentation; 00235 uint64_t CodeAlignmentFactor; 00236 int64_t DataAlignmentFactor; 00237 uint64_t ReturnAddressRegister; 00238 }; 00239 00240 00241 /// \brief DWARF Frame Description Entry (FDE) 00242 class FDE : public FrameEntry { 00243 public: 00244 // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 00245 // an offset to the CIE (provided by parsing the FDE header). The CIE itself 00246 // is obtained lazily once it's actually required. 00247 FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, 00248 uint64_t InitialLocation, uint64_t AddressRange) 00249 : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), 00250 InitialLocation(InitialLocation), AddressRange(AddressRange), 00251 LinkedCIE(nullptr) {} 00252 00253 ~FDE() { 00254 } 00255 00256 void dumpHeader(raw_ostream &OS) const override { 00257 OS << format("%08x %08x %08x FDE ", 00258 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); 00259 OS << format("cie=%08x pc=%08x...%08x\n", 00260 (int32_t)LinkedCIEOffset, 00261 (uint32_t)InitialLocation, 00262 (uint32_t)InitialLocation + (uint32_t)AddressRange); 00263 if (LinkedCIE) { 00264 OS << format("%p\n", LinkedCIE); 00265 } 00266 } 00267 00268 static bool classof(const FrameEntry *FE) { 00269 return FE->getKind() == FK_FDE; 00270 } 00271 00272 private: 00273 /// The following fields are defined in section 6.4.1 of the DWARF standard v3 00274 uint64_t LinkedCIEOffset; 00275 uint64_t InitialLocation; 00276 uint64_t AddressRange; 00277 CIE *LinkedCIE; 00278 }; 00279 } // end anonymous namespace 00280 00281 00282 DWARFDebugFrame::DWARFDebugFrame() { 00283 } 00284 00285 DWARFDebugFrame::~DWARFDebugFrame() { 00286 } 00287 00288 static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 00289 uint32_t Offset, int Length) { 00290 errs() << "DUMP: "; 00291 for (int i = 0; i < Length; ++i) { 00292 uint8_t c = Data.getU8(&Offset); 00293 errs().write_hex(c); errs() << " "; 00294 } 00295 errs() << "\n"; 00296 } 00297 00298 00299 void DWARFDebugFrame::parse(DataExtractor Data) { 00300 uint32_t Offset = 0; 00301 00302 while (Data.isValidOffset(Offset)) { 00303 uint32_t StartOffset = Offset; 00304 00305 bool IsDWARF64 = false; 00306 uint64_t Length = Data.getU32(&Offset); 00307 uint64_t Id; 00308 00309 if (Length == UINT32_MAX) { 00310 // DWARF-64 is distinguished by the first 32 bits of the initial length 00311 // field being 0xffffffff. Then, the next 64 bits are the actual entry 00312 // length. 00313 IsDWARF64 = true; 00314 Length = Data.getU64(&Offset); 00315 } 00316 00317 // At this point, Offset points to the next field after Length. 00318 // Length is the structure size excluding itself. Compute an offset one 00319 // past the end of the structure (needed to know how many instructions to 00320 // read). 00321 // TODO: For honest DWARF64 support, DataExtractor will have to treat 00322 // offset_ptr as uint64_t* 00323 uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); 00324 00325 // The Id field's size depends on the DWARF format 00326 Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4); 00327 bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID); 00328 00329 if (IsCIE) { 00330 // Note: this is specifically DWARFv3 CIE header structure. It was 00331 // changed in DWARFv4. We currently don't support reading DWARFv4 00332 // here because LLVM itself does not emit it (and LLDB doesn't 00333 // support it either). 00334 uint8_t Version = Data.getU8(&Offset); 00335 const char *Augmentation = Data.getCStr(&Offset); 00336 uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 00337 int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 00338 uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); 00339 00340 Entries.emplace_back(new CIE(StartOffset, Length, Version, 00341 StringRef(Augmentation), CodeAlignmentFactor, 00342 DataAlignmentFactor, ReturnAddressRegister)); 00343 } else { 00344 // FDE 00345 uint64_t CIEPointer = Id; 00346 uint64_t InitialLocation = Data.getAddress(&Offset); 00347 uint64_t AddressRange = Data.getAddress(&Offset); 00348 00349 Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, 00350 InitialLocation, AddressRange)); 00351 } 00352 00353 Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); 00354 00355 if (Offset != EndStructureOffset) { 00356 std::string Str; 00357 raw_string_ostream OS(Str); 00358 OS << format("Parsing entry instructions at %lx failed", StartOffset); 00359 report_fatal_error(Str); 00360 } 00361 } 00362 } 00363 00364 00365 void DWARFDebugFrame::dump(raw_ostream &OS) const { 00366 OS << "\n"; 00367 for (const auto &Entry : Entries) { 00368 Entry->dumpHeader(OS); 00369 Entry->dumpInstructions(OS); 00370 OS << "\n"; 00371 } 00372 } 00373