1249259Sdim//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#include "DWARFDebugFrame.h" 11249259Sdim#include "llvm/ADT/SmallString.h" 12249259Sdim#include "llvm/Support/DataTypes.h" 13249259Sdim#include "llvm/Support/ErrorHandling.h" 14249259Sdim#include "llvm/Support/Dwarf.h" 15249259Sdim#include "llvm/Support/Format.h" 16249259Sdim#include "llvm/Support/raw_ostream.h" 17249259Sdim#include <string> 18249259Sdim#include <vector> 19249259Sdim 20249259Sdimusing namespace llvm; 21249259Sdimusing namespace dwarf; 22249259Sdim 23249259Sdim 24249259Sdim/// \brief Abstract frame entry defining the common interface concrete 25249259Sdim/// entries implement. 26249259Sdimclass llvm::FrameEntry { 27249259Sdimpublic: 28249259Sdim enum FrameKind {FK_CIE, FK_FDE}; 29249259Sdim FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length) 30249259Sdim : Kind(K), Data(D), Offset(Offset), Length(Length) {} 31249259Sdim 32249259Sdim virtual ~FrameEntry() { 33249259Sdim } 34249259Sdim 35249259Sdim FrameKind getKind() const { return Kind; } 36249259Sdim virtual uint64_t getOffset() const { return Offset; } 37249259Sdim 38249259Sdim /// \brief Parse and store a sequence of CFI instructions from our data 39249259Sdim /// stream, starting at *Offset and ending at EndOffset. If everything 40249259Sdim /// goes well, *Offset should be equal to EndOffset when this method 41249259Sdim /// returns. Otherwise, an error occurred. 42249259Sdim virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset); 43249259Sdim 44249259Sdim /// \brief Dump the entry header to the given output stream. 45249259Sdim virtual void dumpHeader(raw_ostream &OS) const = 0; 46249259Sdim 47249259Sdim /// \brief Dump the entry's instructions to the given output stream. 48249259Sdim virtual void dumpInstructions(raw_ostream &OS) const; 49249259Sdim 50249259Sdimprotected: 51249259Sdim const FrameKind Kind; 52249259Sdim 53249259Sdim /// \brief The data stream holding the section from which the entry was 54249259Sdim /// parsed. 55249259Sdim DataExtractor Data; 56249259Sdim 57249259Sdim /// \brief Offset of this entry in the section. 58249259Sdim uint64_t Offset; 59249259Sdim 60249259Sdim /// \brief Entry length as specified in DWARF. 61249259Sdim uint64_t Length; 62249259Sdim 63249259Sdim /// An entry may contain CFI instructions. An instruction consists of an 64249259Sdim /// opcode and an optional sequence of operands. 65249259Sdim typedef std::vector<uint64_t> Operands; 66249259Sdim struct Instruction { 67249259Sdim Instruction(uint8_t Opcode) 68249259Sdim : Opcode(Opcode) 69249259Sdim {} 70249259Sdim 71249259Sdim uint8_t Opcode; 72249259Sdim Operands Ops; 73249259Sdim }; 74249259Sdim 75249259Sdim std::vector<Instruction> Instructions; 76249259Sdim 77249259Sdim /// Convenience methods to add a new instruction with the given opcode and 78249259Sdim /// operands to the Instructions vector. 79249259Sdim void addInstruction(uint8_t Opcode) { 80249259Sdim Instructions.push_back(Instruction(Opcode)); 81249259Sdim } 82249259Sdim 83249259Sdim void addInstruction(uint8_t Opcode, uint64_t Operand1) { 84249259Sdim Instructions.push_back(Instruction(Opcode)); 85249259Sdim Instructions.back().Ops.push_back(Operand1); 86249259Sdim } 87249259Sdim 88249259Sdim void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { 89249259Sdim Instructions.push_back(Instruction(Opcode)); 90249259Sdim Instructions.back().Ops.push_back(Operand1); 91249259Sdim Instructions.back().Ops.push_back(Operand2); 92249259Sdim } 93249259Sdim}; 94249259Sdim 95249259Sdim 96249259Sdim// See DWARF standard v3, section 7.23 97249259Sdimconst uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; 98249259Sdimconst uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; 99249259Sdim 100249259Sdim 101249259Sdimvoid FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) { 102249259Sdim while (*Offset < EndOffset) { 103249259Sdim uint8_t Opcode = Data.getU8(Offset); 104249259Sdim // Some instructions have a primary opcode encoded in the top bits. 105249259Sdim uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; 106249259Sdim 107249259Sdim if (Primary) { 108249259Sdim // If it's a primary opcode, the first operand is encoded in the bottom 109249259Sdim // bits of the opcode itself. 110249259Sdim uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; 111249259Sdim switch (Primary) { 112249259Sdim default: llvm_unreachable("Impossible primary CFI opcode"); 113249259Sdim case DW_CFA_advance_loc: 114249259Sdim case DW_CFA_restore: 115249259Sdim addInstruction(Primary, Op1); 116249259Sdim break; 117249259Sdim case DW_CFA_offset: 118249259Sdim addInstruction(Primary, Op1, Data.getULEB128(Offset)); 119249259Sdim break; 120249259Sdim } 121249259Sdim } else { 122249259Sdim // Extended opcode - its value is Opcode itself. 123249259Sdim switch (Opcode) { 124249259Sdim default: llvm_unreachable("Invalid extended CFI opcode"); 125249259Sdim case DW_CFA_nop: 126249259Sdim case DW_CFA_remember_state: 127249259Sdim case DW_CFA_restore_state: 128249259Sdim // No operands 129249259Sdim addInstruction(Opcode); 130249259Sdim break; 131249259Sdim case DW_CFA_set_loc: 132249259Sdim // Operands: Address 133249259Sdim addInstruction(Opcode, Data.getAddress(Offset)); 134249259Sdim break; 135249259Sdim case DW_CFA_advance_loc1: 136249259Sdim // Operands: 1-byte delta 137249259Sdim addInstruction(Opcode, Data.getU8(Offset)); 138249259Sdim break; 139249259Sdim case DW_CFA_advance_loc2: 140249259Sdim // Operands: 2-byte delta 141249259Sdim addInstruction(Opcode, Data.getU16(Offset)); 142249259Sdim break; 143249259Sdim case DW_CFA_advance_loc4: 144249259Sdim // Operands: 4-byte delta 145249259Sdim addInstruction(Opcode, Data.getU32(Offset)); 146249259Sdim break; 147249259Sdim case DW_CFA_restore_extended: 148249259Sdim case DW_CFA_undefined: 149249259Sdim case DW_CFA_same_value: 150249259Sdim case DW_CFA_def_cfa_register: 151249259Sdim case DW_CFA_def_cfa_offset: 152249259Sdim // Operands: ULEB128 153249259Sdim addInstruction(Opcode, Data.getULEB128(Offset)); 154249259Sdim break; 155249259Sdim case DW_CFA_def_cfa_offset_sf: 156249259Sdim // Operands: SLEB128 157249259Sdim addInstruction(Opcode, Data.getSLEB128(Offset)); 158249259Sdim break; 159249259Sdim case DW_CFA_offset_extended: 160249259Sdim case DW_CFA_register: 161249259Sdim case DW_CFA_def_cfa: 162249259Sdim case DW_CFA_val_offset: 163249259Sdim // Operands: ULEB128, ULEB128 164249259Sdim addInstruction(Opcode, Data.getULEB128(Offset), 165249259Sdim Data.getULEB128(Offset)); 166249259Sdim break; 167249259Sdim case DW_CFA_offset_extended_sf: 168249259Sdim case DW_CFA_def_cfa_sf: 169249259Sdim case DW_CFA_val_offset_sf: 170249259Sdim // Operands: ULEB128, SLEB128 171249259Sdim addInstruction(Opcode, Data.getULEB128(Offset), 172249259Sdim Data.getSLEB128(Offset)); 173249259Sdim break; 174249259Sdim case DW_CFA_def_cfa_expression: 175249259Sdim case DW_CFA_expression: 176249259Sdim case DW_CFA_val_expression: 177249259Sdim // TODO: implement this 178249259Sdim report_fatal_error("Values with expressions not implemented yet!"); 179249259Sdim } 180249259Sdim } 181249259Sdim } 182249259Sdim} 183249259Sdim 184249259Sdim 185249259Sdimvoid FrameEntry::dumpInstructions(raw_ostream &OS) const { 186249259Sdim // TODO: at the moment only instruction names are dumped. Expand this to 187249259Sdim // dump operands as well. 188249259Sdim for (std::vector<Instruction>::const_iterator I = Instructions.begin(), 189249259Sdim E = Instructions.end(); 190249259Sdim I != E; ++I) { 191249259Sdim uint8_t Opcode = I->Opcode; 192249259Sdim if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) 193249259Sdim Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; 194249259Sdim OS << " " << CallFrameString(Opcode) << ":\n"; 195249259Sdim } 196249259Sdim} 197249259Sdim 198249259Sdim 199249259Sdimnamespace { 200249259Sdim/// \brief DWARF Common Information Entry (CIE) 201249259Sdimclass CIE : public FrameEntry { 202249259Sdimpublic: 203249259Sdim // CIEs (and FDEs) are simply container classes, so the only sensible way to 204249259Sdim // create them is by providing the full parsed contents in the constructor. 205249259Sdim CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version, 206249259Sdim SmallString<8> Augmentation, uint64_t CodeAlignmentFactor, 207249259Sdim int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) 208249259Sdim : FrameEntry(FK_CIE, D, Offset, Length), Version(Version), 209249259Sdim Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor), 210249259Sdim DataAlignmentFactor(DataAlignmentFactor), 211249259Sdim ReturnAddressRegister(ReturnAddressRegister) {} 212249259Sdim 213249259Sdim ~CIE() { 214249259Sdim } 215249259Sdim 216249259Sdim void dumpHeader(raw_ostream &OS) const { 217249259Sdim OS << format("%08x %08x %08x CIE", 218249259Sdim (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) 219249259Sdim << "\n"; 220249259Sdim OS << format(" Version: %d\n", Version); 221249259Sdim OS << " Augmentation: \"" << Augmentation << "\"\n"; 222249259Sdim OS << format(" Code alignment factor: %u\n", 223249259Sdim (uint32_t)CodeAlignmentFactor); 224249259Sdim OS << format(" Data alignment factor: %d\n", 225249259Sdim (int32_t)DataAlignmentFactor); 226249259Sdim OS << format(" Return address column: %d\n", 227249259Sdim (int32_t)ReturnAddressRegister); 228249259Sdim OS << "\n"; 229249259Sdim } 230249259Sdim 231249259Sdim static bool classof(const FrameEntry *FE) { 232249259Sdim return FE->getKind() == FK_CIE; 233249259Sdim } 234249259Sdim 235249259Sdimprivate: 236249259Sdim /// The following fields are defined in section 6.4.1 of the DWARF standard v3 237249259Sdim uint8_t Version; 238249259Sdim SmallString<8> Augmentation; 239249259Sdim uint64_t CodeAlignmentFactor; 240249259Sdim int64_t DataAlignmentFactor; 241249259Sdim uint64_t ReturnAddressRegister; 242249259Sdim}; 243249259Sdim 244249259Sdim 245249259Sdim/// \brief DWARF Frame Description Entry (FDE) 246249259Sdimclass FDE : public FrameEntry { 247249259Sdimpublic: 248249259Sdim // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with 249249259Sdim // an offset to the CIE (provided by parsing the FDE header). The CIE itself 250249259Sdim // is obtained lazily once it's actually required. 251249259Sdim FDE(DataExtractor D, uint64_t Offset, uint64_t Length, 252249259Sdim int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange) 253249259Sdim : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), 254249259Sdim InitialLocation(InitialLocation), AddressRange(AddressRange), 255249259Sdim LinkedCIE(NULL) {} 256249259Sdim 257249259Sdim ~FDE() { 258249259Sdim } 259249259Sdim 260249259Sdim void dumpHeader(raw_ostream &OS) const { 261249259Sdim OS << format("%08x %08x %08x FDE ", 262249259Sdim (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); 263249259Sdim OS << format("cie=%08x pc=%08x...%08x\n", 264249259Sdim (int32_t)LinkedCIEOffset, 265249259Sdim (uint32_t)InitialLocation, 266249259Sdim (uint32_t)InitialLocation + (uint32_t)AddressRange); 267249259Sdim if (LinkedCIE) { 268249259Sdim OS << format("%p\n", LinkedCIE); 269249259Sdim } 270249259Sdim } 271249259Sdim 272249259Sdim static bool classof(const FrameEntry *FE) { 273249259Sdim return FE->getKind() == FK_FDE; 274249259Sdim } 275249259Sdimprivate: 276249259Sdim 277249259Sdim /// The following fields are defined in section 6.4.1 of the DWARF standard v3 278249259Sdim uint64_t LinkedCIEOffset; 279249259Sdim uint64_t InitialLocation; 280249259Sdim uint64_t AddressRange; 281249259Sdim CIE *LinkedCIE; 282249259Sdim}; 283249259Sdim} // end anonymous namespace 284249259Sdim 285249259Sdim 286249259SdimDWARFDebugFrame::DWARFDebugFrame() { 287249259Sdim} 288249259Sdim 289249259Sdim 290249259SdimDWARFDebugFrame::~DWARFDebugFrame() { 291249259Sdim for (EntryVector::iterator I = Entries.begin(), E = Entries.end(); 292249259Sdim I != E; ++I) { 293249259Sdim delete *I; 294249259Sdim } 295249259Sdim} 296249259Sdim 297249259Sdim 298249259Sdimstatic void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, 299249259Sdim uint32_t Offset, int Length) { 300249259Sdim errs() << "DUMP: "; 301249259Sdim for (int i = 0; i < Length; ++i) { 302249259Sdim uint8_t c = Data.getU8(&Offset); 303249259Sdim errs().write_hex(c); errs() << " "; 304249259Sdim } 305249259Sdim errs() << "\n"; 306249259Sdim} 307249259Sdim 308249259Sdim 309249259Sdimvoid DWARFDebugFrame::parse(DataExtractor Data) { 310249259Sdim uint32_t Offset = 0; 311249259Sdim 312249259Sdim while (Data.isValidOffset(Offset)) { 313249259Sdim uint32_t StartOffset = Offset; 314249259Sdim 315249259Sdim bool IsDWARF64 = false; 316249259Sdim uint64_t Length = Data.getU32(&Offset); 317249259Sdim uint64_t Id; 318249259Sdim 319249259Sdim if (Length == UINT32_MAX) { 320249259Sdim // DWARF-64 is distinguished by the first 32 bits of the initial length 321249259Sdim // field being 0xffffffff. Then, the next 64 bits are the actual entry 322249259Sdim // length. 323249259Sdim IsDWARF64 = true; 324249259Sdim Length = Data.getU64(&Offset); 325249259Sdim } 326249259Sdim 327249259Sdim // At this point, Offset points to the next field after Length. 328249259Sdim // Length is the structure size excluding itself. Compute an offset one 329249259Sdim // past the end of the structure (needed to know how many instructions to 330249259Sdim // read). 331249259Sdim // TODO: For honest DWARF64 support, DataExtractor will have to treat 332249259Sdim // offset_ptr as uint64_t* 333249259Sdim uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); 334249259Sdim 335249259Sdim // The Id field's size depends on the DWARF format 336249259Sdim Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4); 337249259Sdim bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID); 338249259Sdim 339249259Sdim FrameEntry *Entry = 0; 340249259Sdim if (IsCIE) { 341249259Sdim // Note: this is specifically DWARFv3 CIE header structure. It was 342249259Sdim // changed in DWARFv4. We currently don't support reading DWARFv4 343249259Sdim // here because LLVM itself does not emit it (and LLDB doesn't 344249259Sdim // support it either). 345249259Sdim uint8_t Version = Data.getU8(&Offset); 346249259Sdim const char *Augmentation = Data.getCStr(&Offset); 347249259Sdim uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); 348249259Sdim int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); 349249259Sdim uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); 350249259Sdim 351249259Sdim Entry = new CIE(Data, StartOffset, Length, Version, 352249259Sdim StringRef(Augmentation), CodeAlignmentFactor, 353249259Sdim DataAlignmentFactor, ReturnAddressRegister); 354249259Sdim } else { 355249259Sdim // FDE 356249259Sdim uint64_t CIEPointer = Id; 357249259Sdim uint64_t InitialLocation = Data.getAddress(&Offset); 358249259Sdim uint64_t AddressRange = Data.getAddress(&Offset); 359249259Sdim 360249259Sdim Entry = new FDE(Data, StartOffset, Length, CIEPointer, 361249259Sdim InitialLocation, AddressRange); 362249259Sdim } 363249259Sdim 364249259Sdim assert(Entry && "Expected Entry to be populated with CIE or FDE"); 365249259Sdim Entry->parseInstructions(&Offset, EndStructureOffset); 366249259Sdim 367249259Sdim if (Offset == EndStructureOffset) { 368249259Sdim // Entry instrucitons parsed successfully. 369249259Sdim Entries.push_back(Entry); 370249259Sdim } else { 371249259Sdim std::string Str; 372249259Sdim raw_string_ostream OS(Str); 373249259Sdim OS << format("Parsing entry instructions at %lx failed", 374249259Sdim Entry->getOffset()); 375249259Sdim report_fatal_error(Str); 376249259Sdim } 377249259Sdim } 378249259Sdim} 379249259Sdim 380249259Sdim 381249259Sdimvoid DWARFDebugFrame::dump(raw_ostream &OS) const { 382249259Sdim OS << "\n"; 383249259Sdim for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end(); 384249259Sdim I != E; ++I) { 385249259Sdim FrameEntry *Entry = *I; 386249259Sdim Entry->dumpHeader(OS); 387249259Sdim Entry->dumpInstructions(OS); 388249259Sdim OS << "\n"; 389249259Sdim } 390249259Sdim} 391249259Sdim 392