Bug Summary

File:tools/llvm-pdbutil/InputFile.cpp
Warning:line 81, column 13
The left operand of '!=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name InputFile.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/llvm-pdbutil -I /build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil -I /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn329677/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn329677/build-llvm/tools/llvm-pdbutil -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-04-11-031539-24776-1 -x c++ /build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp

/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp

1//===- InputFile.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 "InputFile.h"
11
12#include "FormatUtil.h"
13#include "LinePrinter.h"
14
15#include "llvm/BinaryFormat/Magic.h"
16#include "llvm/DebugInfo/CodeView/CodeView.h"
17#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
18#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
19#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
20#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
21#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
22#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
23#include "llvm/DebugInfo/PDB/Native/RawError.h"
24#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
25#include "llvm/DebugInfo/PDB/PDB.h"
26#include "llvm/Object/COFF.h"
27#include "llvm/Support/FileSystem.h"
28#include "llvm/Support/FormatVariadic.h"
29
30using namespace llvm;
31using namespace llvm::codeview;
32using namespace llvm::object;
33using namespace llvm::pdb;
34
35InputFile::InputFile() {}
36InputFile::~InputFile() {}
37
38static Expected<ModuleDebugStreamRef>
39getModuleDebugStream(PDBFile &File, StringRef &ModuleName, uint32_t Index) {
40 ExitOnError Err("Unexpected error: ");
41
42 auto &Dbi = Err(File.getPDBDbiStream());
43 const auto &Modules = Dbi.modules();
44 auto Modi = Modules.getModuleDescriptor(Index);
45
46 ModuleName = Modi.getModuleName();
47
48 uint16_t ModiStream = Modi.getModuleStreamIndex();
49 if (ModiStream == kInvalidStreamIndex)
50 return make_error<RawError>(raw_error_code::no_stream,
51 "Module stream not present");
52
53 auto ModStreamData = File.createIndexedStream(ModiStream);
54
55 ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
56 if (auto EC = ModS.reload())
57 return make_error<RawError>(raw_error_code::corrupt_file,
58 "Invalid module stream");
59
60 return std::move(ModS);
61}
62
63static inline bool isCodeViewDebugSubsection(object::SectionRef Section,
64 StringRef Name,
65 BinaryStreamReader &Reader) {
66 StringRef SectionName, Contents;
67 if (Section.getName(SectionName))
4
Taking false branch
68 return false;
69
70 if (SectionName != Name)
5
Taking false branch
71 return false;
72
73 if (Section.getContents(Contents))
6
Taking false branch
74 return false;
75
76 Reader = BinaryStreamReader(Contents, support::little);
77 uint32_t Magic;
7
'Magic' declared without an initial value
78 if (Reader.bytesRemaining() < sizeof(uint32_t))
8
Taking false branch
79 return false;
80 cantFail(Reader.readInteger(Magic));
9
Calling 'BinaryStreamReader::readInteger'
12
Returning from 'BinaryStreamReader::readInteger'
81 if (Magic != COFF::DEBUG_SECTION_MAGIC)
13
The left operand of '!=' is a garbage value
82 return false;
83 return true;
84}
85
86static inline bool isDebugSSection(object::SectionRef Section,
87 DebugSubsectionArray &Subsections) {
88 BinaryStreamReader Reader;
89 if (!isCodeViewDebugSubsection(Section, ".debug$S", Reader))
90 return false;
91
92 cantFail(Reader.readArray(Subsections, Reader.bytesRemaining()));
93 return true;
94}
95
96static bool isDebugTSection(SectionRef Section, CVTypeArray &Types) {
97 BinaryStreamReader Reader;
98 if (!isCodeViewDebugSubsection(Section, ".debug$T", Reader) &&
3
Calling 'isCodeViewDebugSubsection'
99 !isCodeViewDebugSubsection(Section, ".debug$P", Reader))
100 return false;
101 cantFail(Reader.readArray(Types, Reader.bytesRemaining()));
102 return true;
103}
104
105static std::string formatChecksumKind(FileChecksumKind Kind) {
106 switch (Kind) {
107 RETURN_CASE(FileChecksumKind, None, "None")case FileChecksumKind::None: return "None";;
108 RETURN_CASE(FileChecksumKind, MD5, "MD5")case FileChecksumKind::MD5: return "MD5";;
109 RETURN_CASE(FileChecksumKind, SHA1, "SHA-1")case FileChecksumKind::SHA1: return "SHA-1";;
110 RETURN_CASE(FileChecksumKind, SHA256, "SHA-256")case FileChecksumKind::SHA256: return "SHA-256";;
111 }
112 return formatUnknownEnum(Kind);
113}
114
115static const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
116 return cantFail(File.getStringTable()).getStringTable();
117}
118
119template <typename... Args>
120static void formatInternal(LinePrinter &Printer, bool Append, Args &&... args) {
121 if (Append)
122 Printer.format(std::forward<Args>(args)...);
123 else
124 Printer.formatLine(std::forward<Args>(args)...);
125}
126
127SymbolGroup::SymbolGroup(InputFile *File, uint32_t GroupIndex) : File(File) {
128 if (!File)
129 return;
130
131 if (File->isPdb())
132 initializeForPdb(GroupIndex);
133 else {
134 Name = ".debug$S";
135 uint32_t I = 0;
136 for (const auto &S : File->obj().sections()) {
137 DebugSubsectionArray SS;
138 if (!isDebugSSection(S, SS))
139 continue;
140
141 if (!SC.hasChecksums() || !SC.hasStrings())
142 SC.initialize(SS);
143
144 if (I == GroupIndex)
145 Subsections = SS;
146
147 if (SC.hasChecksums() && SC.hasStrings())
148 break;
149 }
150 rebuildChecksumMap();
151 }
152}
153
154StringRef SymbolGroup::name() const { return Name; }
155
156void SymbolGroup::updateDebugS(const codeview::DebugSubsectionArray &SS) {
157 Subsections = SS;
158}
159
160void SymbolGroup::updatePdbModi(uint32_t Modi) { initializeForPdb(Modi); }
161
162void SymbolGroup::initializeForPdb(uint32_t Modi) {
163 assert(File && File->isPdb())(static_cast <bool> (File && File->isPdb()) ?
void (0) : __assert_fail ("File && File->isPdb()"
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 163, __extension__ __PRETTY_FUNCTION__))
;
164
165 // PDB always uses the same string table, but each module has its own
166 // checksums. So we only set the strings if they're not already set.
167 if (!SC.hasStrings())
168 SC.setStrings(extractStringTable(File->pdb()));
169
170 SC.resetChecksums();
171 auto MDS = getModuleDebugStream(File->pdb(), Name, Modi);
172 if (!MDS) {
173 consumeError(MDS.takeError());
174 return;
175 }
176
177 DebugStream = std::make_shared<ModuleDebugStreamRef>(std::move(*MDS));
178 Subsections = DebugStream->getSubsectionsArray();
179 SC.initialize(Subsections);
180 rebuildChecksumMap();
181}
182
183void SymbolGroup::rebuildChecksumMap() {
184 if (!SC.hasChecksums())
185 return;
186
187 for (const auto &Entry : SC.checksums()) {
188 auto S = SC.strings().getString(Entry.FileNameOffset);
189 if (!S)
190 continue;
191 ChecksumsByFile[*S] = Entry;
192 }
193}
194
195const ModuleDebugStreamRef &SymbolGroup::getPdbModuleStream() const {
196 assert(File && File->isPdb() && DebugStream)(static_cast <bool> (File && File->isPdb() &&
DebugStream) ? void (0) : __assert_fail ("File && File->isPdb() && DebugStream"
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 196, __extension__ __PRETTY_FUNCTION__))
;
197 return *DebugStream;
198}
199
200Expected<StringRef> SymbolGroup::getNameFromStringTable(uint32_t Offset) const {
201 return SC.strings().getString(Offset);
202}
203
204void SymbolGroup::formatFromFileName(LinePrinter &Printer, StringRef File,
205 bool Append) const {
206 auto FC = ChecksumsByFile.find(File);
207 if (FC == ChecksumsByFile.end()) {
208 formatInternal(Printer, Append, "- (no checksum) {0}", File);
209 return;
210 }
211
212 formatInternal(Printer, Append, "- ({0}: {1}) {2}",
213 formatChecksumKind(FC->getValue().Kind),
214 toHex(FC->getValue().Checksum), File);
215}
216
217void SymbolGroup::formatFromChecksumsOffset(LinePrinter &Printer,
218 uint32_t Offset,
219 bool Append) const {
220 if (!SC.hasChecksums()) {
221 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
222 return;
223 }
224
225 auto Iter = SC.checksums().getArray().at(Offset);
226 if (Iter == SC.checksums().getArray().end()) {
227 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
228 return;
229 }
230
231 uint32_t FO = Iter->FileNameOffset;
232 auto ExpectedFile = getNameFromStringTable(FO);
233 if (!ExpectedFile) {
234 formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
235 consumeError(ExpectedFile.takeError());
236 return;
237 }
238 if (Iter->Kind == FileChecksumKind::None) {
239 formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
240 } else {
241 formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
242 formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
243 }
244}
245
246Expected<InputFile> InputFile::open(StringRef Path, bool AllowUnknownFile) {
247 InputFile IF;
248 if (!llvm::sys::fs::exists(Path))
249 return make_error<StringError>(formatv("File {0} not found", Path),
250 inconvertibleErrorCode());
251
252 file_magic Magic;
253 if (auto EC = identify_magic(Path, Magic))
254 return make_error<StringError>(
255 formatv("Unable to identify file type for file {0}", Path), EC);
256
257 if (Magic == file_magic::coff_object) {
258 Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Path);
259 if (!BinaryOrErr)
260 return BinaryOrErr.takeError();
261
262 IF.CoffObject = std::move(*BinaryOrErr);
263 IF.PdbOrObj = llvm::cast<COFFObjectFile>(IF.CoffObject.getBinary());
264 return std::move(IF);
265 }
266
267 if (Magic == file_magic::pdb) {
268 std::unique_ptr<IPDBSession> Session;
269 if (auto Err = loadDataForPDB(PDB_ReaderType::Native, Path, Session))
270 return std::move(Err);
271
272 IF.PdbSession.reset(static_cast<NativeSession *>(Session.release()));
273 IF.PdbOrObj = &IF.PdbSession->getPDBFile();
274
275 return std::move(IF);
276 }
277
278 if (!AllowUnknownFile)
279 return make_error<StringError>(
280 formatv("File {0} is not a supported file type", Path),
281 inconvertibleErrorCode());
282
283 auto Result = MemoryBuffer::getFile(Path, -1LL, false);
284 if (!Result)
285 return make_error<StringError>(
286 formatv("File {0} could not be opened", Path), Result.getError());
287
288 IF.UnknownFile = std::move(*Result);
289 IF.PdbOrObj = IF.UnknownFile.get();
290 return std::move(IF);
291}
292
293PDBFile &InputFile::pdb() {
294 assert(isPdb())(static_cast <bool> (isPdb()) ? void (0) : __assert_fail
("isPdb()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 294, __extension__ __PRETTY_FUNCTION__))
;
295 return *PdbOrObj.get<PDBFile *>();
296}
297
298const PDBFile &InputFile::pdb() const {
299 assert(isPdb())(static_cast <bool> (isPdb()) ? void (0) : __assert_fail
("isPdb()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 299, __extension__ __PRETTY_FUNCTION__))
;
300 return *PdbOrObj.get<PDBFile *>();
301}
302
303object::COFFObjectFile &InputFile::obj() {
304 assert(isObj())(static_cast <bool> (isObj()) ? void (0) : __assert_fail
("isObj()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 304, __extension__ __PRETTY_FUNCTION__))
;
305 return *PdbOrObj.get<object::COFFObjectFile *>();
306}
307
308const object::COFFObjectFile &InputFile::obj() const {
309 assert(isObj())(static_cast <bool> (isObj()) ? void (0) : __assert_fail
("isObj()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 309, __extension__ __PRETTY_FUNCTION__))
;
310 return *PdbOrObj.get<object::COFFObjectFile *>();
311}
312
313MemoryBuffer &InputFile::unknown() {
314 assert(isUnknown())(static_cast <bool> (isUnknown()) ? void (0) : __assert_fail
("isUnknown()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 314, __extension__ __PRETTY_FUNCTION__))
;
315 return *PdbOrObj.get<MemoryBuffer *>();
316}
317
318const MemoryBuffer &InputFile::unknown() const {
319 assert(isUnknown())(static_cast <bool> (isUnknown()) ? void (0) : __assert_fail
("isUnknown()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 319, __extension__ __PRETTY_FUNCTION__))
;
320 return *PdbOrObj.get<MemoryBuffer *>();
321}
322
323StringRef InputFile::getFilePath() const {
324 if (isPdb())
325 return pdb().getFilePath();
326 if (isObj())
327 return obj().getFileName();
328 assert(isUnknown())(static_cast <bool> (isUnknown()) ? void (0) : __assert_fail
("isUnknown()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 328, __extension__ __PRETTY_FUNCTION__))
;
329 return unknown().getBufferIdentifier();
330}
331
332bool InputFile::hasTypes() const {
333 if (isPdb())
1
Taking false branch
334 return pdb().hasPDBTpiStream();
335
336 for (const auto &Section : obj().sections()) {
337 CVTypeArray Types;
338 if (isDebugTSection(Section, Types))
2
Calling 'isDebugTSection'
339 return true;
340 }
341 return false;
342}
343
344bool InputFile::hasIds() const {
345 if (isObj())
346 return false;
347 return pdb().hasPDBIpiStream();
348}
349
350bool InputFile::isPdb() const { return PdbOrObj.is<PDBFile *>(); }
351
352bool InputFile::isObj() const {
353 return PdbOrObj.is<object::COFFObjectFile *>();
354}
355
356bool InputFile::isUnknown() const { return PdbOrObj.is<MemoryBuffer *>(); }
357
358codeview::LazyRandomTypeCollection &
359InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) {
360 if (Types && Kind == kTypes)
361 return *Types;
362 if (Ids && Kind == kIds)
363 return *Ids;
364
365 if (Kind == kIds) {
366 assert(isPdb() && pdb().hasPDBIpiStream())(static_cast <bool> (isPdb() && pdb().hasPDBIpiStream
()) ? void (0) : __assert_fail ("isPdb() && pdb().hasPDBIpiStream()"
, "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 366, __extension__ __PRETTY_FUNCTION__))
;
367 }
368
369 // If the collection was already initialized, we should have just returned it
370 // in step 1.
371 if (isPdb()) {
372 TypeCollectionPtr &Collection = (Kind == kIds) ? Ids : Types;
373 auto &Stream = cantFail((Kind == kIds) ? pdb().getPDBIpiStream()
374 : pdb().getPDBTpiStream());
375
376 auto &Array = Stream.typeArray();
377 uint32_t Count = Stream.getNumTypeRecords();
378 auto Offsets = Stream.getTypeIndexOffsets();
379 Collection =
380 llvm::make_unique<LazyRandomTypeCollection>(Array, Count, Offsets);
381 return *Collection;
382 }
383
384 assert(isObj())(static_cast <bool> (isObj()) ? void (0) : __assert_fail
("isObj()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 384, __extension__ __PRETTY_FUNCTION__))
;
385 assert(Kind == kTypes)(static_cast <bool> (Kind == kTypes) ? void (0) : __assert_fail
("Kind == kTypes", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 385, __extension__ __PRETTY_FUNCTION__))
;
386 assert(!Types)(static_cast <bool> (!Types) ? void (0) : __assert_fail
("!Types", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 386, __extension__ __PRETTY_FUNCTION__))
;
387
388 for (const auto &Section : obj().sections()) {
389 CVTypeArray Records;
390 if (!isDebugTSection(Section, Records))
391 continue;
392
393 Types = llvm::make_unique<LazyRandomTypeCollection>(Records, 100);
394 return *Types;
395 }
396
397 Types = llvm::make_unique<LazyRandomTypeCollection>(100);
398 return *Types;
399}
400
401codeview::LazyRandomTypeCollection &InputFile::types() {
402 return getOrCreateTypeCollection(kTypes);
403}
404
405codeview::LazyRandomTypeCollection &InputFile::ids() {
406 // Object files have only one type stream that contains both types and ids.
407 // Similarly, some PDBs don't contain an IPI stream, and for those both types
408 // and IDs are in the same stream.
409 if (isObj() || !pdb().hasPDBIpiStream())
410 return types();
411
412 return getOrCreateTypeCollection(kIds);
413}
414
415iterator_range<SymbolGroupIterator> InputFile::symbol_groups() {
416 return make_range<SymbolGroupIterator>(symbol_groups_begin(),
417 symbol_groups_end());
418}
419
420SymbolGroupIterator InputFile::symbol_groups_begin() {
421 return SymbolGroupIterator(*this);
422}
423
424SymbolGroupIterator InputFile::symbol_groups_end() {
425 return SymbolGroupIterator();
426}
427
428SymbolGroupIterator::SymbolGroupIterator() : Value(nullptr) {}
429
430SymbolGroupIterator::SymbolGroupIterator(InputFile &File) : Value(&File) {
431 if (File.isObj()) {
432 SectionIter = File.obj().section_begin();
433 scanToNextDebugS();
434 }
435}
436
437bool SymbolGroupIterator::operator==(const SymbolGroupIterator &R) const {
438 bool E = isEnd();
439 bool RE = R.isEnd();
440 if (E || RE)
441 return E == RE;
442
443 if (Value.File != R.Value.File)
444 return false;
445 return Index == R.Index;
446}
447
448const SymbolGroup &SymbolGroupIterator::operator*() const {
449 assert(!isEnd())(static_cast <bool> (!isEnd()) ? void (0) : __assert_fail
("!isEnd()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 449, __extension__ __PRETTY_FUNCTION__))
;
450 return Value;
451}
452SymbolGroup &SymbolGroupIterator::operator*() {
453 assert(!isEnd())(static_cast <bool> (!isEnd()) ? void (0) : __assert_fail
("!isEnd()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 453, __extension__ __PRETTY_FUNCTION__))
;
454 return Value;
455}
456
457SymbolGroupIterator &SymbolGroupIterator::operator++() {
458 assert(Value.File && !isEnd())(static_cast <bool> (Value.File && !isEnd()) ? void
(0) : __assert_fail ("Value.File && !isEnd()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 458, __extension__ __PRETTY_FUNCTION__))
;
459 ++Index;
460 if (isEnd())
461 return *this;
462
463 if (Value.File->isPdb()) {
464 Value.updatePdbModi(Index);
465 return *this;
466 }
467
468 scanToNextDebugS();
469 return *this;
470}
471
472void SymbolGroupIterator::scanToNextDebugS() {
473 assert(SectionIter.hasValue())(static_cast <bool> (SectionIter.hasValue()) ? void (0)
: __assert_fail ("SectionIter.hasValue()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 473, __extension__ __PRETTY_FUNCTION__))
;
474 auto End = Value.File->obj().section_end();
475 auto &Iter = *SectionIter;
476 assert(!isEnd())(static_cast <bool> (!isEnd()) ? void (0) : __assert_fail
("!isEnd()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 476, __extension__ __PRETTY_FUNCTION__))
;
477
478 while (++Iter != End) {
479 DebugSubsectionArray SS;
480 SectionRef SR = *Iter;
481 if (!isDebugSSection(SR, SS))
482 continue;
483
484 Value.updateDebugS(SS);
485 return;
486 }
487}
488
489bool SymbolGroupIterator::isEnd() const {
490 if (!Value.File)
491 return true;
492 if (Value.File->isPdb()) {
493 auto &Dbi = cantFail(Value.File->pdb().getPDBDbiStream());
494 uint32_t Count = Dbi.modules().getModuleCount();
495 assert(Index <= Count)(static_cast <bool> (Index <= Count) ? void (0) : __assert_fail
("Index <= Count", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 495, __extension__ __PRETTY_FUNCTION__))
;
496 return Index == Count;
497 }
498
499 assert(SectionIter.hasValue())(static_cast <bool> (SectionIter.hasValue()) ? void (0)
: __assert_fail ("SectionIter.hasValue()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/llvm-pdbutil/InputFile.cpp"
, 499, __extension__ __PRETTY_FUNCTION__))
;
500 return *SectionIter == Value.File->obj().section_end();
501}

/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/Support/BinaryStreamReader.h

1//===- BinaryStreamReader.h - Reads objects from a binary stream *- 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#ifndef LLVM_SUPPORT_BINARYSTREAMREADER_H
11#define LLVM_SUPPORT_BINARYSTREAMREADER_H
12
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/STLExtras.h"
15#include "llvm/Support/BinaryStreamArray.h"
16#include "llvm/Support/BinaryStreamRef.h"
17#include "llvm/Support/ConvertUTF.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/Error.h"
20#include "llvm/Support/type_traits.h"
21
22#include <string>
23#include <type_traits>
24
25namespace llvm {
26
27/// \brief Provides read only access to a subclass of `BinaryStream`. Provides
28/// bounds checking and helpers for writing certain common data types such as
29/// null-terminated strings, integers in various flavors of endianness, etc.
30/// Can be subclassed to provide reading of custom datatypes, although no
31/// are overridable.
32class BinaryStreamReader {
33public:
34 BinaryStreamReader() = default;
35 explicit BinaryStreamReader(BinaryStreamRef Ref);
36 explicit BinaryStreamReader(BinaryStream &Stream);
37 explicit BinaryStreamReader(ArrayRef<uint8_t> Data,
38 llvm::support::endianness Endian);
39 explicit BinaryStreamReader(StringRef Data, llvm::support::endianness Endian);
40
41 BinaryStreamReader(const BinaryStreamReader &Other)
42 : Stream(Other.Stream), Offset(Other.Offset) {}
43
44 BinaryStreamReader &operator=(const BinaryStreamReader &Other) {
45 Stream = Other.Stream;
46 Offset = Other.Offset;
47 return *this;
48 }
49
50 virtual ~BinaryStreamReader() {}
51
52 /// Read as much as possible from the underlying string at the current offset
53 /// without invoking a copy, and set \p Buffer to the resulting data slice.
54 /// Updates the stream's offset to point after the newly read data.
55 ///
56 /// \returns a success error code if the data was successfully read, otherwise
57 /// returns an appropriate error code.
58 Error readLongestContiguousChunk(ArrayRef<uint8_t> &Buffer);
59
60 /// Read \p Size bytes from the underlying stream at the current offset and
61 /// and set \p Buffer to the resulting data slice. Whether a copy occurs
62 /// depends on the implementation of the underlying stream. Updates the
63 /// stream's offset to point after the newly read data.
64 ///
65 /// \returns a success error code if the data was successfully read, otherwise
66 /// returns an appropriate error code.
67 Error readBytes(ArrayRef<uint8_t> &Buffer, uint32_t Size);
68
69 /// Read an integer of the specified endianness into \p Dest and update the
70 /// stream's offset. The data is always copied from the stream's underlying
71 /// buffer into \p Dest. Updates the stream's offset to point after the newly
72 /// read data.
73 ///
74 /// \returns a success error code if the data was successfully read, otherwise
75 /// returns an appropriate error code.
76 template <typename T> Error readInteger(T &Dest) {
77 static_assert(std::is_integral<T>::value,
78 "Cannot call readInteger with non-integral value!");
79
80 ArrayRef<uint8_t> Bytes;
81 if (auto EC = readBytes(Bytes, sizeof(T)))
10
Taking true branch
82 return EC;
83
84 Dest = llvm::support::endian::read<T, llvm::support::unaligned>(
85 Bytes.data(), Stream.getEndian());
86 return Error::success();
87 }
11
Returning without writing to 'Dest'
88
89 /// Similar to readInteger.
90 template <typename T> Error readEnum(T &Dest) {
91 static_assert(std::is_enum<T>::value,
92 "Cannot call readEnum with non-enum value!");
93 typename std::underlying_type<T>::type N;
94 if (auto EC = readInteger(N))
95 return EC;
96 Dest = static_cast<T>(N);
97 return Error::success();
98 }
99
100 /// Read a null terminated string from \p Dest. Whether a copy occurs depends
101 /// on the implementation of the underlying stream. Updates the stream's
102 /// offset to point after the newly read data.
103 ///
104 /// \returns a success error code if the data was successfully read, otherwise
105 /// returns an appropriate error code.
106 Error readCString(StringRef &Dest);
107
108 /// Similar to readCString, however read a null-terminated UTF16 string
109 /// instead.
110 ///
111 /// \returns a success error code if the data was successfully read, otherwise
112 /// returns an appropriate error code.
113 Error readWideString(ArrayRef<UTF16> &Dest);
114
115 /// Read a \p Length byte string into \p Dest. Whether a copy occurs depends
116 /// on the implementation of the underlying stream. Updates the stream's
117 /// offset to point after the newly read data.
118 ///
119 /// \returns a success error code if the data was successfully read, otherwise
120 /// returns an appropriate error code.
121 Error readFixedString(StringRef &Dest, uint32_t Length);
122
123 /// Read the entire remainder of the underlying stream into \p Ref. This is
124 /// equivalent to calling getUnderlyingStream().slice(Offset). Updates the
125 /// stream's offset to point to the end of the stream. Never causes a copy.
126 ///
127 /// \returns a success error code if the data was successfully read, otherwise
128 /// returns an appropriate error code.
129 Error readStreamRef(BinaryStreamRef &Ref);
130
131 /// Read \p Length bytes from the underlying stream into \p Ref. This is
132 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
133 /// Updates the stream's offset to point after the newly read object. Never
134 /// causes a copy.
135 ///
136 /// \returns a success error code if the data was successfully read, otherwise
137 /// returns an appropriate error code.
138 Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
139
140 /// Read \p Length bytes from the underlying stream into \p Stream. This is
141 /// equivalent to calling getUnderlyingStream().slice(Offset, Length).
142 /// Updates the stream's offset to point after the newly read object. Never
143 /// causes a copy.
144 ///
145 /// \returns a success error code if the data was successfully read, otherwise
146 /// returns an appropriate error code.
147 Error readSubstream(BinarySubstreamRef &Stream, uint32_t Size);
148
149 /// Get a pointer to an object of type T from the underlying stream, as if by
150 /// memcpy, and store the result into \p Dest. It is up to the caller to
151 /// ensure that objects of type T can be safely treated in this manner.
152 /// Updates the stream's offset to point after the newly read object. Whether
153 /// a copy occurs depends upon the implementation of the underlying
154 /// stream.
155 ///
156 /// \returns a success error code if the data was successfully read, otherwise
157 /// returns an appropriate error code.
158 template <typename T> Error readObject(const T *&Dest) {
159 ArrayRef<uint8_t> Buffer;
160 if (auto EC = readBytes(Buffer, sizeof(T)))
161 return EC;
162 Dest = reinterpret_cast<const T *>(Buffer.data());
163 return Error::success();
164 }
165
166 /// Get a reference to a \p NumElements element array of objects of type T
167 /// from the underlying stream as if by memcpy, and store the resulting array
168 /// slice into \p array. It is up to the caller to ensure that objects of
169 /// type T can be safely treated in this manner. Updates the stream's offset
170 /// to point after the newly read object. Whether a copy occurs depends upon
171 /// the implementation of the underlying stream.
172 ///
173 /// \returns a success error code if the data was successfully read, otherwise
174 /// returns an appropriate error code.
175 template <typename T>
176 Error readArray(ArrayRef<T> &Array, uint32_t NumElements) {
177 ArrayRef<uint8_t> Bytes;
178 if (NumElements == 0) {
179 Array = ArrayRef<T>();
180 return Error::success();
181 }
182
183 if (NumElements > UINT32_MAX(4294967295U) / sizeof(T))
184 return make_error<BinaryStreamError>(
185 stream_error_code::invalid_array_size);
186
187 if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
188 return EC;
189
190 assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&(static_cast <bool> (alignmentAdjustment(Bytes.data(), alignof
(T)) == 0 && "Reading at invalid alignment!") ? void (
0) : __assert_fail ("alignmentAdjustment(Bytes.data(), alignof(T)) == 0 && \"Reading at invalid alignment!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/Support/BinaryStreamReader.h"
, 191, __extension__ __PRETTY_FUNCTION__))
191 "Reading at invalid alignment!")(static_cast <bool> (alignmentAdjustment(Bytes.data(), alignof
(T)) == 0 && "Reading at invalid alignment!") ? void (
0) : __assert_fail ("alignmentAdjustment(Bytes.data(), alignof(T)) == 0 && \"Reading at invalid alignment!\""
, "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/Support/BinaryStreamReader.h"
, 191, __extension__ __PRETTY_FUNCTION__))
;
192
193 Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
194 return Error::success();
195 }
196
197 /// Read a VarStreamArray of size \p Size bytes and store the result into
198 /// \p Array. Updates the stream's offset to point after the newly read
199 /// array. Never causes a copy (although iterating the elements of the
200 /// VarStreamArray may, depending upon the implementation of the underlying
201 /// stream).
202 ///
203 /// \returns a success error code if the data was successfully read, otherwise
204 /// returns an appropriate error code.
205 template <typename T, typename U>
206 Error readArray(VarStreamArray<T, U> &Array, uint32_t Size) {
207 BinaryStreamRef S;
208 if (auto EC = readStreamRef(S, Size))
209 return EC;
210 Array.setUnderlyingStream(S);
211 return Error::success();
212 }
213
214 /// Read a FixedStreamArray of \p NumItems elements and store the result into
215 /// \p Array. Updates the stream's offset to point after the newly read
216 /// array. Never causes a copy (although iterating the elements of the
217 /// FixedStreamArray may, depending upon the implementation of the underlying
218 /// stream).
219 ///
220 /// \returns a success error code if the data was successfully read, otherwise
221 /// returns an appropriate error code.
222 template <typename T>
223 Error readArray(FixedStreamArray<T> &Array, uint32_t NumItems) {
224 if (NumItems == 0) {
225 Array = FixedStreamArray<T>();
226 return Error::success();
227 }
228
229 if (NumItems > UINT32_MAX(4294967295U) / sizeof(T))
230 return make_error<BinaryStreamError>(
231 stream_error_code::invalid_array_size);
232
233 BinaryStreamRef View;
234 if (auto EC = readStreamRef(View, NumItems * sizeof(T)))
235 return EC;
236
237 Array = FixedStreamArray<T>(View);
238 return Error::success();
239 }
240
241 bool empty() const { return bytesRemaining() == 0; }
242 void setOffset(uint32_t Off) { Offset = Off; }
243 uint32_t getOffset() const { return Offset; }
244 uint32_t getLength() const { return Stream.getLength(); }
245 uint32_t bytesRemaining() const { return getLength() - getOffset(); }
246
247 /// Advance the stream's offset by \p Amount bytes.
248 ///
249 /// \returns a success error code if at least \p Amount bytes remain in the
250 /// stream, otherwise returns an appropriate error code.
251 Error skip(uint32_t Amount);
252
253 /// Examine the next byte of the underlying stream without advancing the
254 /// stream's offset. If the stream is empty the behavior is undefined.
255 ///
256 /// \returns the next byte in the stream.
257 uint8_t peek() const;
258
259 Error padToAlignment(uint32_t Align);
260
261 std::pair<BinaryStreamReader, BinaryStreamReader>
262 split(uint32_t Offset) const;
263
264private:
265 BinaryStreamRef Stream;
266 uint32_t Offset = 0;
267};
268} // namespace llvm
269
270#endif // LLVM_SUPPORT_BINARYSTREAMREADER_H