blob: 6aa40b3d27ae12a3dc7d8c958e207c40649749ac [file] [log] [blame]
Benjamin Kramer358f4fd2011-09-14 01:09:52 +00001//===-- 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"
14#include "llvm/Support/raw_ostream.h"
15#include <algorithm>
16#include <cassert>
17using namespace llvm;
18
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000019namespace {
20 class CountArangeDescriptors {
21 public:
22 CountArangeDescriptors(uint32_t &count_ref) : Count(count_ref) {}
Alexey Samsonov63a450a2012-11-16 08:36:25 +000023 void operator()(const DWARFDebugArangeSet &Set) {
24 Count += Set.getNumDescriptors();
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000025 }
26 uint32_t &Count;
27 };
28
29 class AddArangeDescriptors {
30 public:
Alexey Samsonov63a450a2012-11-16 08:36:25 +000031 AddArangeDescriptors(DWARFDebugAranges::RangeColl &Ranges,
32 DWARFDebugAranges::ParsedCUOffsetColl &CUOffsets)
33 : RangeCollection(Ranges),
34 CUOffsetCollection(CUOffsets) {}
35 void operator()(const DWARFDebugArangeSet &Set) {
36 DWARFDebugAranges::Range Range;
Alexey Samsonov17f7d092013-10-01 16:25:14 +000037 Range.CUOffset = Set.getCompileUnitDIEOffset();
38 CUOffsetCollection.insert(Range.CUOffset);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000039
Alexey Samsonov63a450a2012-11-16 08:36:25 +000040 for (uint32_t i = 0, n = Set.getNumDescriptors(); i < n; ++i) {
41 const DWARFDebugArangeSet::Descriptor *ArangeDescPtr =
42 Set.getDescriptor(i);
Alexey Samsonov17f7d092013-10-01 16:25:14 +000043 Range.LowPC = ArangeDescPtr->Address;
Alexey Samsonov63a450a2012-11-16 08:36:25 +000044 Range.Length = ArangeDescPtr->Length;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000045
46 // Insert each item in increasing address order so binary searching
47 // can later be done!
Alexey Samsonov63a450a2012-11-16 08:36:25 +000048 DWARFDebugAranges::RangeColl::iterator InsertPos =
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000049 std::lower_bound(RangeCollection.begin(), RangeCollection.end(),
Alexey Samsonov17f7d092013-10-01 16:25:14 +000050 Range);
Alexey Samsonov63a450a2012-11-16 08:36:25 +000051 RangeCollection.insert(InsertPos, Range);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000052 }
Alexey Samsonov63a450a2012-11-16 08:36:25 +000053
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000054 }
Alexey Samsonov63a450a2012-11-16 08:36:25 +000055 DWARFDebugAranges::RangeColl &RangeCollection;
56 DWARFDebugAranges::ParsedCUOffsetColl &CUOffsetCollection;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000057 };
58}
59
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000060void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
61 if (!DebugArangesData.isValidOffset(0))
62 return;
63 uint32_t offset = 0;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000064
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000065 typedef std::vector<DWARFDebugArangeSet> SetCollection;
66 SetCollection sets;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000067
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000068 DWARFDebugArangeSet set;
69 Range range;
70 while (set.extract(DebugArangesData, &offset))
71 sets.push_back(set);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000072
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000073 uint32_t count = 0;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000074
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000075 std::for_each(sets.begin(), sets.end(), CountArangeDescriptors(count));
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000076
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000077 if (count > 0) {
78 Aranges.reserve(count);
79 AddArangeDescriptors range_adder(Aranges, ParsedCUOffsets);
80 std::for_each(sets.begin(), sets.end(), range_adder);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000081 }
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000082}
83
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000084void DWARFDebugAranges::generate(DWARFContext *CTX) {
85 if (CTX) {
86 const uint32_t num_compile_units = CTX->getNumCompileUnits();
Benjamin Kramer10df8062011-09-14 20:52:27 +000087 for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000088 if (DWARFCompileUnit *cu = CTX->getCompileUnitAtIndex(cu_idx)) {
Alexey Samsonov63a450a2012-11-16 08:36:25 +000089 uint32_t CUOffset = cu->getOffset();
90 if (ParsedCUOffsets.insert(CUOffset).second)
Alexey Samsonov63fd2af2013-08-27 09:20:22 +000091 cu->buildAddressRangeTable(this, true, CUOffset);
Alexey Samsonov63a450a2012-11-16 08:36:25 +000092 }
Benjamin Kramer10df8062011-09-14 20:52:27 +000093 }
94 }
Alexey Samsonov17f7d092013-10-01 16:25:14 +000095 sortAndMinimize();
Benjamin Kramer10df8062011-09-14 20:52:27 +000096}
97
Benjamin Kramer358f4fd2011-09-14 01:09:52 +000098void DWARFDebugAranges::dump(raw_ostream &OS) const {
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +000099 for (RangeCollIterator I = Aranges.begin(), E = Aranges.end(); I != E; ++I) {
100 I->dump(OS);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000101 }
102}
103
104void DWARFDebugAranges::Range::dump(raw_ostream &OS) const {
Benjamin Kramer41a96492011-11-05 08:57:40 +0000105 OS << format("{0x%8.8x}: [0x%8.8" PRIx64 " - 0x%8.8" PRIx64 ")\n",
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000106 CUOffset, LowPC, HighPC());
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000107}
108
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +0000109void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
110 uint64_t HighPC) {
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000111 if (!Aranges.empty()) {
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000112 if (Aranges.back().CUOffset == CUOffset &&
113 Aranges.back().HighPC() == LowPC) {
114 Aranges.back().setHighPC(HighPC);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000115 return;
116 }
117 }
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +0000118 Aranges.push_back(Range(LowPC, HighPC, CUOffset));
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000119}
120
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000121void DWARFDebugAranges::sortAndMinimize() {
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000122 const size_t orig_arange_size = Aranges.size();
123 // Size of one? If so, no sorting is needed
124 if (orig_arange_size <= 1)
125 return;
126 // Sort our address range entries
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000127 std::stable_sort(Aranges.begin(), Aranges.end());
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000128
129 // Most address ranges are contiguous from function to function
130 // so our new ranges will likely be smaller. We calculate the size
131 // of the new ranges since although std::vector objects can be resized,
132 // the will never reduce their allocated block size and free any excesss
133 // memory, so we might as well start a brand new collection so it is as
134 // small as possible.
135
136 // First calculate the size of the new minimal arange vector
137 // so we don't have to do a bunch of re-allocations as we
138 // copy the new minimal stuff over to the new collection.
139 size_t minimal_size = 1;
140 for (size_t i = 1; i < orig_arange_size; ++i) {
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000141 if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i]))
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000142 ++minimal_size;
143 }
144
145 // If the sizes are the same, then no consecutive aranges can be
146 // combined, we are done.
147 if (minimal_size == orig_arange_size)
148 return;
149
150 // Else, make a new RangeColl that _only_ contains what we need.
151 RangeColl minimal_aranges;
152 minimal_aranges.resize(minimal_size);
153 uint32_t j = 0;
154 minimal_aranges[j] = Aranges[0];
155 for (size_t i = 1; i < orig_arange_size; ++i) {
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000156 if (Range::SortedOverlapCheck(minimal_aranges[j], Aranges[i])) {
157 minimal_aranges[j].setHighPC(Aranges[i].HighPC());
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000158 } else {
159 // Only increment j if we aren't merging
160 minimal_aranges[++j] = Aranges[i];
161 }
162 }
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000163 assert(j+1 == minimal_size);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000164
165 // Now swap our new minimal aranges into place. The local
166 // minimal_aranges will then contian the old big collection
167 // which will get freed.
168 minimal_aranges.swap(Aranges);
169}
170
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +0000171uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000172 if (!Aranges.empty()) {
Alexey Samsonovd1fc0f82013-10-01 15:48:10 +0000173 Range range(Address);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000174 RangeCollIterator begin = Aranges.begin();
175 RangeCollIterator end = Aranges.end();
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000176 RangeCollIterator pos =
177 std::lower_bound(begin, end, range);
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000178
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000179 if (pos != end && pos->containsAddress(Address)) {
180 return pos->CUOffset;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000181 } else if (pos != begin) {
182 --pos;
Alexey Samsonov17f7d092013-10-01 16:25:14 +0000183 if (pos->containsAddress(Address))
184 return pos->CUOffset;
Benjamin Kramer358f4fd2011-09-14 01:09:52 +0000185 }
186 }
187 return -1U;
188}