diff options
author | Jonas Devlieghere <jonas@devlieghere.com> | 2018-11-13 19:18:16 +0000 |
---|---|---|
committer | Jonas Devlieghere <jonas@devlieghere.com> | 2018-11-13 19:18:16 +0000 |
commit | 9e046f02e34fbb93eea1bd8b4136da7fd8d06612 (patch) | |
tree | a5fcd26ec570e8a3262ab7ea7e312930e9014cdd /lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | |
parent | 3bea50aeb35704798aefa9acbb8973c7864f3732 (diff) | |
download | bcm5719-llvm-9e046f02e34fbb93eea1bd8b4136da7fd8d06612.tar.gz bcm5719-llvm-9e046f02e34fbb93eea1bd8b4136da7fd8d06612.zip |
Add GDB remote packet reproducer.
llvm-svn: 346780
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 134 |
1 files changed, 111 insertions, 23 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 85c40cef41f..31968de3902 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -65,6 +65,7 @@ #include "lldb/Utility/Args.h" #include "lldb/Utility/CleanUp.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Reproducer.h" #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" @@ -85,6 +86,7 @@ #include "llvm/Support/raw_ostream.h" #define DEBUGSERVER_BASENAME "debugserver" +using namespace llvm; using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; @@ -104,7 +106,7 @@ void DumpProcessGDBRemotePacketHistory(void *p, const char *path) { if (error.Success()) ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm); } -} +} // namespace lldb namespace { @@ -155,7 +157,37 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() { return g_settings_sp; } -} // anonymous namespace end +class ProcessGDBRemoteProvider : public repro::Provider { +public: + ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) { + m_info.name = "gdb-remote"; + m_info.files.push_back("gdb-remote.yaml"); + } + + raw_ostream *GetHistoryStream() { + FileSpec history_file = + GetDirectory().CopyByAppendingPathComponent("gdb-remote.yaml"); + + std::error_code EC; + m_stream_up = make_unique<raw_fd_ostream>(history_file.GetPath(), EC, + sys::fs::OpenFlags::F_None); + return m_stream_up.get(); + } + + void SetCallback(std::function<void()> callback) { + m_callback = std::move(callback); + } + + void Keep() override { m_callback(); } + + void Discard() override { m_callback(); } + +private: + std::function<void()> m_callback; + std::unique_ptr<raw_fd_ostream> m_stream_up; +}; + +} // namespace // TODO Randomly assigning a port is unsafe. We should get an unused // ephemeral port from the kernel and make sure we reserve it before passing it @@ -256,8 +288,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_addr_to_mmap_size(), m_thread_create_bp_sp(), m_waiting_for_attach(false), m_destroy_tried_resuming(false), m_command_sp(), m_breakpoint_pc_offset(0), - m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false), - m_erased_flash_ranges() { + m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false), + m_allow_flash_writes(false), m_erased_flash_ranges() { m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, @@ -265,6 +297,16 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit"); + repro::Generator *generator = repro::Reproducer::Instance().GetGenerator(); + if (generator) { + ProcessGDBRemoteProvider &provider = + generator->CreateProvider<ProcessGDBRemoteProvider>(); + // Set the history stream to the stream owned by the provider. + m_gdb_comm.SetHistoryStream(provider.GetHistoryStream()); + // Make sure to clear the stream again when we're finished. + provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); }); + } + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC)); const uint32_t async_event_mask = @@ -1057,9 +1099,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { if (log) log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, " "using %s %s", - __FUNCTION__, process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", process_arch.GetTriple().getTriple().c_str() ? process_arch.GetTriple().getTriple().c_str() : "<null>"); @@ -1068,9 +1111,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { if (log) log->Printf("ProcessGDBRemote::%s gdb-remote did not have process " "architecture, using gdb-remote host architecture %s %s", - __FUNCTION__, process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", process_arch.GetTriple().getTriple().c_str() ? process_arch.GetTriple().getTriple().c_str() : "<null>"); @@ -1082,9 +1126,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { if (log) log->Printf( "ProcessGDBRemote::%s analyzing target arch, currently %s %s", - __FUNCTION__, target_arch.GetArchitectureName() - ? target_arch.GetArchitectureName() - : "<null>", + __FUNCTION__, + target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", target_arch.GetTriple().getTriple().c_str() ? target_arch.GetTriple().getTriple().c_str() : "<null>"); @@ -1104,9 +1149,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { if (log) log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, " "setting target arch to %s %s", - __FUNCTION__, process_arch.GetArchitectureName() - ? process_arch.GetArchitectureName() - : "<null>", + __FUNCTION__, + process_arch.GetArchitectureName() + ? process_arch.GetArchitectureName() + : "<null>", process_arch.GetTriple().getTriple().c_str() ? process_arch.GetTriple().getTriple().c_str() : "<null>"); @@ -1134,9 +1180,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { if (log) log->Printf("ProcessGDBRemote::%s final target arch after " "adjustments for remote architecture: %s %s", - __FUNCTION__, target_arch.GetArchitectureName() - ? target_arch.GetArchitectureName() - : "<null>", + __FUNCTION__, + target_arch.GetArchitectureName() + ? target_arch.GetArchitectureName() + : "<null>", target_arch.GetTriple().getTriple().c_str() ? target_arch.GetTriple().getTriple().c_str() : "<null>"); @@ -3377,6 +3424,43 @@ Status ProcessGDBRemote::DoSignal(int signo) { return error; } +Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) { + if (!loader) + return Status("No loader provided."); + + auto provider_info = loader->GetProviderInfo("gdb-remote"); + if (!provider_info) + return Status("No provider for gdb-remote."); + + if (provider_info->files.empty()) + return Status("Provider for gdb-remote contains no files."); + + // Construct replay history path. + FileSpec history_file(loader->GetDirectory()); + history_file.AppendPathComponent(provider_info->files.front()); + + // Enable replay mode. + m_replay_mode = true; + + // Load replay history. + if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file)) + return Status("Unable to load replay history"); + + // Make a local connection. + if (auto error = GDBRemoteCommunication::ConnectLocally(m_gdb_comm, + m_gdb_replay_server)) + return Status("Unable to connect to replay server"); + + // Start server thread. + m_gdb_replay_server.StartAsyncThread(); + + // Start client thread. + StartAsyncThread(); + + // Do the usual setup. + return ConnectToDebugserver(""); +} + Status ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { // Make sure we aren't already connected? @@ -3387,6 +3471,9 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) { if (platform_sp && !platform_sp->IsHost()) return Status("Lost debug server connection"); + if (repro::Loader *loader = repro::Reproducer::Instance().GetLoader()) + return ConnectToReplayServer(loader); + auto error = LaunchAndConnectToDebugserver(process_info); if (error.Fail()) { const char *error_string = error.AsCString(); @@ -3496,7 +3583,7 @@ bool ProcessGDBRemote::MonitorDebugserverProcess( bool exited, // True if the process did exit int signo, // Zero for no signal int exit_status // Exit value of process if signal is zero - ) { +) { // "debugserver_pid" argument passed in is the process ID for debugserver // that we are tracking... Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); @@ -4268,8 +4355,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, return false; feature_node.ForEachChildElementWithName( - "reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, - &abi_sp](const XMLNode ®_node) -> bool { + "reg", + [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, + &abi_sp](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; ConstString reg_name; @@ -4431,7 +4519,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, return true; } -} // namespace {} +} // namespace // query the target of gdb-remote for extended target information return: // 'true' on success |