summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
diff options
context:
space:
mode:
authorJonas Devlieghere <jonas@devlieghere.com>2018-11-13 19:18:16 +0000
committerJonas Devlieghere <jonas@devlieghere.com>2018-11-13 19:18:16 +0000
commit9e046f02e34fbb93eea1bd8b4136da7fd8d06612 (patch)
treea5fcd26ec570e8a3262ab7ea7e312930e9014cdd /lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
parent3bea50aeb35704798aefa9acbb8973c7864f3732 (diff)
downloadbcm5719-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.cpp134
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, &reg_offset,
- &abi_sp](const XMLNode &reg_node) -> bool {
+ "reg",
+ [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset,
+ &abi_sp](const XMLNode &reg_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
OpenPOWER on IntegriCloud