aboutsummaryrefslogtreecommitdiff
path: root/lib/Object/IRSymtab.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Object/IRSymtab.cpp')
-rw-r--r--lib/Object/IRSymtab.cpp48
1 files changed, 45 insertions, 3 deletions
diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp
index 7bca032a7be1..7a6424a76a98 100644
--- a/lib/Object/IRSymtab.cpp
+++ b/lib/Object/IRSymtab.cpp
@@ -32,6 +32,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/VCSRevision.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <string>
@@ -43,6 +44,21 @@ using namespace irsymtab;
namespace {
+const char *getExpectedProducerName() {
+ static char DefaultName[] = LLVM_VERSION_STRING
+#ifdef LLVM_REVISION
+ " " LLVM_REVISION
+#endif
+ ;
+ // Allows for testing of the irsymtab writer and upgrade mechanism. This
+ // environment variable should not be set by users.
+ if (char *OverrideName = getenv("LLVM_OVERRIDE_PRODUCER"))
+ return OverrideName;
+ return DefaultName;
+}
+
+const char *kExpectedProducerName = getExpectedProducerName();
+
/// Stores the temporary state that is required to build an IR symbol table.
struct Builder {
SmallVector<char, 0> &Symtab;
@@ -231,6 +247,8 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
storage::Header Hdr;
assert(!IRMods.empty());
+ Hdr.Version = storage::Header::kCurrentVersion;
+ setStr(Hdr.Producer, kExpectedProducerName);
setStr(Hdr.TargetTriple, IRMods[0]->getTargetTriple());
setStr(Hdr.SourceFileName, IRMods[0]->getSourceFileName());
TT = Triple(IRMods[0]->getTargetTriple());
@@ -300,7 +318,31 @@ Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) {
return make_error<StringError>("Bitcode file does not contain any modules",
inconvertibleErrorCode());
- // Right now we have no on-disk representation of symbol tables, so we always
- // upgrade.
- return upgrade(BFC.Mods);
+ if (BFC.StrtabForSymtab.empty() ||
+ BFC.Symtab.size() < sizeof(storage::Header))
+ return upgrade(BFC.Mods);
+
+ // We cannot use the regular reader to read the version and producer, because
+ // it will expect the header to be in the current format. The only thing we
+ // can rely on is that the version and producer will be present as the first
+ // struct elements.
+ auto *Hdr = reinterpret_cast<const storage::Header *>(BFC.Symtab.data());
+ unsigned Version = Hdr->Version;
+ StringRef Producer = Hdr->Producer.get(BFC.StrtabForSymtab);
+ if (Version != storage::Header::kCurrentVersion ||
+ Producer != kExpectedProducerName)
+ return upgrade(BFC.Mods);
+
+ FileContents FC;
+ FC.TheReader = {{BFC.Symtab.data(), BFC.Symtab.size()},
+ {BFC.StrtabForSymtab.data(), BFC.StrtabForSymtab.size()}};
+
+ // Finally, make sure that the number of modules in the symbol table matches
+ // the number of modules in the bitcode file. If they differ, it may mean that
+ // the bitcode file was created by binary concatenation, so we need to create
+ // a new symbol table from scratch.
+ if (FC.TheReader.getNumModules() != BFC.Mods.size())
+ return upgrade(std::move(BFC.Mods));
+
+ return std::move(FC);
}