forked from OSchip/llvm-project
Bitcode: Include any strings added to the string table in the module hash.
Differential Revision: https://reviews.llvm.org/D35037 llvm-svn: 307286
This commit is contained in:
parent
8d10129e59
commit
c855615831
|
@ -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<unsigned, 64> 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<uint8_t>((const uint8_t *)&(Buffer)[BlockStartPos],
|
||||
Buffer.size() - BlockStartPos));
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
source_filename = "foo.c"
|
||||
|
||||
$com = comdat any
|
||||
|
||||
define void @main() comdat($com) {
|
||||
call void @bar()
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @bar()
|
|
@ -0,0 +1,10 @@
|
|||
source_filename = "foo.c"
|
||||
|
||||
$dat = comdat any
|
||||
|
||||
define void @main() comdat($dat) {
|
||||
call void @foo()
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @foo()
|
|
@ -0,0 +1,15 @@
|
|||
; RUN: opt -module-hash %s -o - | llvm-bcanalyzer -dump | grep '<HASH' > %t
|
||||
; RUN: opt -module-hash %S/Inputs/module-hash-strtab1.ll -o - | llvm-bcanalyzer -dump | grep '<HASH' >> %t
|
||||
; RUN: opt -module-hash %S/Inputs/module-hash-strtab2.ll -o - | llvm-bcanalyzer -dump | grep '<HASH' >> %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()
|
|
@ -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: <HASH op0={{[0-9]*}} op1={{[0-9]*}} op2={{[0-9]*}} op3={{[0-9]*}} op4={{[0-9]*}} (match)/>
|
||||
; 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: <HASH op0={{[0-9]*}} op1={{[0-9]*}} op2={{[0-9]*}} op3={{[0-9]*}} op4={{[0-9]*}} (match)/>
|
||||
|
||||
; 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: <HASH op0=[[HASH1_1:[0-9]*]] op1=[[HASH1_2:[0-9]*]] op2=[[HASH1_3:[0-9]*]] op3=[[HASH1_4:[0-9]*]] op4=[[HASH1_5:[0-9]*]] (match)/>
|
||||
; COMBINED: <HASH op0=[[HASH2_1:[0-9]*]] op1=[[HASH2_2:[0-9]*]] op2=[[HASH2_3:[0-9]*]] op3=[[HASH2_4:[0-9]*]] op4=[[HASH2_5:[0-9]*]] (match)/>
|
||||
; COMBINED: <HASH op0=[[HASH1_1:[0-9]*]] op1=[[HASH1_2:[0-9]*]] op2=[[HASH1_3:[0-9]*]] op3=[[HASH1_4:[0-9]*]] op4=[[HASH1_5:[0-9]*]]/>
|
||||
; COMBINED: <HASH op0=[[HASH2_1:[0-9]*]] op1=[[HASH2_2:[0-9]*]] op2=[[HASH2_3:[0-9]*]] op3=[[HASH2_4:[0-9]*]] op4=[[HASH2_5:[0-9]*]]/>
|
||||
|
||||
; Validate against the value extracted from the combined index
|
||||
; COMBINED-DAG: <HASH abbrevid={{[0-9]*}} op0=[[HASH1_1]] op1=[[HASH1_2]] op2=[[HASH1_3]] op3=[[HASH1_4]] op4=[[HASH1_5]]/>
|
||||
|
|
|
@ -71,6 +71,10 @@ static cl::opt<bool>
|
|||
ShowBinaryBlobs("show-binary-blobs",
|
||||
cl::desc("Print binary blobs using hex escapes"));
|
||||
|
||||
static cl::opt<std::string> 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);
|
||||
|
|
Loading…
Reference in New Issue