diff options
author | Ben Langmuir <blangmuir@apple.com> | 2014-10-23 18:05:36 +0000 |
---|---|---|
committer | Ben Langmuir <blangmuir@apple.com> | 2014-10-23 18:05:36 +0000 |
commit | 487ea14a46f50f7b025ebb3ae5ee00da935b3f25 (patch) | |
tree | 546427f824aec7a61a92e1cf15451afe1ed88ef1 /clang/lib/Serialization/ModuleManager.cpp | |
parent | 5b2787dfb263574ec94a1993c3f1627f9adf97da (diff) | |
download | bcm5719-llvm-487ea14a46f50f7b025ebb3ae5ee00da935b3f25.tar.gz bcm5719-llvm-487ea14a46f50f7b025ebb3ae5ee00da935b3f25.zip |
Add a "signature" to AST files to verify that they haven't changed
Since the order of the IDs in the AST file (e.g. DeclIDs, SelectorIDs)
is not stable, it is not safe to load an AST file that depends on
another AST file that has been rebuilt since the importer was built,
even if "nothing changed". We previously used size and modtime to check
this, but I've seen cases where a module rebuilt quickly enough to foil
this check and caused very hard to debug build errors.
To save cycles when we're loading the AST, we just generate a random
nonce value and check that it hasn't changed when we load an imported
module, rather than actually hash the whole file.
This is slightly complicated by the fact that we need to verify the
signature inside addModule, since we might otherwise consider that a
mdoule is "OutOfDate" when really it is the importer that is out of
date. I didn't see any regressions in module load time after this
change.
llvm-svn: 220493
Diffstat (limited to 'clang/lib/Serialization/ModuleManager.cpp')
-rw-r--r-- | clang/lib/Serialization/ModuleManager.cpp | 18 |
1 files changed, 18 insertions, 0 deletions
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) { |