llvm-6502/lib/DebugInfo/DWARFDebugAranges.cpp
Frederic Riss 7e5492d27d [DebugInfo] Move all DWARF headers to the public include directory.
dsymutil needs access to DWARF specific inforamtion, the small DIContext
wrapper isn't sufficient. Other DWARF consumers might want to use it too
(I'm looking at you lldb).

Differential Revision: http://reviews.llvm.org/D6694

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224594 91177308-0d34-0410-b5e6-96231b3b80d8
2014-12-19 18:26:33 +00:00

130 lines
4.0 KiB
C++

//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARFDebugAranges.h"
#include "llvm/DebugInfo/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARFContext.h"
#include "llvm/DebugInfo/DWARFDebugArangeSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <set>
using namespace llvm;
void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
if (!DebugArangesData.isValidOffset(0))
return;
uint32_t Offset = 0;
DWARFDebugArangeSet Set;
while (Set.extract(DebugArangesData, &Offset)) {
uint32_t CUOffset = Set.getCompileUnitDIEOffset();
for (const auto &Desc : Set.descriptors()) {
uint64_t LowPC = Desc.Address;
uint64_t HighPC = Desc.getEndAddress();
appendRange(CUOffset, LowPC, HighPC);
}
ParsedCUOffsets.insert(CUOffset);
}
}
void DWARFDebugAranges::generate(DWARFContext *CTX) {
clear();
if (!CTX)
return;
// Extract aranges from .debug_aranges section.
DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
extract(ArangesData);
// Generate aranges from DIEs: even if .debug_aranges section is present,
// it may describe only a small subset of compilation units, so we need to
// manually build aranges for the rest of them.
for (const auto &CU : CTX->compile_units()) {
uint32_t CUOffset = CU->getOffset();
if (ParsedCUOffsets.insert(CUOffset).second) {
DWARFAddressRangesVector CURanges;
CU->collectAddressRanges(CURanges);
for (const auto &R : CURanges) {
appendRange(CUOffset, R.first, R.second);
}
}
}
construct();
}
void DWARFDebugAranges::clear() {
Endpoints.clear();
Aranges.clear();
ParsedCUOffsets.clear();
}
void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
uint64_t HighPC) {
if (LowPC >= HighPC)
return;
Endpoints.emplace_back(LowPC, CUOffset, true);
Endpoints.emplace_back(HighPC, CUOffset, false);
}
void DWARFDebugAranges::construct() {
std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing
// a current address range.
std::sort(Endpoints.begin(), Endpoints.end());
uint64_t PrevAddress = -1ULL;
for (const auto &E : Endpoints) {
if (PrevAddress < E.Address && ValidCUs.size() > 0) {
// If the address range between two endpoints is described by some
// CU, first try to extend the last range in Aranges. If we can't
// do it, start a new range.
if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
Aranges.back().setHighPC(E.Address);
} else {
Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
}
}
// Update the set of valid CUs.
if (E.IsRangeStart) {
ValidCUs.insert(E.CUOffset);
} else {
auto CUPos = ValidCUs.find(E.CUOffset);
assert(CUPos != ValidCUs.end());
ValidCUs.erase(CUPos);
}
PrevAddress = E.Address;
}
assert(ValidCUs.empty());
// Endpoints are not needed now.
std::vector<RangeEndpoint> EmptyEndpoints;
EmptyEndpoints.swap(Endpoints);
}
uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
if (!Aranges.empty()) {
Range range(Address);
RangeCollIterator begin = Aranges.begin();
RangeCollIterator end = Aranges.end();
RangeCollIterator pos =
std::lower_bound(begin, end, range);
if (pos != end && pos->containsAddress(Address)) {
return pos->CUOffset;
} else if (pos != begin) {
--pos;
if (pos->containsAddress(Address))
return pos->CUOffset;
}
}
return -1U;
}