mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146960 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			170 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===-- DWARFContext.cpp --------------------------------------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "DWARFContext.h"
 | 
						|
#include "llvm/Support/Dwarf.h"
 | 
						|
#include "llvm/Support/Format.h"
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
#include <algorithm>
 | 
						|
using namespace llvm;
 | 
						|
using namespace dwarf;
 | 
						|
 | 
						|
void DWARFContext::dump(raw_ostream &OS) {
 | 
						|
  OS << ".debug_abbrev contents:\n";
 | 
						|
  getDebugAbbrev()->dump(OS);
 | 
						|
 | 
						|
  OS << "\n.debug_info contents:\n";
 | 
						|
  for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i)
 | 
						|
    getCompileUnitAtIndex(i)->dump(OS);
 | 
						|
 | 
						|
  OS << "\n.debug_aranges contents:\n";
 | 
						|
  DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
 | 
						|
  uint32_t offset = 0;
 | 
						|
  DWARFDebugArangeSet set;
 | 
						|
  while (set.extract(arangesData, &offset))
 | 
						|
    set.dump(OS);
 | 
						|
 | 
						|
  OS << "\n.debug_lines contents:\n";
 | 
						|
  for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) {
 | 
						|
    DWARFCompileUnit *cu = getCompileUnitAtIndex(i);
 | 
						|
    unsigned stmtOffset =
 | 
						|
      cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
 | 
						|
                                                           -1U);
 | 
						|
    if (stmtOffset != -1U) {
 | 
						|
      DataExtractor lineData(getLineSection(), isLittleEndian(),
 | 
						|
                             cu->getAddressByteSize());
 | 
						|
      DWARFDebugLine::DumpingState state(OS);
 | 
						|
      DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  OS << "\n.debug_str contents:\n";
 | 
						|
  DataExtractor strData(getStringSection(), isLittleEndian(), 0);
 | 
						|
  offset = 0;
 | 
						|
  uint32_t lastOffset = 0;
 | 
						|
  while (const char *s = strData.getCStr(&offset)) {
 | 
						|
    OS << format("0x%8.8x: \"%s\"\n", lastOffset, s);
 | 
						|
    lastOffset = offset;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
 | 
						|
  if (Abbrev)
 | 
						|
    return Abbrev.get();
 | 
						|
 | 
						|
  DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
 | 
						|
 | 
						|
  Abbrev.reset(new DWARFDebugAbbrev());
 | 
						|
  Abbrev->parse(abbrData);
 | 
						|
  return Abbrev.get();
 | 
						|
}
 | 
						|
 | 
						|
const DWARFDebugAranges *DWARFContext::getDebugAranges() {
 | 
						|
  if (Aranges)
 | 
						|
    return Aranges.get();
 | 
						|
 | 
						|
  DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
 | 
						|
 | 
						|
  Aranges.reset(new DWARFDebugAranges());
 | 
						|
  Aranges->extract(arangesData);
 | 
						|
  if (Aranges->isEmpty()) // No aranges in file, generate them from the DIEs.
 | 
						|
    Aranges->generate(this);
 | 
						|
  return Aranges.get();
 | 
						|
}
 | 
						|
 | 
						|
const DWARFDebugLine::LineTable *
 | 
						|
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
 | 
						|
  if (!Line)
 | 
						|
    Line.reset(new DWARFDebugLine());
 | 
						|
 | 
						|
  unsigned stmtOffset =
 | 
						|
    cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
 | 
						|
                                                         -1U);
 | 
						|
  if (stmtOffset == -1U)
 | 
						|
    return 0; // No line table for this compile unit.
 | 
						|
 | 
						|
  // See if the line table is cached.
 | 
						|
  if (const DWARFDebugLine::LineTable *lt = Line->getLineTable(stmtOffset))
 | 
						|
    return lt;
 | 
						|
 | 
						|
  // We have to parse it first.
 | 
						|
  DataExtractor lineData(getLineSection(), isLittleEndian(),
 | 
						|
                         cu->getAddressByteSize());
 | 
						|
  return Line->getOrParseLineTable(lineData, stmtOffset);
 | 
						|
}
 | 
						|
 | 
						|
void DWARFContext::parseCompileUnits() {
 | 
						|
  uint32_t offset = 0;
 | 
						|
  const DataExtractor &debug_info_data = DataExtractor(getInfoSection(),
 | 
						|
                                                       isLittleEndian(), 0);
 | 
						|
  while (debug_info_data.isValidOffset(offset)) {
 | 
						|
    CUs.push_back(DWARFCompileUnit(*this));
 | 
						|
    if (!CUs.back().extract(debug_info_data, &offset)) {
 | 
						|
      CUs.pop_back();
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    offset = CUs.back().getNextCompileUnitOffset();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace {
 | 
						|
  struct OffsetComparator {
 | 
						|
    bool operator()(const DWARFCompileUnit &LHS,
 | 
						|
                    const DWARFCompileUnit &RHS) const {
 | 
						|
      return LHS.getOffset() < RHS.getOffset();
 | 
						|
    }
 | 
						|
    bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const {
 | 
						|
      return LHS.getOffset() < RHS;
 | 
						|
    }
 | 
						|
    bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const {
 | 
						|
      return LHS < RHS.getOffset();
 | 
						|
    }
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t offset) {
 | 
						|
  if (CUs.empty())
 | 
						|
    parseCompileUnits();
 | 
						|
 | 
						|
  DWARFCompileUnit *i = std::lower_bound(CUs.begin(), CUs.end(), offset,
 | 
						|
                                         OffsetComparator());
 | 
						|
  if (i != CUs.end())
 | 
						|
    return &*i;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t address) {
 | 
						|
  // First, get the offset of the compile unit.
 | 
						|
  uint32_t cuOffset = getDebugAranges()->findAddress(address);
 | 
						|
  // Retrieve the compile unit.
 | 
						|
  DWARFCompileUnit *cu = getCompileUnitForOffset(cuOffset);
 | 
						|
  if (!cu)
 | 
						|
    return DILineInfo("<invalid>", 0, 0);
 | 
						|
  // Get the line table for this compile unit.
 | 
						|
  const DWARFDebugLine::LineTable *lineTable = getLineTableForCompileUnit(cu);
 | 
						|
  if (!lineTable)
 | 
						|
    return DILineInfo("<invalid>", 0, 0);
 | 
						|
  // Get the index of the row we're looking for in the line table.
 | 
						|
  uint64_t hiPC =
 | 
						|
    cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_high_pc,
 | 
						|
                                                         -1ULL);
 | 
						|
  uint32_t rowIndex = lineTable->lookupAddress(address, hiPC);
 | 
						|
  if (rowIndex == -1U)
 | 
						|
    return DILineInfo("<invalid>", 0, 0);
 | 
						|
 | 
						|
  // From here, contruct the DILineInfo.
 | 
						|
  const DWARFDebugLine::Row &row = lineTable->Rows[rowIndex];
 | 
						|
  const std::string &fileName = lineTable->Prologue.FileNames[row.File-1].Name;
 | 
						|
 | 
						|
  return DILineInfo(fileName.c_str(), row.Line, row.Column);
 | 
						|
}
 | 
						|
 | 
						|
void DWARFContextInMemory::anchor() { }
 |