Skip to content

[lldb] Hoist UUID generation into the UUID class #133662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions lldb/include/lldb/Utility/UUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,27 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include <cstddef>
#include <cstdint>
#include <string>

namespace lldb_private {

class Stream;
class Stream;

/// Represents UUID's of various sizes. In all cases, a uuid of all zeros is
/// treated as an "Invalid UUID" marker, and the UUID created from such data
/// will return false for IsValid.
class UUID {
// Represents UUID's of various sizes. In all cases, a uuid of all zeros is
// treated as an "Invalid UUID" marker, and the UUID created from such data
// will return false for IsValid.
public:
UUID() = default;
/// Creates a uuid from the data pointed to by the bytes argument.

/// Create a uuid from the data pointed to by the bytes argument.
UUID(llvm::ArrayRef<uint8_t> bytes) : m_bytes(bytes) {
if (llvm::all_of(m_bytes, [](uint8_t b) { return b == 0; })) {
Clear();
}
}
}

// Reference:
Expand All @@ -50,13 +51,12 @@ class UUID {
/// Create a UUID from CvRecordPdb70.
UUID(CvRecordPdb70 debug_info);

/// Creates a UUID from the data pointed to by the bytes argument.
/// Create a UUID from the data pointed to by the bytes argument.
UUID(const void *bytes, uint32_t num_bytes) {
if (!bytes)
return;
*this
= UUID(llvm::ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(bytes),
num_bytes));
*this = UUID(llvm::ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(bytes), num_bytes));
}

void Clear() { m_bytes.clear(); }
Expand All @@ -67,7 +67,7 @@ class UUID {

explicit operator bool() const { return IsValid(); }
bool IsValid() const { return !m_bytes.empty(); }

std::string GetAsString(llvm::StringRef separator = "-") const;

bool SetFromStringRef(llvm::StringRef str);
Expand All @@ -88,6 +88,9 @@ class UUID {
DecodeUUIDBytesFromString(llvm::StringRef str,
llvm::SmallVectorImpl<uint8_t> &uuid_bytes);

/// Create a random UUID.
static UUID Generate(uint32_t num_bytes = 16);

private:
// GNU ld generates 20-byte build-ids. Size chosen to avoid heap allocations
// for this case.
Expand Down
18 changes: 6 additions & 12 deletions lldb/source/Core/Telemetry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Telemetry.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/UUID.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Telemetry/Telemetry.h"
#include <chrono>
#include <cstdlib>
#include <ctime>
#include <memory>
#include <string>
#include <utility>
Expand All @@ -37,18 +40,9 @@ static uint64_t ToNanosec(const SteadyTimePoint Point) {
// This reduces the chances of getting the same UUID, even when the same
// user runs the two copies of binary at the same time.
static std::string MakeUUID() {
uint8_t random_bytes[16];
std::string randomString = "_";
if (auto ec = llvm::getRandomBytes(random_bytes, 16)) {
LLDB_LOG(GetLog(LLDBLog::Object),
"Failed to generate random bytes for UUID: {0}", ec.message());
} else {
randomString = UUID(random_bytes).GetAsString();
}

return llvm::formatv(
"{0}_{1}", randomString,
std::chrono::steady_clock::now().time_since_epoch().count());
auto timestmap = std::chrono::steady_clock::now().time_since_epoch().count();
UUID uuid = UUID::Generate();
return llvm::formatv("{0}_{1}", uuid.GetAsString(), timestmap);
}

void LLDBBaseTelemetryInfo::serialize(Serializer &serializer) const {
Expand Down
20 changes: 20 additions & 0 deletions lldb/source/Utility/UUID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/RandomNumberGenerator.h"

#include <cctype>
#include <chrono>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <random>

using namespace lldb_private;

Expand Down Expand Up @@ -110,3 +115,18 @@ bool UUID::SetFromStringRef(llvm::StringRef str) {
*this = UUID(bytes);
return true;
}

UUID UUID::Generate(uint32_t num_bytes) {
llvm::SmallVector<uint8_t, 20> bytes(num_bytes);
auto ec = llvm::getRandomBytes(bytes.data(), bytes.size());

// If getRandomBytes failed, fall back to a lower entropy source.
if (ec) {
auto seed = std::chrono::steady_clock::now().time_since_epoch().count();
std::independent_bits_engine<std::default_random_engine, CHAR_BIT, uint8_t>
engine(seed);
std::generate(bytes.begin(), bytes.end(), std::ref(engine));
}

return UUID(bytes);
}
12 changes: 10 additions & 2 deletions lldb/unittests/Utility/UUIDTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"

#include "lldb/Utility/UUID.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"

using namespace lldb_private;

Expand Down Expand Up @@ -86,3 +86,11 @@ TEST(UUIDTest, StringConverion) {
EXPECT_EQ("40414243-4445-4647-4849-4A4B4C4D4E4F-50515253",
UUID("@ABCDEFGHIJKLMNOPQRS", 20).GetAsString());
}

TEST(UUIDTest, Generate) {
UUID u16 = UUID::Generate();
EXPECT_EQ(u16.GetBytes().size(), 16UL);

UUID u20 = UUID::Generate(20);
EXPECT_EQ(u20.GetBytes().size(), 20UL);
}
Loading