119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===-- DWARFContext.cpp --------------------------------------------------===// 219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// The LLVM Compiler Infrastructure 419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source 619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details. 719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// 819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===// 919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "DWARFContext.h" 1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/Dwarf.h" 1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/Format.h" 1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/raw_ostream.h" 1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include <algorithm> 1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanusing namespace llvm; 1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanusing namespace dwarf; 1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid DWARFContext::dump(raw_ostream &OS) { 1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OS << ".debug_abbrev contents:\n"; 2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman getDebugAbbrev()->dump(OS); 2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OS << "\n.debug_info contents:\n"; 2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) 2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman getCompileUnitAtIndex(i)->dump(OS); 2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OS << "\n.debug_aranges contents:\n"; 2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t offset = 0; 2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DWARFDebugArangeSet set; 3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman while (set.extract(arangesData, &offset)) 3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman set.dump(OS); 3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OS << "\n.debug_lines contents:\n"; 3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) { 3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DWARFCompileUnit *cu = getCompileUnitAtIndex(i); 3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned stmtOffset = 3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, 3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman -1U); 3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (stmtOffset != -1U) { 4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DataExtractor lineData(getLineSection(), isLittleEndian(), 4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman cu->getAddressByteSize()); 4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DWARFDebugLine::DumpingState state(OS); 4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state); 4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OS << "\n.debug_str contents:\n"; 4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DataExtractor strData(getStringSection(), isLittleEndian(), 0); 4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman offset = 0; 5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t lastOffset = 0; 5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman while (const char *s = strData.getCStr(&offset)) { 5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OS << format("0x%8.8x: \"%s\"\n", lastOffset, s); 5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman lastOffset = offset; 5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { 5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Abbrev) 5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Abbrev.get(); 6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); 6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Abbrev.reset(new DWARFDebugAbbrev()); 6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Abbrev->parse(abbrData); 6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Abbrev.get(); 6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst DWARFDebugAranges *DWARFContext::getDebugAranges() { 6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Aranges) 7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Aranges.get(); 7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0); 7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Aranges.reset(new DWARFDebugAranges()); 7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Aranges->extract(arangesData); 7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs. 7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Aranges->generate(this); 7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Aranges.get(); 7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst DWARFDebugLine::LineTable * 8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanDWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { 8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!Line) 8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman Line.reset(new DWARFDebugLine()); 8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman unsigned stmtOffset = 8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list, 8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman -1U); 8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (stmtOffset == -1U) 9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return 0; // No line table for this compile unit. 9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // See if the line table is cached. 9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset)) 9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return lt; 9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // We have to parse it first. 9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DataExtractor lineData(getLineSection(), isLittleEndian(), 9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman cu->getAddressByteSize()); 9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return Line->getOrParseLineTable(lineData, stmtOffset); 10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid DWARFContext::parseCompileUnits() { 10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t offset = 0; 10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const DataExtractor &debug_info_data = DataExtractor(getInfoSection(), 10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman isLittleEndian(), 0); 10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman while (debug_info_data.isValidOffset(offset)) { 10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman CUs.push_back(DWARFCompileUnit(*this)); 10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!CUs.back().extract(debug_info_data, &offset)) { 10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman CUs.pop_back(); 11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman break; 11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman offset = CUs.back().getNextCompileUnitOffset(); 11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace { 11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman struct OffsetComparator { 11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool operator()(const DWARFCompileUnit &LHS, 12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const DWARFCompileUnit &RHS) const { 12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return LHS.getOffset() < RHS.getOffset(); 12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const { 12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return LHS.getOffset() < RHS; 12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const { 12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return LHS < RHS.getOffset(); 12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman } 12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman }; 13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanDWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) { 13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (CUs.empty()) 13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman parseCompileUnits(); 13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DWARFCompileUnit *i = std::lower_bound(CUs.begin(), CUs.end(), offset, 13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman OffsetComparator()); 13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (i != CUs.end()) 13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return &*i; 14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return 0; 14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanDILineInfo DWARFContext::getLineInfoForAddress(uint64_t address) { 14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // First, get the offset of the compile unit. 14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t cuOffset = getDebugAranges()->findAddress(address); 14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Retrieve the compile unit. 14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset); 14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!cu) 14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return DILineInfo("<invalid>", 0, 0); 15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Get the line table for this compile unit. 15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu); 15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (!lineTable) 15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return DILineInfo("<invalid>", 0, 0); 15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // Get the index of the row we're looking for in the line table. 15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint64_t hiPC = 15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_high_pc, 15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman -1ULL); 15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman uint32_t rowIndex = lineTable->lookupAddress(address, hiPC); 15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman if (rowIndex == -1U) 16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return DILineInfo("<invalid>", 0, 0); 16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman // From here, contruct the DILineInfo. 16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex]; 16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman const std::string &fileName = lineTable->Prologue.FileNames[row.File-1].Name; 16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman 16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman return DILineInfo(fileName.c_str(), row.Line, row.Column); 16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} 168