diff options
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 42 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Serialization/GlobalModuleIndex.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/Module.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 18 |
5 files changed, 79 insertions, 3 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index f3181546320..80b1c2b6bcc 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2363,6 +2363,11 @@ ASTReader::ReadControlBlock(ModuleFile &F, break; } + case SIGNATURE: + assert((!F.Signature || F.Signature == Record[0]) && "signature changed"); + F.Signature = Record[0]; + break; + case IMPORTS: { // Load each of the imported PCH files. unsigned Idx = 0, N = Record.size(); @@ -2376,6 +2381,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, SourceLocation::getFromRawEncoding(Record[Idx++]); off_t StoredSize = (off_t)Record[Idx++]; time_t StoredModTime = (time_t)Record[Idx++]; + ASTFileSignature StoredSignature = Record[Idx++]; unsigned Length = Record[Idx++]; SmallString<128> ImportedFile(Record.begin() + Idx, Record.begin() + Idx + Length); @@ -2383,7 +2389,7 @@ ASTReader::ReadControlBlock(ModuleFile &F, // Load the AST file. switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded, - StoredSize, StoredModTime, + StoredSize, StoredModTime, StoredSignature, ClientLoadCapabilities)) { case Failure: return Failure; // If we have to ignore the dependency, we'll have to ignore this too. @@ -3552,7 +3558,7 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, SmallVector<ImportedModule, 4> Loaded; switch(ASTReadResult ReadResult = ReadASTCore(FileName, Type, ImportLoc, /*ImportedBy=*/nullptr, Loaded, - 0, 0, + 0, 0, 0, ClientLoadCapabilities)) { case Failure: case Missing: @@ -3719,6 +3725,8 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, return Success; } +static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile); + ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, @@ -3726,12 +3734,14 @@ ASTReader::ReadASTCore(StringRef FileName, ModuleFile *ImportedBy, SmallVectorImpl<ImportedModule> &Loaded, off_t ExpectedSize, time_t ExpectedModTime, + ASTFileSignature ExpectedSignature, unsigned ClientLoadCapabilities) { ModuleFile *M; std::string ErrorStr; ModuleManager::AddModuleResult AddResult = ModuleMgr.addModule(FileName, Type, ImportLoc, ImportedBy, getGeneration(), ExpectedSize, ExpectedModTime, + ExpectedSignature, readASTFileSignature, M, ErrorStr); switch (AddResult) { @@ -4029,6 +4039,34 @@ static bool SkipCursorToBlock(BitstreamCursor &Cursor, unsigned BlockID) { } } +static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){ + BitstreamCursor Stream(StreamFile); + if (Stream.Read(8) != 'C' || + Stream.Read(8) != 'P' || + Stream.Read(8) != 'C' || + Stream.Read(8) != 'H') { + return 0; + } + + // Scan for the CONTROL_BLOCK_ID block. + if (SkipCursorToBlock(Stream, CONTROL_BLOCK_ID)) + return 0; + + // Scan for SIGNATURE inside the control block. + ASTReader::RecordData Record; + while (1) { + llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + if (Entry.Kind == llvm::BitstreamEntry::EndBlock || + Entry.Kind != llvm::BitstreamEntry::Record) + return 0; + + Record.clear(); + StringRef Blob; + if (SIGNATURE == Stream.readRecord(Entry.ID, Record, &Blob)) + return Record[0]; + } +} + /// \brief Retrieve the name of the original source file name /// directly from the AST file, without actually loading the AST /// file. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 0681e3975d2..e39e5bb0222 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -51,6 +51,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include <algorithm> #include <cstdio> #include <string.h> @@ -862,6 +863,7 @@ void ASTWriter::WriteBlockInfoBlock() { // Control Block. BLOCK(CONTROL_BLOCK); RECORD(METADATA); + RECORD(SIGNATURE); RECORD(MODULE_NAME); RECORD(MODULE_MAP_FILE); RECORD(IMPORTS); @@ -1092,6 +1094,14 @@ adjustFilenameForRelocatablePCH(const char *Filename, StringRef isysroot) { return Filename + Pos; } +static ASTFileSignature getSignature() { + while (1) { + if (ASTFileSignature S = llvm::sys::Process::GetRandomNumber()) + return S; + // Rely on GetRandomNumber to eventually return non-zero... + } +} + /// \brief Write the control block. void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, StringRef isysroot, @@ -1121,6 +1131,11 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record, getClangFullRepositoryVersion()); + // Signature + Record.clear(); + Record.push_back(getSignature()); + Stream.EmitRecord(SIGNATURE, Record); + // Module name if (WritingModule) { BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); @@ -1173,6 +1188,7 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, AddSourceLocation((*M)->ImportLoc, Record); Record.push_back((*M)->File->getSize()); Record.push_back((*M)->File->getModificationTime()); + Record.push_back((*M)->Signature); const std::string &FileName = (*M)->FileName; Record.push_back(FileName.size()); Record.append(FileName.begin(), FileName.end()); diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index f43fbaca140..121478ce052 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -591,6 +591,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { off_t StoredSize = (off_t)Record[Idx++]; time_t StoredModTime = (time_t)Record[Idx++]; + // Skip the stored signature. + // FIXME: we could read the signature out of the import and validate it. + Idx++; + // Retrieve the imported file name. unsigned Length = Record[Idx++]; SmallString<128> ImportedFile(Record.begin() + Idx, diff --git a/clang/lib/Serialization/Module.cpp b/clang/lib/Serialization/Module.cpp index 6f2a3c22043..6c48a41187c 100644 --- a/clang/lib/Serialization/Module.cpp +++ b/clang/lib/Serialization/Module.cpp @@ -21,7 +21,7 @@ using namespace serialization; using namespace reader; ModuleFile::ModuleFile(ModuleKind Kind, unsigned Generation) - : Kind(Kind), File(nullptr), DirectlyImported(false), + : Kind(Kind), File(nullptr), Signature(0), DirectlyImported(false), Generation(Generation), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0), SLocEntryBaseOffset(0), SLocEntryOffsets(nullptr), diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 20249e0a7bd..300ef31b590 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -57,6 +57,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, SourceLocation ImportLoc, ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, + ASTFileSignature ExpectedSignature, + std::function<ASTFileSignature(llvm::BitstreamReader &)> + ReadSignature, ModuleFile *&Module, std::string &ErrorStr) { Module = nullptr; @@ -130,6 +133,21 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // Initialize the stream New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), (const unsigned char *)New->Buffer->getBufferEnd()); + + if (ExpectedSignature) { + New->Signature = ReadSignature(New->StreamFile); + if (New->Signature != ExpectedSignature) { + ErrorStr = New->Signature ? "signature mismatch" + : "could not read module signature"; + + // Remove the module file immediately, since removeModules might try to + // invalidate the file cache for Entry, and that is not safe if this + // module is *itself* up to date, but has an out-of-date importer. + Modules.erase(Entry); + Chain.pop_back(); + return OutOfDate; + } + } } if (ImportedBy) { |