Index: lldb/include/lldb/Core/DataFileCache.h =================================================================== --- lldb/include/lldb/Core/DataFileCache.h +++ lldb/include/lldb/Core/DataFileCache.h @@ -9,6 +9,7 @@ #ifndef LLDB_CORE_DATAFILECACHE_H #define LLDB_CORE_DATAFILECACHE_H +#include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/UUID.h" @@ -191,9 +192,12 @@ private: std::vector m_strings; + /// Note that Encode() will store uint32_t hash value before each string, + /// and the offset actually points to that. llvm::DenseMap m_string_to_offset; - /// Skip one byte to start the string table off with an empty string. - uint32_t m_next_offset = 1; + /// Skip one byte plus hash size to start the string table off with an empty + /// string. + uint32_t m_next_offset = 1 + sizeof(uint32_t); }; /// Many cache files require string tables to store data efficiently. This @@ -203,13 +207,15 @@ public: StringTableReader() = default; - llvm::StringRef Get(uint32_t offset) const; + ConstString Get(lldb::offset_t offset) const; bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr); protected: /// All of the strings in the string table are contained in m_data. - llvm::StringRef m_data; + /// Each format is uint32_t hash value followed by null-terminated + /// string data. + DataExtractor m_data; }; } // namespace lldb_private Index: lldb/include/lldb/Utility/ConstString.h =================================================================== --- lldb/include/lldb/Utility/ConstString.h +++ lldb/include/lldb/Utility/ConstString.h @@ -386,6 +386,15 @@ /// might not be NULL terminated if the string takes the entire buffer. void SetTrimmedCStringWithLength(const char *cstr, size_t fixed_cstr_len); + /// Returns a hash value of the string. + uint32_t GetHash() const; + + /// Set with hash value of the string + /// + /// Creates as if by calling SetString, but \a hash must contain the hash + /// of the string from a previous call to GetHash. + void SetStringWithHash(const llvm::StringRef &s, uint32_t hash); + /// Get the memory cost of this object. /// /// Return the size in bytes that this object takes in memory. This returns Index: lldb/source/Core/DataFileCache.cpp =================================================================== --- lldb/source/Core/DataFileCache.cpp +++ lldb/source/Core/DataFileCache.cpp @@ -12,6 +12,7 @@ #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/Endian.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "llvm/Support/CachePruning.h" @@ -262,11 +263,11 @@ const uint32_t offset = m_next_offset; m_strings.push_back(s); m_string_to_offset[s] = offset; - m_next_offset += s.GetLength() + 1; + m_next_offset += sizeof(uint32_t) + s.GetLength() + 1; // hash value + string return offset; } -static const llvm::StringRef kStringTableIdentifier("STAB"); +constexpr llvm::StringLiteral kStringTableIdentifier("STB2"); bool ConstStringTable::Encode(DataEncoder &encoder) { // Write an 4 character code into the stream. This will help us when decoding @@ -277,11 +278,16 @@ size_t length_offset = encoder.GetByteSize(); encoder.AppendU32(0); // Total length of all strings which will be fixed up. size_t strtab_offset = encoder.GetByteSize(); - encoder.AppendU8(0); // Start the string table with with an empty string. + // Start the string table with an empty string (preceded by its hash). + encoder.AppendU32(ConstString().GetHash()); + encoder.AppendU8(0); for (auto s: m_strings) { // Make sure all of the offsets match up with what we handed out! assert(m_string_to_offset.find(s)->second == encoder.GetByteSize() - strtab_offset); + // Append the hash value, so that it doesn't have to be computed every time + // the cache is read. + encoder.AppendU32(s.GetHash()); // Append the C string into the encoder encoder.AppendCString(s.GetStringRef()); } @@ -296,18 +302,21 @@ if (identifier != kStringTableIdentifier) return false; const uint32_t length = data.GetU32(offset_ptr); - // We always have at least one byte for the empty string at offset zero. - if (length == 0) + // We always have at least one byte for the empty string at offset 4 + // and there's uint32_t hash for it. + if (length < 1 + sizeof(uint32_t)) return false; - const char *bytes = (const char *)data.GetData(offset_ptr, length); - if (bytes == nullptr) - return false; - m_data = llvm::StringRef(bytes, length); + m_data = DataExtractor(data, *offset_ptr, length); + *offset_ptr += length; return true; } -llvm::StringRef StringTableReader::Get(uint32_t offset) const { - if (offset >= m_data.size()) - return llvm::StringRef(); - return llvm::StringRef(m_data.data() + offset); +ConstString StringTableReader::Get(lldb::offset_t offset) const { + if (offset >= m_data.GetByteSize()) + return ConstString(); + ConstString cstr; + uint32_t hash = m_data.GetU32(&offset); + llvm::StringRef str(m_data.PeekCStr(offset)); + cstr.SetStringWithHash(str, hash); + return cstr; } Index: lldb/source/Core/Mangled.cpp =================================================================== --- lldb/source/Core/Mangled.cpp +++ lldb/source/Core/Mangled.cpp @@ -431,16 +431,16 @@ return true; case DemangledOnly: - m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + m_demangled = strtab.Get(data.GetU32(offset_ptr)); return true; case MangledOnly: - m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + m_mangled = strtab.Get(data.GetU32(offset_ptr)); return true; case MangledAndDemangled: - m_mangled.SetString(strtab.Get(data.GetU32(offset_ptr))); - m_demangled.SetString(strtab.Get(data.GetU32(offset_ptr))); + m_mangled = strtab.Get(data.GetU32(offset_ptr)); + m_demangled = strtab.Get(data.GetU32(offset_ptr)); return true; } return false; Index: lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -505,7 +505,7 @@ kDataIDEnd = 255u, }; -constexpr uint32_t CURRENT_CACHE_VERSION = 1; +constexpr uint32_t CURRENT_CACHE_VERSION = 2; bool ManualDWARFIndex::IndexSet::Decode(const DataExtractor &data, lldb::offset_t *offset_ptr) { @@ -658,7 +658,8 @@ // that claims its module is the main executable. ObjectFile *objfile = m_dwarf->GetObjectFile(); strm << objfile->GetModule()->GetCacheKey() << "-dwarf-index-" - << llvm::format_hex(objfile->GetCacheHash(), 10); + << CURRENT_CACHE_VERSION << "-" + << llvm::format_hex(objfile->GetCacheHash(), 10); return strm.str(); } Index: lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -102,12 +102,12 @@ const uint32_t count = data.GetU32(offset_ptr); m_map.Reserve(count); for (uint32_t i = 0; i < count; ++i) { - llvm::StringRef str(strtab.Get(data.GetU32(offset_ptr))); + ConstString cstr(strtab.Get(data.GetU32(offset_ptr))); // No empty strings allowed in the name to DIE maps. - if (str.empty()) + if (cstr.IsEmpty()) return false; if (llvm::Optional die_ref = DIERef::Decode(data, offset_ptr)) - m_map.Append(ConstString(str), die_ref.getValue()); + m_map.Append(cstr, die_ref.getValue()); else return false; } Index: lldb/source/Symbol/Symtab.cpp =================================================================== --- lldb/source/Symbol/Symtab.cpp +++ lldb/source/Symbol/Symtab.cpp @@ -1158,6 +1158,8 @@ return nullptr; } +constexpr uint32_t CURRENT_CACHE_VERSION = 2; + std::string Symtab::GetCacheKey() { std::string key; llvm::raw_string_ostream strm(key); @@ -1165,7 +1167,8 @@ // module can have one object file as the main executable and might have // another object file in a separate symbol file. strm << m_objfile->GetModule()->GetCacheKey() << "-symtab-" - << llvm::format_hex(m_objfile->GetCacheHash(), 10); + << CURRENT_CACHE_VERSION << "-" + << llvm::format_hex(m_objfile->GetCacheHash(), 10); return strm.str(); } @@ -1207,12 +1210,12 @@ cstr_map.Reserve(count); for (uint32_t i=0; i') + // - add it here, remove trailing empty items + // - set offsets 19-23 (between 0x02 and 0xff) to 0x00 const uint8_t symtab_cache_bytes[] = { 0x01, 0x10, 0x3e, 0x94, 0x86, 0x6e, 0x0d, 0x1a, 0x39, 0xbd, 0x97, 0x5b, 0x64, 0xe8, 0xf1, 0xfd, - 0xba, 0xae, 0xff, 0x53, 0x54, 0x41, 0x42, 0x91, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0x55, 0x73, 0x65, - 0x72, 0x73, 0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79, - 0x74, 0x6f, 0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62, - 0x6a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, - 0x63, 0x00, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, - 0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79, 0x74, 0x6f, - 0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62, 0x6a, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6f, 0x00, - 0x66, 0x6f, 0x6f, 0x00, 0x62, 0x61, 0x72, 0x00, - 0x62, 0x61, 0x7a, 0x00, 0x6d, 0x61, 0x69, 0x6e, - 0x00, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x00, 0x53, 0x59, 0x4d, 0x42, - 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2a, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0xba, 0xae, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x53, 0x54, 0x42, 0x32, 0xb1, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x46, 0xb0, + 0x3d, 0x2f, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2f, + 0x67, 0x63, 0x6c, 0x61, 0x79, 0x74, 0x6f, 0x6e, + 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x2f, 0x6f, 0x62, 0x6a, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x2f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2f, + 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x63, 0x00, 0x08, + 0x47, 0xb0, 0x3d, 0x2f, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x2f, 0x67, 0x63, 0x6c, 0x61, 0x79, 0x74, + 0x6f, 0x6e, 0x2f, 0x44, 0x6f, 0x63, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6f, 0x62, 0x6a, + 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2f, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x2d, 0x6e, 0x61, 0x6d, 0x65, + 0x73, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6f, + 0x00, 0xa4, 0xc0, 0x01, 0x00, 0x66, 0x6f, 0x6f, + 0x00, 0xd5, 0xad, 0x01, 0x00, 0x62, 0x61, 0x72, + 0x00, 0xdd, 0xad, 0x01, 0x00, 0x62, 0x61, 0x7a, + 0x00, 0xe5, 0x6f, 0x3d, 0x00, 0x6d, 0x61, 0x69, + 0x6e, 0x00, 0xee, 0x47, 0xd6, 0x47, 0x5f, 0x6d, + 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x00, 0x53, 0x59, 0x4d, 0x42, 0x02, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x2a, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0a, 0x20, 0x01, 0x37, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0xc3, 0x69, 0x62, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x20, 0x01, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xc3, 0x69, + 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x66, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x32, 0x01, 0x79, 0x00, 0x00, 0x00, 0x01, 0x64, + 0x3f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x66, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x32, 0x01, 0x6d, 0x00, 0x00, - 0x00, 0x01, 0x64, 0x3f, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x32, 0x01, 0x71, - 0x00, 0x00, 0x00, 0x01, 0x6c, 0x3f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, - 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x32, - 0x01, 0x75, 0x00, 0x00, 0x00, 0x01, 0x74, 0x3f, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x32, 0x01, 0x79, 0x00, 0x00, 0x00, 0x01, - 0x7c, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0f, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x04, 0x12, 0x02, 0x7e, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x64, 0x3f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x01, 0x00, - 0x43, 0x4d, 0x41, 0x50, 0x07, 0x00, 0x00, 0x00, - 0x6d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x75, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x79, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x71, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x7e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 + 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x32, 0x01, 0x81, 0x00, 0x00, 0x00, + 0x01, 0x6c, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x32, 0x01, 0x89, 0x00, + 0x00, 0x00, 0x01, 0x74, 0x3f, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x32, 0x01, + 0x91, 0x00, 0x00, 0x00, 0x01, 0x7c, 0x3f, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x12, 0x02, 0x9a, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x0f, 0x00, 0x01, 0x00, 0x43, 0x4d, 0x41, + 0x50, 0x07, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00 }; ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); Index: lldb/unittests/Utility/ConstStringTest.cpp =================================================================== --- lldb/unittests/Utility/ConstStringTest.cpp +++ lldb/unittests/Utility/ConstStringTest.cpp @@ -157,3 +157,12 @@ EXPECT_EQ(strings, deserialized); } + +TEST(ConstStringTest, Hash) { + // If this test fails, that most likely means that the implementation + // of StringMap::hash() has changed. Places that use ConstString::GetHash() + // need to be checked and those that reuse the value between runs + // such as cache files need to have their version increased. + ConstString str("This is a test string for ConstString hash."); + EXPECT_EQ(1740496963U, str.GetHash()); +}