Index: lldb/trunk/include/lldb/Utility/DataExtractor.h =================================================================== --- lldb/trunk/include/lldb/Utility/DataExtractor.h +++ lldb/trunk/include/lldb/Utility/DataExtractor.h @@ -223,22 +223,6 @@ const char *type_format = nullptr) const; //------------------------------------------------------------------ - /// Dump a UUID value at \a offset. - /// - /// Dump a UUID starting at \a offset bytes into this object's data. If the - /// stream \a s is nullptr, the output will be sent to Log(). - /// - /// @param[in] s - /// The stream to dump the output to. If nullptr the output will - /// be dumped to Log(). - /// - /// @param[in] offset - /// The offset into the data at which to extract and dump a - /// UUID value. - //------------------------------------------------------------------ - void DumpUUID(Stream *s, lldb::offset_t offset) const; - - //------------------------------------------------------------------ /// Extract an arbitrary number of bytes in the specified byte order. /// /// Attemps to extract \a length bytes starting at \a offset bytes into this Index: lldb/trunk/include/lldb/Utility/UUID.h =================================================================== --- lldb/trunk/include/lldb/Utility/UUID.h +++ lldb/trunk/include/lldb/Utility/UUID.h @@ -33,15 +33,38 @@ //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - UUID(); - UUID(const UUID &rhs); - UUID(const void *uuid_bytes, uint32_t num_uuid_bytes); + UUID() = default; - ~UUID(); + /// Creates a UUID from the data pointed to by the bytes argument. No special + /// significance is attached to any of the values. + static UUID fromData(const void *bytes, uint32_t num_bytes) { + if (bytes) + return fromData({reinterpret_cast(bytes), num_bytes}); + return UUID(); + } + + /// Creates a uuid from the data pointed to by the bytes argument. No special + /// significance is attached to any of the values. + static UUID fromData(llvm::ArrayRef bytes) { return UUID(bytes); } + + /// Creates a UUID from the data pointed to by the bytes argument. Data + /// consisting purely of zero bytes is treated as an invalid UUID. + static UUID fromOptionalData(const void *bytes, uint32_t num_bytes) { + if (bytes) + return fromOptionalData( + {reinterpret_cast(bytes), num_bytes}); + return UUID(); + } - const UUID &operator=(const UUID &rhs); + /// Creates a UUID from the data pointed to by the bytes argument. Data + /// consisting purely of zero bytes is treated as an invalid UUID. + static UUID fromOptionalData(llvm::ArrayRef bytes) { + if (llvm::all_of(bytes, [](uint8_t b) { return b == 0; })) + return UUID(); + return UUID(bytes); + } - void Clear(); + void Clear() { m_num_uuid_bytes = 0; } void Dump(Stream *s) const; @@ -49,9 +72,8 @@ return {m_uuid, m_num_uuid_bytes}; } - bool IsValid() const; - - bool SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes = 16); + explicit operator bool() const { return IsValid(); } + bool IsValid() const { return m_num_uuid_bytes > 0; } std::string GetAsString(const char *separator = nullptr) const; @@ -81,11 +103,10 @@ uint32_t &bytes_decoded, uint32_t num_uuid_bytes = 16); -protected: - //------------------------------------------------------------------ - // Classes that inherit from UUID can see and modify these - //------------------------------------------------------------------ - uint32_t m_num_uuid_bytes; // Should be 16 or 20 +private: + UUID(llvm::ArrayRef bytes); + + uint32_t m_num_uuid_bytes = 0; // Should be 0, 16 or 20 ValueType m_uuid; }; Index: lldb/trunk/source/API/SBModuleSpec.cpp =================================================================== --- lldb/trunk/source/API/SBModuleSpec.cpp +++ lldb/trunk/source/API/SBModuleSpec.cpp @@ -90,7 +90,8 @@ } bool SBModuleSpec::SetUUIDBytes(const uint8_t *uuid, size_t uuid_len) { - return m_opaque_ap->GetUUID().SetBytes(uuid, uuid_len); + m_opaque_ap->GetUUID() = UUID::fromOptionalData(uuid, uuid_len); + return m_opaque_ap->GetUUID().IsValid(); } bool SBModuleSpec::GetDescription(lldb::SBStream &description) { Index: lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp =================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -1368,7 +1368,7 @@ if (name_data == NULL) break; image_infos[i].SetName((const char *)name_data); - UUID uuid(extractor.GetData(&offset, 16), 16); + UUID uuid = UUID::fromOptionalData(extractor.GetData(&offset, 16), 16); image_infos[i].SetUUID(uuid); image_infos[i].SetLoadAddress(extractor.GetU64(&offset)); image_infos[i].SetSize(extractor.GetU64(&offset)); Index: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp =================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -898,7 +898,7 @@ break; case llvm::MachO::LC_UUID: - dylib_info.uuid.SetBytes(data.GetData(&offset, 16)); + dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16); break; default: @@ -1110,7 +1110,7 @@ uuid_t shared_cache_uuid; if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid, sizeof(uuid_t), err) == sizeof(uuid_t)) { - uuid.SetBytes(shared_cache_uuid); + uuid = UUID::fromOptionalData(shared_cache_uuid, 16); if (uuid.IsValid()) { using_shared_cache = eLazyBoolYes; } Index: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -733,13 +733,13 @@ if (gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. uint32_t uuidt[4] = {gnu_debuglink_crc, 0, 0, 0}; - uuid.SetBytes(uuidt, sizeof(uuidt)); + uuid = UUID::fromData(uuidt, sizeof(uuidt)); } else if (core_notes_crc) { // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make // it look different form .gnu_debuglink crc followed by 4 bytes // of note segments crc. uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0}; - uuid.SetBytes(uuidt, sizeof(uuidt)); + uuid = UUID::fromData(uuidt, sizeof(uuidt)); } } @@ -926,7 +926,7 @@ // different form .gnu_debuglink crc - followed by 4 bytes of note // segments crc. uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0}; - m_uuid.SetBytes(uuidt, sizeof(uuidt)); + m_uuid = UUID::fromData(uuidt, sizeof(uuidt)); } } else { if (!m_gnu_debuglink_crc) @@ -935,7 +935,7 @@ if (m_gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. uint32_t uuidt[4] = {m_gnu_debuglink_crc, 0, 0, 0}; - m_uuid.SetBytes(uuidt, sizeof(uuidt)); + m_uuid = UUID::fromData(uuidt, sizeof(uuidt)); } } @@ -1284,7 +1284,7 @@ } // Save the build id as the UUID for the module. - uuid.SetBytes(uuidbuf, note.n_descsz); + uuid = UUID::fromData(uuidbuf, note.n_descsz); } } break; Index: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -2087,10 +2087,8 @@ version_str[6] = '\0'; if (strcmp(version_str, "dyld_v") == 0) { offset = offsetof(struct lldb_copy_dyld_cache_header_v1, uuid); - uint8_t uuid_bytes[sizeof(uuid_t)]; - memcpy(uuid_bytes, dsc_header_data.GetData(&offset, sizeof(uuid_t)), - sizeof(uuid_t)); - dsc_uuid.SetBytes(uuid_bytes); + dsc_uuid = UUID::fromOptionalData( + dsc_header_data.GetData(&offset, sizeof(uuid_t)), sizeof(uuid_t)); } Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); if (log && dsc_uuid.IsValid()) { @@ -4861,7 +4859,7 @@ if (!memcmp(uuid_bytes, opencl_uuid, 16)) return false; - uuid.SetBytes(uuid_bytes); + uuid = UUID::fromOptionalData(uuid_bytes, 16); return true; } return false; @@ -5392,12 +5390,11 @@ uuid_t raw_uuid; memset (raw_uuid, 0, sizeof (uuid_t)); - if (m_data.GetU32 (&offset, &type, 1) - && m_data.GetU64 (&offset, &address, 1) - && m_data.CopyData (offset, sizeof (uuid_t), raw_uuid) != 0 - && uuid.SetBytes (raw_uuid, sizeof (uuid_t))) - { - return true; + if (m_data.GetU32(&offset, &type, 1) && + m_data.GetU64(&offset, &address, 1) && + m_data.CopyData(offset, sizeof(uuid_t), raw_uuid) != 0) { + uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t)); + return true; } } } @@ -5660,7 +5657,7 @@ + 100); // sharedCacheBaseAddress } } - uuid.SetBytes(sharedCacheUUID_address); + uuid = UUID::fromOptionalData(sharedCacheUUID_address, sizeof(uuid_t)); } } } else { @@ -5685,7 +5682,7 @@ dyld_process_info_get_cache (process_info, &sc_info); if (sc_info.cacheBaseAddress != 0) { base_addr = sc_info.cacheBaseAddress; - uuid.SetBytes (sc_info.cacheUUID); + uuid = UUID::fromOptionalData(sc_info.cacheUUID, sizeof(uuid_t)); } dyld_process_info_release (process_info); } Index: lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp +++ lldb/trunk/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -114,18 +114,9 @@ const CvRecordPdb70 *pdb70_uuid = nullptr; Status error = consumeObject(cv_record, pdb70_uuid); if (!error.Fail()) - return UUID(pdb70_uuid, sizeof(*pdb70_uuid)); - } else if (cv_signature == CvSignature::ElfBuildId) { - // ELF BuildID (found in Breakpad/Crashpad generated minidumps) - // - // This is variable-length, but usually 20 bytes - // as the binutils ld default is a SHA-1 hash. - // (We'll handle only 16 and 20 bytes signatures, - // matching LLDB support for UUIDs) - // - if (cv_record.size() == 16 || cv_record.size() == 20) - return UUID(cv_record.data(), cv_record.size()); - } + return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid)); + } else if (cv_signature == CvSignature::ElfBuildId) + return UUID::fromData(cv_record); return UUID(); } Index: lldb/trunk/source/Utility/DataExtractor.cpp =================================================================== --- lldb/trunk/source/Utility/DataExtractor.cpp +++ lldb/trunk/source/Utility/DataExtractor.cpp @@ -1093,24 +1093,6 @@ return offset; // Return the offset at which we ended up } -//---------------------------------------------------------------------- -// DumpUUID -// -// Dump out a UUID starting at 'offset' bytes into the buffer -//---------------------------------------------------------------------- -void DataExtractor::DumpUUID(Stream *s, offset_t offset) const { - if (s) { - const uint8_t *uuid_data = PeekData(offset, 16); - if (uuid_data) { - lldb_private::UUID uuid(uuid_data, 16); - uuid.Dump(s); - } else { - s->Printf("", - offset); - } - } -} - size_t DataExtractor::Copy(DataExtractor &dest_data) const { if (m_data_sp) { // we can pass along the SP to the data Index: lldb/trunk/source/Utility/UUID.cpp =================================================================== --- lldb/trunk/source/Utility/UUID.cpp +++ lldb/trunk/source/Utility/UUID.cpp @@ -21,29 +21,12 @@ using namespace lldb_private; -UUID::UUID() { Clear(); } +UUID::UUID(llvm::ArrayRef bytes) { + if (bytes.size() != 20 && bytes.size() != 16) + bytes = {}; -UUID::UUID(const UUID &rhs) { - SetBytes(rhs.m_uuid, rhs.m_num_uuid_bytes); -} - -UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) { - SetBytes(uuid_bytes, num_uuid_bytes); -} - -const UUID &UUID::operator=(const UUID &rhs) { - if (this != &rhs) { - m_num_uuid_bytes = rhs.m_num_uuid_bytes; - ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); - } - return *this; -} - -UUID::~UUID() {} - -void UUID::Clear() { - m_num_uuid_bytes = 16; - ::memset(m_uuid, 0, sizeof(m_uuid)); + m_num_uuid_bytes = bytes.size(); + std::memcpy(m_uuid, bytes.data(), bytes.size()); } std::string UUID::GetAsString(const char *separator) const { @@ -74,38 +57,6 @@ s->PutCString(GetAsString().c_str()); } -bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { - if (uuid_bytes) { - switch (num_uuid_bytes) { - case 20: - m_num_uuid_bytes = 20; - break; - case 16: - m_num_uuid_bytes = 16; - m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0; - break; - default: - // Unsupported UUID byte size - m_num_uuid_bytes = 0; - break; - } - - if (m_num_uuid_bytes > 0) { - ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes); - return true; - } - } - ::memset(m_uuid, 0, sizeof(m_uuid)); - return false; -} - -bool UUID::IsValid() const { - return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] || - m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] || - m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] || - m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19]; -} - static inline int xdigit_to_int(char ch) { ch = tolower(ch); if (ch >= 'a' && ch <= 'f') @@ -155,14 +106,15 @@ // Skip leading whitespace characters p = p.ltrim(); + ValueType bytes; uint32_t bytes_decoded = 0; llvm::StringRef rest = - UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes); + UUID::DecodeUUIDBytesFromString(p, bytes, bytes_decoded, num_uuid_bytes); // If we successfully decoded a UUID, return the amount of characters that // were consumed if (bytes_decoded == num_uuid_bytes) { - m_num_uuid_bytes = num_uuid_bytes; + *this = fromData(bytes, bytes_decoded); return str.size() - rest.size(); } Index: lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp =================================================================== --- lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -194,7 +194,8 @@ ASSERT_EQ(1u, result->size()); EXPECT_EQ("/foo/bar.so", result.getValue()[0].GetFileSpec().GetPath()); EXPECT_EQ(triple, result.getValue()[0].GetArchitecture().GetTriple()); - EXPECT_EQ(UUID("@ABCDEFGHIJKLMNO", 16), result.getValue()[0].GetUUID()); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNO", 16), + result.getValue()[0].GetUUID()); EXPECT_EQ(0u, result.getValue()[0].GetObjectOffset()); EXPECT_EQ(1234u, result.getValue()[0].GetObjectSize()); } @@ -218,7 +219,8 @@ ASSERT_EQ(1u, result->size()); EXPECT_EQ("/foo/bar.so", result.getValue()[0].GetFileSpec().GetPath()); EXPECT_EQ(triple, result.getValue()[0].GetArchitecture().GetTriple()); - EXPECT_EQ(UUID("@ABCDEFGHIJKLMNOPQRS", 20), result.getValue()[0].GetUUID()); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNOPQRS", 20), + result.getValue()[0].GetUUID()); EXPECT_EQ(0u, result.getValue()[0].GetObjectOffset()); EXPECT_EQ(1234u, result.getValue()[0].GetObjectSize()); } Index: lldb/trunk/unittests/Utility/UUIDTest.cpp =================================================================== --- lldb/trunk/unittests/Utility/UUIDTest.cpp +++ lldb/trunk/unittests/Utility/UUIDTest.cpp @@ -15,10 +15,10 @@ TEST(UUIDTest, RelationalOperators) { UUID empty; - UUID a16("1234567890123456", 16); - UUID b16("1234567890123457", 16); - UUID a20("12345678901234567890", 20); - UUID b20("12345678900987654321", 20); + UUID a16 = UUID::fromData("1234567890123456", 16); + UUID b16 = UUID::fromData("1234567890123457", 16); + UUID a20 = UUID::fromData("12345678901234567890", 20); + UUID b20 = UUID::fromData("12345678900987654321", 20); EXPECT_EQ(empty, empty); EXPECT_EQ(a16, a16); @@ -34,3 +34,40 @@ EXPECT_LT(a16, b16); EXPECT_GT(a20, b20); } + +TEST(UUIDTest, Validity) { + UUID empty; + std::vector zeroes(20, 0); + UUID a16 = UUID::fromData(zeroes.data(), 16); + UUID a20 = UUID::fromData(zeroes.data(), 20); + UUID a16_0 = UUID::fromOptionalData(zeroes.data(), 16); + UUID a20_0 = UUID::fromOptionalData(zeroes.data(), 20); + EXPECT_FALSE(empty); + EXPECT_TRUE(a16); + EXPECT_TRUE(a20); + EXPECT_FALSE(a16_0); + EXPECT_FALSE(a20_0); +} + +TEST(UUIDTest, SetFromStringRef) { + UUID u; + EXPECT_EQ(32u, u.SetFromStringRef("404142434445464748494a4b4c4d4e4f")); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNO", 16), u); + + EXPECT_EQ(36u, u.SetFromStringRef("40-41-42-43-4445464748494a4b4c4d4e4f")); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNO", 16), u); + + EXPECT_EQ(45u, u.SetFromStringRef( + "40-41-42-43-4445464748494a4b4c4d4e4f-50515253", 20)); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNOPQRS", 20), u); + + EXPECT_EQ(0u, u.SetFromStringRef("40-41-42-43-4445464748494a4b4c4d4e4f", 20)); + EXPECT_EQ(0u, u.SetFromStringRef("40xxxxx")); + EXPECT_EQ(0u, u.SetFromStringRef("")); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNOPQRS", 20), u) + << "uuid was changed by failed parse calls"; + + EXPECT_EQ( + 32u, u.SetFromStringRef("404142434445464748494a4b4c4d4e4f-50515253", 16)); + EXPECT_EQ(UUID::fromData("@ABCDEFGHIJKLMNO", 16), u); +}