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