DWARFContext.cpp revision 9d26b0ba06479d9debadebce19344169f72407dd
1//===-- DWARFContext.cpp --------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "DWARFContext.h" 11#include "llvm/Support/Dwarf.h" 12#include "llvm/Support/Format.h" 13#include "llvm/Support/raw_ostream.h" 14#include <algorithm> 15using namespace llvm; 16using namespace dwarf; 17 18void DWARFContext::dump(raw_ostream &OS) { 19 OS << ".debug_abbrev contents:\n"; 20 getDebugAbbrev()->dump(OS); 21 22 OS << "\n.debug_info contents:\n"; 23 for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) 24 getCompileUnitAtIndex(i)->dump(OS); 25 26 OS << "\n.debug_aranges contents:\n"; 27 DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 28 uint32_t offset = 0; 29 DWARFDebugArangeSet set; 30 while (set.extract(arangesData, &offset)) 31 set.dump(OS); 32 33 OS << "\n.debug_lines contents:\n"; 34 for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) { 35 DWARFCompileUnit *cu = getCompileUnitAtIndex(i); 36 unsigned stmtOffset = 37 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, 38 -1U); 39 if (stmtOffset != -1U) { 40 DataExtractor lineData(getLineSection(), isLittleEndian(), 41 cu->getAddressByteSize()); 42 DWARFDebugLine::DumpingState state(OS); 43 DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state); 44 } 45 } 46 47 OS << "\n.debug_str contents:\n"; 48 DataExtractor strData(getStringSection(), isLittleEndian(), 0); 49 offset = 0; 50 uint32_t lastOffset = 0; 51 while (const char *s = strData.getCStr(&offset)) { 52 OS << format("0x%8.8x: \"%s\"\n", lastOffset, s); 53 lastOffset = offset; 54 } 55} 56 57const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { 58 if (Abbrev) 59 return Abbrev.get(); 60 61 DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); 62 63 Abbrev.reset(new DWARFDebugAbbrev()); 64 Abbrev->parse(abbrData); 65 return Abbrev.get(); 66} 67 68const DWARFDebugAranges *DWARFContext::getDebugAranges() { 69 if (Aranges) 70 return Aranges.get(); 71 72 DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 73 74 Aranges.reset(new DWARFDebugAranges()); 75 Aranges->extract(arangesData); 76 if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs. 77 Aranges->generate(this); 78 return Aranges.get(); 79} 80 81const DWARFDebugLine::LineTable * 82DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { 83 if (!Line) 84 Line.reset(new DWARFDebugLine()); 85 86 unsigned stmtOffset = 87 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, 88 -1U); 89 if (stmtOffset == -1U) 90 return 0; // No line table for this compile unit. 91 92 // See if the line table is cached. 93 if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset)) 94 return lt; 95 96 // We have to parse it first. 97 DataExtractor lineData(getLineSection(), isLittleEndian(), 98 cu->getAddressByteSize()); 99 return Line->getOrParseLineTable(lineData, stmtOffset); 100} 101 102void DWARFContext::parseCompileUnits() { 103 uint32_t offset = 0; 104 const DataExtractor &debug_info_data = DataExtractor(getInfoSection(), 105 isLittleEndian(), 0); 106 while (debug_info_data.isValidOffset(offset)) { 107 CUs.push_back(DWARFCompileUnit(*this)); 108 if (!CUs.back().extract(debug_info_data, &offset)) { 109 CUs.pop_back(); 110 break; 111 } 112 113 offset = CUs.back().getNextCompileUnitOffset(); 114 } 115} 116 117namespace { 118 struct OffsetComparator { 119 bool operator()(const DWARFCompileUnit &LHS, 120 const DWARFCompileUnit &RHS) const { 121 return LHS.getOffset() < RHS.getOffset(); 122 } 123 bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const { 124 return LHS.getOffset() < RHS; 125 } 126 bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const { 127 return LHS < RHS.getOffset(); 128 } 129 }; 130} 131 132DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) { 133 if (CUs.empty()) 134 parseCompileUnits(); 135 136 DWARFCompileUnit *i = std::lower_bound(CUs.begin(), CUs.end(), offset, 137 OffsetComparator()); 138 if (i != CUs.end()) 139 return &*i; 140 return 0; 141} 142 143DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address, 144 DILineInfoSpecifier specifier) { 145 // First, get the offset of the compile unit. 146 uint32_t cuOffset = getDebugAranges()->findAddress(address); 147 // Retrieve the compile unit. 148 DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset); 149 if (!cu) 150 return DILineInfo(); 151 const char *fileName = "<invalid>"; 152 const char *functionName = "<invalid>"; 153 uint32_t line = 0; 154 uint32_t column = 0; 155 if (specifier.needs(DILineInfoSpecifier::FunctionName)) { 156 const DWARFDebugInfoEntryMinimal *function_die = 157 cu->getFunctionDIEForAddress(address); 158 if (function_die) { 159 if (const char *name = function_die->getSubprogramName(cu)) 160 functionName = name; 161 } 162 } 163 if (specifier.needs(DILineInfoSpecifier::FileLineInfo)) { 164 // Get the line table for this compile unit. 165 const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); 166 if (lineTable) { 167 // Get the index of the row we're looking for in the line table. 168 uint64_t hiPC = cu->getCompileUnitDIE()->getAttributeValueAsUnsigned( 169 cu, DW_AT_high_pc, -1ULL); 170 uint32_t rowIndex = lineTable->lookupAddress(address, hiPC); 171 if (rowIndex != -1U) { 172 const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; 173 // Take file/line info from the line table. 174 fileName = lineTable->Prologue.FileNames[row.File - 1].Name.c_str(); 175 line = row.Line; 176 column = row.Column; 177 } 178 } 179 } 180 return DILineInfo(fileName, functionName, line, column); 181} 182 183void DWARFContextInMemory::anchor() { } 184