diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index b2b1ea6de37..862d43381f3 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -114,6 +114,8 @@ class ModuleBitcodeWriter : public BitcodeWriterBase { /// True if a module hash record should be written. bool GenerateHash; + SHA1 Hasher; + /// If non-null, when GenerateHash is true, the resulting hash is written /// into ModHash. When GenerateHash is false, that specified value /// is used as the hash instead of computing from the generated bitcode. @@ -176,6 +178,8 @@ public: private: uint64_t bitcodeStartBit() { return BitcodeStartBit; } + size_t addToStrtab(StringRef Str); + void writeAttributeGroupTable(); void writeAttributeTable(); void writeTypeTable(); @@ -947,11 +951,17 @@ static unsigned getEncodedUnnamedAddr(const GlobalValue &GV) { llvm_unreachable("Invalid unnamed_addr"); } +size_t ModuleBitcodeWriter::addToStrtab(StringRef Str) { + if (GenerateHash) + Hasher.update(Str); + return StrtabBuilder.add(Str); +} + void ModuleBitcodeWriter::writeComdats() { SmallVector Vals; for (const Comdat *C : VE.getComdats()) { // COMDAT: [strtab offset, strtab size, selection_kind] - Vals.push_back(StrtabBuilder.add(C->getName())); + Vals.push_back(addToStrtab(C->getName())); Vals.push_back(C->getName().size()); Vals.push_back(getEncodedComdatSelectionKind(*C)); Stream.EmitRecord(bitc::MODULE_CODE_COMDAT, Vals, /*AbbrevToUse=*/0); @@ -1122,7 +1132,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { // linkage, alignment, section, visibility, threadlocal, // unnamed_addr, externally_initialized, dllstorageclass, // comdat, attributes] - Vals.push_back(StrtabBuilder.add(GV.getName())); + Vals.push_back(addToStrtab(GV.getName())); Vals.push_back(GV.getName().size()); Vals.push_back(VE.getTypeID(GV.getValueType())); Vals.push_back(GV.getType()->getAddressSpace() << 2 | 2 | GV.isConstant()); @@ -1161,7 +1171,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { // linkage, paramattrs, alignment, section, visibility, gc, // unnamed_addr, prologuedata, dllstorageclass, comdat, // prefixdata, personalityfn] - Vals.push_back(StrtabBuilder.add(F.getName())); + Vals.push_back(addToStrtab(F.getName())); Vals.push_back(F.getName().size()); Vals.push_back(VE.getTypeID(F.getFunctionType())); Vals.push_back(F.getCallingConv()); @@ -1191,7 +1201,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { for (const GlobalAlias &A : M.aliases()) { // ALIAS: [strtab offset, strtab size, alias type, aliasee val#, linkage, // visibility, dllstorageclass, threadlocal, unnamed_addr] - Vals.push_back(StrtabBuilder.add(A.getName())); + Vals.push_back(addToStrtab(A.getName())); Vals.push_back(A.getName().size()); Vals.push_back(VE.getTypeID(A.getValueType())); Vals.push_back(A.getType()->getAddressSpace()); @@ -1210,7 +1220,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { for (const GlobalIFunc &I : M.ifuncs()) { // IFUNC: [strtab offset, strtab size, ifunc type, address space, resolver // val#, linkage, visibility] - Vals.push_back(StrtabBuilder.add(I.getName())); + Vals.push_back(addToStrtab(I.getName())); Vals.push_back(I.getName().size()); Vals.push_back(VE.getTypeID(I.getValueType())); Vals.push_back(I.getType()->getAddressSpace()); @@ -3648,7 +3658,6 @@ void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) { // Emit the module's hash. // MODULE_CODE_HASH: [5*i32] if (GenerateHash) { - SHA1 Hasher; uint32_t Vals[5]; Hasher.update(ArrayRef((const uint8_t *)&(Buffer)[BlockStartPos], Buffer.size() - BlockStartPos)); diff --git a/test/Bitcode/Inputs/module-hash-strtab1.ll b/test/Bitcode/Inputs/module-hash-strtab1.ll new file mode 100644 index 00000000000..6b4a3fce07e --- /dev/null +++ b/test/Bitcode/Inputs/module-hash-strtab1.ll @@ -0,0 +1,10 @@ +source_filename = "foo.c" + +$com = comdat any + +define void @main() comdat($com) { + call void @bar() + ret void +} + +declare void @bar() diff --git a/test/Bitcode/Inputs/module-hash-strtab2.ll b/test/Bitcode/Inputs/module-hash-strtab2.ll new file mode 100644 index 00000000000..87d2478145b --- /dev/null +++ b/test/Bitcode/Inputs/module-hash-strtab2.ll @@ -0,0 +1,10 @@ +source_filename = "foo.c" + +$dat = comdat any + +define void @main() comdat($dat) { + call void @foo() + ret void +} + +declare void @foo() diff --git a/test/Bitcode/module-hash-strtab.ll b/test/Bitcode/module-hash-strtab.ll new file mode 100644 index 00000000000..e5a1fb0c407 --- /dev/null +++ b/test/Bitcode/module-hash-strtab.ll @@ -0,0 +1,15 @@ +; RUN: opt -module-hash %s -o - | llvm-bcanalyzer -dump | grep ' %t +; RUN: opt -module-hash %S/Inputs/module-hash-strtab1.ll -o - | llvm-bcanalyzer -dump | grep '> %t +; RUN: opt -module-hash %S/Inputs/module-hash-strtab2.ll -o - | llvm-bcanalyzer -dump | grep '> %t +; RUN: sort %t | uniq | count 3 + +source_filename = "foo.c" + +$com = comdat any + +define void @main() comdat($com) { + call void @foo() + ret void +} + +declare void @foo() diff --git a/test/Bitcode/module_hash.ll b/test/Bitcode/module_hash.ll index 56f3fdc4b7e..b24819fe6fd 100644 --- a/test/Bitcode/module_hash.ll +++ b/test/Bitcode/module_hash.ll @@ -1,7 +1,7 @@ ; Check per module hash. -; RUN: opt -module-hash %s -o - | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=MOD1 +; RUN: opt -module-hash %s -o - | llvm-bcanalyzer -dump -check-hash=foo | FileCheck %s --check-prefix=MOD1 ; MOD1: -; RUN: opt -module-hash %p/Inputs/module_hash.ll -o - | llvm-bcanalyzer -dump | FileCheck %s --check-prefix=MOD2 +; RUN: opt -module-hash %p/Inputs/module_hash.ll -o - | llvm-bcanalyzer -dump -check-hash=bar | FileCheck %s --check-prefix=MOD2 ; MOD2: ; Check that the hash matches in the combined index. @@ -21,8 +21,8 @@ ; RUN: cat %t.hash | FileCheck %s --check-prefix=COMBINED ; First capture the value of the hash for the two modules. -; COMBINED: -; COMBINED: +; COMBINED: +; COMBINED: ; Validate against the value extracted from the combined index ; COMBINED-DAG: diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 528247c2dbc..529bdf5b7d9 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -71,6 +71,10 @@ static cl::opt ShowBinaryBlobs("show-binary-blobs", cl::desc("Print binary blobs using hex escapes")); +static cl::opt CheckHash( + "check-hash", + cl::desc("Check module hash using the argument as a string table")); + namespace { /// CurStreamTypeType - A type for CurStreamType @@ -652,13 +656,15 @@ static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo, } // If we found a module hash, let's verify that it matches! - if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH) { + if (BlockID == bitc::MODULE_BLOCK_ID && Code == bitc::MODULE_CODE_HASH && + !CheckHash.empty()) { if (Record.size() != 5) outs() << " (invalid)"; else { // Recompute the hash and compare it to the one in the bitcode SHA1 Hasher; StringRef Hash; + Hasher.update(CheckHash); { int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos; auto Ptr = Stream.getPointerToByte(BlockEntryPos, BlockSize);