LLVM  14.0.0git
DbiModuleList.cpp
Go to the documentation of this file.
1 //===- DbiModuleList.cpp - PDB module information list --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Error.h"
15 #include <algorithm>
16 #include <cassert>
17 #include <cstddef>
18 #include <cstdint>
19 
20 using namespace llvm;
21 using namespace llvm::pdb;
22 
24  const DbiModuleList &Modules, uint32_t Modi, uint16_t Filei)
25  : Modules(&Modules), Modi(Modi), Filei(Filei) {
26  setValue();
27 }
28 
31  // incompatible iterators are never equal
32  if (!isCompatible(R))
33  return false;
34 
35  // If they're compatible, and they're both ends, then they're equal.
36  if (isEnd() && R.isEnd())
37  return true;
38 
39  // If one is an end and the other is not, they're not equal.
40  if (isEnd() != R.isEnd())
41  return false;
42 
43  // Now we know:
44  // - They're compatible
45  // - They're not *both* end iterators
46  // - Their endness is the same.
47  // Thus, they're compatible iterators pointing to a valid file on the same
48  // module. All we need to check are the file indices.
49  assert(Modules == R.Modules);
50  assert(Modi == R.Modi);
51  assert(!isEnd());
52  assert(!R.isEnd());
53 
54  return (Filei == R.Filei);
55 }
56 
59  assert(isCompatible(R));
60 
61  // It's not sufficient to compare the file indices, because default
62  // constructed iterators could be equal to iterators with valid indices. To
63  // account for this, early-out if they're equal.
64  if (*this == R)
65  return false;
66 
67  return Filei < R.Filei;
68 }
69 
70 std::ptrdiff_t DbiModuleSourceFilesIterator::
72  assert(isCompatible(R));
73  assert(!(*this < R));
74 
75  // If they're both end iterators, the distance is 0.
76  if (isEnd() && R.isEnd())
77  return 0;
78 
79  assert(!R.isEnd());
80 
81  // At this point, R cannot be end, but *this can, which means that *this
82  // might be a universal end iterator with none of its fields set. So in that
83  // case have to rely on R as the authority to figure out how many files there
84  // are to compute the distance.
85  uint32_t Thisi = Filei;
86  if (isEnd()) {
87  uint32_t RealModi = R.Modi;
88  Thisi = R.Modules->getSourceFileCount(RealModi);
89  }
90 
91  assert(Thisi >= R.Filei);
92  return Thisi - R.Filei;
93 }
94 
96 operator+=(std::ptrdiff_t N) {
97  assert(!isEnd());
98 
99  Filei += N;
100  assert(Filei <= Modules->getSourceFileCount(Modi));
101  setValue();
102  return *this;
103 }
104 
106 operator-=(std::ptrdiff_t N) {
107  // Note that we can subtract from an end iterator, but not a universal end
108  // iterator.
109  assert(!isUniversalEnd());
110 
111  assert(N <= Filei);
112 
113  Filei -= N;
114  return *this;
115 }
116 
117 void DbiModuleSourceFilesIterator::setValue() {
118  if (isEnd()) {
119  ThisValue = "";
120  return;
121  }
122 
123  uint32_t Off = Modules->ModuleInitialFileIndex[Modi] + Filei;
124  auto ExpectedValue = Modules->getFileName(Off);
125  if (!ExpectedValue) {
126  consumeError(ExpectedValue.takeError());
127  Filei = Modules->getSourceFileCount(Modi);
128  } else
129  ThisValue = *ExpectedValue;
130 }
131 
132 bool DbiModuleSourceFilesIterator::isEnd() const {
133  if (isUniversalEnd())
134  return true;
135 
136  assert(Modules);
137  assert(Modi <= Modules->getModuleCount());
138  assert(Filei <= Modules->getSourceFileCount(Modi));
139 
140  if (Modi == Modules->getModuleCount())
141  return true;
142  if (Filei == Modules->getSourceFileCount(Modi))
143  return true;
144  return false;
145 }
146 
147 bool DbiModuleSourceFilesIterator::isUniversalEnd() const { return !Modules; }
148 
149 bool DbiModuleSourceFilesIterator::isCompatible(
150  const DbiModuleSourceFilesIterator &R) const {
151  // Universal iterators are compatible with any other iterator.
152  if (isUniversalEnd() || R.isUniversalEnd())
153  return true;
154 
155  // At this point, neither iterator is a universal end iterator, although one
156  // or both might be non-universal end iterators. Regardless, the module index
157  // is valid, so they are compatible if and only if they refer to the same
158  // module.
159  return Modi == R.Modi;
160 }
161 
163  BinaryStreamRef FileInfo) {
164  if (auto EC = initializeModInfo(ModInfo))
165  return EC;
166  if (auto EC = initializeFileInfo(FileInfo))
167  return EC;
168 
169  return Error::success();
170 }
171 
172 Error DbiModuleList::initializeModInfo(BinaryStreamRef ModInfo) {
173  ModInfoSubstream = ModInfo;
174 
175  if (ModInfo.getLength() == 0)
176  return Error::success();
177 
178  BinaryStreamReader Reader(ModInfo);
179 
180  if (auto EC = Reader.readArray(Descriptors, ModInfo.getLength()))
181  return EC;
182 
183  return Error::success();
184 }
185 
186 Error DbiModuleList::initializeFileInfo(BinaryStreamRef FileInfo) {
187  FileInfoSubstream = FileInfo;
188 
189  if (FileInfo.getLength() == 0)
190  return Error::success();
191 
192  BinaryStreamReader FISR(FileInfo);
193  if (auto EC = FISR.readObject(FileInfoHeader))
194  return EC;
195 
196  // First is an array of `NumModules` module indices. This does not seem to be
197  // used for anything meaningful, so we ignore it.
199  if (auto EC = FISR.readArray(ModuleIndices, FileInfoHeader->NumModules))
200  return EC;
201  if (auto EC = FISR.readArray(ModFileCountArray, FileInfoHeader->NumModules))
202  return EC;
203 
204  // Compute the real number of source files. We can't trust the value in
205  // `FileInfoHeader->NumSourceFiles` because it is a unit16, and the sum of all
206  // source file counts might be larger than a unit16. So we compute the real
207  // count by summing up the individual counts.
208  uint32_t NumSourceFiles = 0;
209  for (auto Count : ModFileCountArray)
210  NumSourceFiles += Count;
211 
212  // In the reference implementation, this array is where the pointer documented
213  // at the definition of ModuleInfoHeader::FileNameOffs points to. Note that
214  // although the field in ModuleInfoHeader is ignored this array is not, as it
215  // is the authority on where each filename begins in the names buffer.
216  if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
217  return EC;
218 
219  if (auto EC = FISR.readStreamRef(NamesBuffer))
220  return EC;
221 
222  auto DescriptorIter = Descriptors.begin();
223  uint32_t NextFileIndex = 0;
224  ModuleInitialFileIndex.resize(FileInfoHeader->NumModules);
225  ModuleDescriptorOffsets.resize(FileInfoHeader->NumModules);
226  for (size_t I = 0; I < FileInfoHeader->NumModules; ++I) {
227  assert(DescriptorIter != Descriptors.end());
228  ModuleInitialFileIndex[I] = NextFileIndex;
229  ModuleDescriptorOffsets[I] = DescriptorIter.offset();
230 
231  NextFileIndex += ModFileCountArray[I];
232  ++DescriptorIter;
233  }
234 
235  assert(DescriptorIter == Descriptors.end());
236  assert(NextFileIndex == NumSourceFiles);
237 
238  return Error::success();
239 }
240 
242  return FileInfoHeader->NumModules;
243 }
244 
246  return FileNameOffsets.size();
247 }
248 
250  return ModFileCountArray[Modi];
251 }
252 
254  assert(Modi < getModuleCount());
255  uint32_t Offset = ModuleDescriptorOffsets[Modi];
256  auto Iter = Descriptors.at(Offset);
257  assert(Iter != Descriptors.end());
258  return *Iter;
259 }
260 
263  return make_range<DbiModuleSourceFilesIterator>(
264  DbiModuleSourceFilesIterator(*this, Modi, 0),
266 }
267 
269  BinaryStreamReader Names(NamesBuffer);
270  if (Index >= getSourceFileCount())
271  return make_error<RawError>(raw_error_code::index_out_of_bounds);
272 
273  uint32_t FileOffset = FileNameOffsets[Index];
274  Names.setOffset(FileOffset);
275  StringRef Name;
276  if (auto EC = Names.readCString(Name))
277  return std::move(EC);
278  return Name;
279 }
llvm::pdb::DbiModuleList::getModuleCount
uint32_t getModuleCount() const
Definition: DbiModuleList.cpp:241
BinaryStreamReader.h
llvm::BinaryStreamReader::setOffset
void setOffset(uint64_t Off)
Definition: BinaryStreamReader.h:254
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::pdb::DbiModuleList::initialize
Error initialize(BinaryStreamRef ModInfo, BinaryStreamRef FileInfo)
Definition: DbiModuleList.cpp:162
StringRef.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::pdb::raw_error_code::index_out_of_bounds
@ index_out_of_bounds
Error.h
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
RawError.h
llvm::FixedStreamArray
FixedStreamArray is similar to VarStreamArray, except with each record having a fixed-length.
Definition: BinaryStreamArray.h:262
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1035
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:193
llvm::pdb::DbiModuleList
Definition: DbiModuleList.h:69
llvm::pdb::FileInfoSubstreamHeader::NumModules
support::ulittle16_t NumModules
Total # of modules, should match number of records in the ModuleInfo substream.
Definition: RawTypes.h:183
llvm::BinaryStreamRefBase::getLength
uint64_t getLength() const
Definition: BinaryStreamRef.h:51
llvm::pdb::DbiModuleList::getSourceFileCount
uint32_t getSourceFileCount() const
Definition: DbiModuleList.cpp:245
llvm::pdb
Definition: ConcreteSymbolEnumerator.h:20
llvm::BinaryStreamReader
Provides read only access to a subclass of BinaryStream.
Definition: BinaryStreamReader.h:31
llvm::pdb::DbiModuleSourceFilesIterator::operator-
std::ptrdiff_t operator-(const DbiModuleSourceFilesIterator &R) const
Definition: DbiModuleList.cpp:71
llvm::pdb::DbiModuleSourceFilesIterator::DbiModuleSourceFilesIterator
DbiModuleSourceFilesIterator()=default
Index
uint32_t Index
Definition: ELFObjHandler.cpp:84
llvm::BinaryStreamReader::readCString
Error readCString(StringRef &Dest)
Read a null terminated string from Dest.
Definition: BinaryStreamReader.cpp:74
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
I
#define I(x, y, z)
Definition: MD5.cpp:59
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
iterator_range.h
llvm::pdb::DbiModuleSourceFilesIterator::operator==
bool operator==(const DbiModuleSourceFilesIterator &R) const
Definition: DbiModuleList.cpp:30
llvm::pdb::DbiModuleSourceFilesIterator::operator+=
DbiModuleSourceFilesIterator & operator+=(std::ptrdiff_t N)
Definition: DbiModuleList.cpp:96
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
llvm::pdb::DbiModuleList::getFileName
Expected< StringRef > getFileName(uint32_t Index) const
Definition: DbiModuleList.cpp:268
llvm::pdb::DbiModuleSourceFilesIterator::operator-=
DbiModuleSourceFilesIterator & operator-=(std::ptrdiff_t N)
Definition: DbiModuleList.cpp:106
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
uint16_t
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
N
#define N
llvm::pdb::DbiModuleSourceFilesIterator
Definition: DbiModuleList.h:31
llvm::pdb::DbiModuleList::getModuleDescriptor
DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const
Definition: DbiModuleList.cpp:253
llvm::pdb::DbiModuleSourceFilesIterator::operator<
bool operator<(const DbiModuleSourceFilesIterator &RHS) const
Definition: DbiModuleList.cpp:58
llvm::iterator_range
A range adaptor for a pair of iterators.
Definition: iterator_range.h:30
DbiModuleList.h
llvm::pdb::DbiModuleDescriptor
Definition: DbiModuleDescriptor.h:23
llvm::pdb::DbiModuleList::source_files
iterator_range< DbiModuleSourceFilesIterator > source_files(uint32_t Modi) const
Definition: DbiModuleList.cpp:262
llvm::BinaryStreamRef
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.
Definition: BinaryStreamRef.h:156