[lldb] Contribute the GDB-remote packet history to diagnostics bundles (#210418)
Register a Diagnostics artifact provider from ProcessGDBRemote so a diagnostics bundle captures the GDB-remote packet history, the same data "process plugin packet history" prints.
This commit is contained in:
parent
ccd75bb4b9
commit
ab6ef5680e
4 changed files with 132 additions and 0 deletions
|
|
@ -33,6 +33,7 @@
|
|||
#include "lldb/Breakpoint/WatchpointAlgorithms.h"
|
||||
#include "lldb/Breakpoint/WatchpointResource.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Diagnostics.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/ModuleSpec.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
|
|
@ -102,6 +103,7 @@
|
|||
#include "llvm/ADT/ScopeExit.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/Chrono.h"
|
||||
#include "llvm/Support/ErrorExtras.h"
|
||||
#include "llvm/Support/FormatAdapters.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
|
|
@ -346,10 +348,29 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
|
|||
|
||||
m_use_g_packet_for_reading =
|
||||
GetGlobalPluginProperties().GetUseGPacketForReading();
|
||||
|
||||
// Contribute the packet history to diagnostics bundles, named with the
|
||||
// creation timestamp so files from different processes stay distinguishable.
|
||||
if (Diagnostics::Enabled()) {
|
||||
llvm::sys::TimePoint<> now = std::chrono::system_clock::now();
|
||||
std::string name = llvm::formatv(
|
||||
"gdb-remote-packet-history-{0:%Y-%m-%dT%H-%M-%S}.txt", now);
|
||||
m_diagnostics_artifact_id = Diagnostics::Instance().AddArtifactProvider(
|
||||
std::move(name), [this]() -> std::string {
|
||||
StreamString stream;
|
||||
DumpPluginHistory(stream);
|
||||
return stream.GetString().str();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor
|
||||
ProcessGDBRemote::~ProcessGDBRemote() {
|
||||
// Unregister before teardown so a concurrent collection can't run the
|
||||
// provider on a half-destroyed process.
|
||||
if (m_diagnostics_artifact_id && Diagnostics::Enabled())
|
||||
Diagnostics::Instance().RemoveArtifactProvider(*m_diagnostics_artifact_id);
|
||||
|
||||
// m_mach_process.UnregisterNotificationCallbacks (this);
|
||||
Clear();
|
||||
// We need to call finalize on the process before destroying ourselves to
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "lldb/Core/Diagnostics.h"
|
||||
#include "lldb/Core/LoadedModuleInfoList.h"
|
||||
#include "lldb/Core/ModuleSpec.h"
|
||||
#include "lldb/Core/ThreadSafeValue.h"
|
||||
|
|
@ -285,6 +286,9 @@ protected:
|
|||
GDBRemoteCommunicationClient m_gdb_comm;
|
||||
std::atomic<lldb::pid_t> m_debugserver_pid;
|
||||
|
||||
/// Registration for the packet-history diagnostics provider, if enabled.
|
||||
std::optional<Diagnostics::ArtifactProviderID> m_diagnostics_artifact_id;
|
||||
|
||||
std::optional<StringExtractorGDBRemote> m_last_stop_packet;
|
||||
std::recursive_mutex m_last_stop_packet_mutex;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ add_lldb_unittest(ProcessGdbRemoteTests
|
|||
GDBRemoteCommunicationServerTest.cpp
|
||||
GDBRemoteCommunicationTest.cpp
|
||||
GDBRemoteTestUtils.cpp
|
||||
ProcessGDBRemoteTest.cpp
|
||||
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
|
|
|
|||
106
lldb/unittests/Process/gdb-remote/ProcessGDBRemoteTest.cpp
Normal file
106
lldb/unittests/Process/gdb-remote/ProcessGDBRemoteTest.cpp
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
|
||||
#include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
|
||||
#include "Plugins/Platform/MacOSX/PlatformRemoteMacOSX.h"
|
||||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Diagnostics.h"
|
||||
#include "lldb/Host/FileSystem.h"
|
||||
#include "lldb/Host/HostInfo.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Platform.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/TargetList.h"
|
||||
#include "lldb/Utility/ArchSpec.h"
|
||||
#include "lldb/Utility/Listener.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Testing/Support/Error.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::process_gdb_remote;
|
||||
|
||||
namespace {
|
||||
class ProcessGDBRemoteDiagnosticsTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
FileSystem::Initialize();
|
||||
HostInfo::Initialize();
|
||||
PlatformMacOSX::Initialize();
|
||||
static std::once_flag g_debugger_initialize_flag;
|
||||
std::call_once(g_debugger_initialize_flag,
|
||||
[] { Debugger::Initialize(nullptr); });
|
||||
Diagnostics::Initialize();
|
||||
}
|
||||
void TearDown() override {
|
||||
Diagnostics::Terminate();
|
||||
PlatformMacOSX::Terminate();
|
||||
HostInfo::Terminate();
|
||||
FileSystem::Terminate();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// A ProcessGDBRemote registers a packet-history provider while alive and
|
||||
// unregisters it when destroyed.
|
||||
TEST_F(ProcessGDBRemoteDiagnosticsTest, PacketHistoryContributesToBundle) {
|
||||
ArchSpec arch("x86_64-apple-macosx-");
|
||||
Platform::SetHostPlatform(PlatformRemoteMacOSX::CreateInstance(true, &arch));
|
||||
|
||||
DebuggerSP debugger_sp = Debugger::CreateInstance();
|
||||
ASSERT_TRUE(debugger_sp);
|
||||
|
||||
PlatformSP platform_sp;
|
||||
TargetSP target_sp;
|
||||
debugger_sp->GetTargetList().CreateTarget(
|
||||
*debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);
|
||||
ASSERT_TRUE(target_sp);
|
||||
|
||||
ListenerSP listener_sp = Listener::MakeListener("test-listener");
|
||||
ProcessSP process_sp = ProcessGDBRemote::CreateInstance(
|
||||
target_sp, listener_sp, /*crash_file_path=*/nullptr,
|
||||
/*can_connect=*/true);
|
||||
ASSERT_TRUE(process_sp);
|
||||
|
||||
// The provider's file is named with a timestamp, so match it by prefix.
|
||||
auto has_packet_history = [](const std::vector<std::string> &files) {
|
||||
return llvm::any_of(files, [](llvm::StringRef f) {
|
||||
return f.starts_with("gdb-remote-packet-history-");
|
||||
});
|
||||
};
|
||||
ExecutionContext exe_ctx;
|
||||
|
||||
// Alive: the provider contributes the history file.
|
||||
{
|
||||
llvm::Expected<FileSpec> dir = Diagnostics::CreateUniqueDirectory();
|
||||
ASSERT_THAT_EXPECTED(dir, llvm::Succeeded());
|
||||
llvm::Expected<Diagnostics::Report> report =
|
||||
Diagnostics::Instance().Collect(*debugger_sp, exe_ctx, *dir);
|
||||
ASSERT_THAT_EXPECTED(report, llvm::Succeeded());
|
||||
EXPECT_TRUE(has_packet_history(report->attachments.files));
|
||||
llvm::sys::fs::remove_directories(dir->GetPath());
|
||||
}
|
||||
|
||||
// Destroyed: the provider is gone.
|
||||
process_sp.reset();
|
||||
{
|
||||
llvm::Expected<FileSpec> dir = Diagnostics::CreateUniqueDirectory();
|
||||
ASSERT_THAT_EXPECTED(dir, llvm::Succeeded());
|
||||
llvm::Expected<Diagnostics::Report> report =
|
||||
Diagnostics::Instance().Collect(*debugger_sp, exe_ctx, *dir);
|
||||
ASSERT_THAT_EXPECTED(report, llvm::Succeeded());
|
||||
EXPECT_FALSE(has_packet_history(report->attachments.files));
|
||||
llvm::sys::fs::remove_directories(dir->GetPath());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue