LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DWARFDebugAranges.cpp
Go to the documentation of this file.
1 //===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
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 "DWARFDebugAranges.h"
11 #include "DWARFCompileUnit.h"
12 #include "DWARFContext.h"
13 #include "llvm/Support/Format.h"
15 #include <algorithm>
16 #include <cassert>
17 using namespace llvm;
18 
19 void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
20  if (!DebugArangesData.isValidOffset(0))
21  return;
22  uint32_t Offset = 0;
23  typedef std::vector<DWARFDebugArangeSet> RangeSetColl;
24  RangeSetColl Sets;
26  uint32_t TotalRanges = 0;
27 
28  while (Set.extract(DebugArangesData, &Offset)) {
29  Sets.push_back(Set);
30  TotalRanges += Set.getNumDescriptors();
31  }
32  if (TotalRanges == 0)
33  return;
34 
35  Aranges.reserve(TotalRanges);
36  for (RangeSetColl::const_iterator I = Sets.begin(), E = Sets.end(); I != E;
37  ++I) {
38  uint32_t CUOffset = I->getCompileUnitDIEOffset();
39 
40  for (uint32_t i = 0, n = I->getNumDescriptors(); i < n; ++i) {
41  const DWARFDebugArangeSet::Descriptor *ArangeDescPtr =
42  I->getDescriptor(i);
43  uint64_t LowPC = ArangeDescPtr->Address;
44  uint64_t HighPC = LowPC + ArangeDescPtr->Length;
45  appendRange(CUOffset, LowPC, HighPC);
46  }
47  }
48 }
49 
51  clear();
52  if (!CTX)
53  return;
54 
55  // Extract aranges from .debug_aranges section.
56  DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
57  extract(ArangesData);
58 
59  // Generate aranges from DIEs: even if .debug_aranges section is present,
60  // it may describe only a small subset of compilation units, so we need to
61  // manually build aranges for the rest of them.
62  for (uint32_t i = 0, n = CTX->getNumCompileUnits(); i < n; ++i) {
63  if (DWARFCompileUnit *CU = CTX->getCompileUnitAtIndex(i)) {
64  uint32_t CUOffset = CU->getOffset();
65  if (ParsedCUOffsets.insert(CUOffset).second)
66  CU->buildAddressRangeTable(this, true, CUOffset);
67  }
68  }
69 
70  sortAndMinimize();
71 }
72 
73 void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
74  uint64_t HighPC) {
75  if (!Aranges.empty()) {
76  if (Aranges.back().CUOffset == CUOffset &&
77  Aranges.back().HighPC() == LowPC) {
78  Aranges.back().setHighPC(HighPC);
79  return;
80  }
81  }
82  Aranges.push_back(Range(LowPC, HighPC, CUOffset));
83 }
84 
85 void DWARFDebugAranges::sortAndMinimize() {
86  const size_t orig_arange_size = Aranges.size();
87  // Size of one? If so, no sorting is needed
88  if (orig_arange_size <= 1)
89  return;
90  // Sort our address range entries
91  std::stable_sort(Aranges.begin(), Aranges.end());
92 
93  // Most address ranges are contiguous from function to function
94  // so our new ranges will likely be smaller. We calculate the size
95  // of the new ranges since although std::vector objects can be resized,
96  // the will never reduce their allocated block size and free any excesss
97  // memory, so we might as well start a brand new collection so it is as
98  // small as possible.
99 
100  // First calculate the size of the new minimal arange vector
101  // so we don't have to do a bunch of re-allocations as we
102  // copy the new minimal stuff over to the new collection.
103  size_t minimal_size = 1;
104  for (size_t i = 1; i < orig_arange_size; ++i) {
105  if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i]))
106  ++minimal_size;
107  }
108 
109  // If the sizes are the same, then no consecutive aranges can be
110  // combined, we are done.
111  if (minimal_size == orig_arange_size)
112  return;
113 
114  // Else, make a new RangeColl that _only_ contains what we need.
115  RangeColl minimal_aranges;
116  minimal_aranges.resize(minimal_size);
117  uint32_t j = 0;
118  minimal_aranges[j] = Aranges[0];
119  for (size_t i = 1; i < orig_arange_size; ++i) {
120  if (Range::SortedOverlapCheck(minimal_aranges[j], Aranges[i])) {
121  minimal_aranges[j].setHighPC(Aranges[i].HighPC());
122  } else {
123  // Only increment j if we aren't merging
124  minimal_aranges[++j] = Aranges[i];
125  }
126  }
127  assert(j+1 == minimal_size);
128 
129  // Now swap our new minimal aranges into place. The local
130  // minimal_aranges will then contian the old big collection
131  // which will get freed.
132  minimal_aranges.swap(Aranges);
133 }
134 
135 uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
136  if (!Aranges.empty()) {
137  Range range(Address);
138  RangeCollIterator begin = Aranges.begin();
139  RangeCollIterator end = Aranges.end();
140  RangeCollIterator pos =
141  std::lower_bound(begin, end, range);
142 
143  if (pos != end && pos->containsAddress(Address)) {
144  return pos->CUOffset;
145  } else if (pos != begin) {
146  --pos;
147  if (pos->containsAddress(Address))
148  return pos->CUOffset;
149  }
150  }
151  return -1U;
152 }
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:181
const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:173
void generate(DWARFContext *CTX)
bool isValidOffset(uint32_t offset) const
unsigned getNumCompileUnits()
Get the number of compile units in this context.
Definition: DWARFContext.h:71
DWARFCompileUnit * getCompileUnitAtIndex(unsigned index)
Get the compile unit at the specified index for this compile unit.
Definition: DWARFContext.h:92
uint32_t getNumDescriptors() const
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:117
bool extract(DataExtractor data, uint32_t *offset_ptr)
void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC)
#define I(x, y, z)
Definition: MD5.cpp:54
virtual StringRef getARangeSection()=0
uint32_t findAddress(uint64_t Address) const
virtual bool isLittleEndian() const =0