augusto2112 updated this revision to Diff 329385.
augusto2112 marked 7 inline comments as done and an inline comment as not done.
augusto2112 added a comment.
Address comments
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D96176/new/
https://reviews.llvm.org/D96176
Files:
lldb/include/lldb/Target/Process.h
lldb/include/lldb/Utility/StringExtractorGDBRemote.h
lldb/include/lldb/lldb-enumerations.h
lldb/source/Commands/CommandObjectProcess.cpp
lldb/source/Commands/Options.td
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
lldb/source/Utility/StringExtractorGDBRemote.cpp
Index: lldb/source/Utility/StringExtractorGDBRemote.cpp
===================================================================
--- lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -200,7 +200,10 @@
if (PACKET_MATCHES("qHostInfo"))
return eServerPacketType_qHostInfo;
break;
-
+ case 'J':
+ if (PACKET_MATCHES("qJAttachSupported"))
+ return eServerPacketType_qJAttachSupported;
+ break;
case 'K':
if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
return eServerPacketType_qKillSpawnedProcess;
@@ -294,6 +297,8 @@
break;
case 'j':
+ if (PACKET_STARTS_WITH("jAttach:"))
+ return eServerPacketType_jAttach;
if (PACKET_STARTS_WITH("jModulesInfo:"))
return eServerPacketType_jModulesInfo;
if (PACKET_MATCHES("jSignalsInfo"))
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1160,41 +1160,72 @@
return error;
}
+static StreamGDBRemote MakeJAttachPacket(const char *process_name,
+ const ProcessAttachInfo &attach_info) {
+
+ StreamString json_string;
+ json_string.PutCString("jAttach:");
+
+ StructuredData::Dictionary json_packet;
+ json_packet.AddStringItem("process_name", process_name);
+
+ if (auto interval = attach_info.GetWaitForLaunchInterval())
+ json_packet.AddIntegerItem("waitfor-interval-usec", interval->count());
+
+ if (auto duration = attach_info.GetWaitForLaunchDuration())
+ json_packet.AddIntegerItem("waitfor-duration-sec", duration->count());
+
+ json_packet.AddBooleanItem("include-existing",
+ !attach_info.GetIgnoreExisting());
+
+ json_packet.Dump(json_string, false);
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+ return escaped_packet;
+}
+
Status ProcessGDBRemote::DoAttachToProcessWithName(
const char *process_name, const ProcessAttachInfo &attach_info) {
Status error;
// Clear out and clean up from any current state
Clear();
- if (process_name && process_name[0]) {
- error = EstablishConnectionIfNeeded(attach_info);
- if (error.Success()) {
- StreamString packet;
+ if (!process_name || !process_name[0])
+ return error;
- m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+ error = EstablishConnectionIfNeeded(attach_info);
+ if (!error.Success()) {
+ SetExitStatus(-1, error.AsCString());
+ return error;
+ }
- if (attach_info.GetWaitForLaunch()) {
- if (!m_gdb_comm.GetVAttachOrWaitSupported()) {
+ m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+ if (attach_info.GetWaitForLaunch() && m_gdb_comm.GetJAttachSupported()) {
+ auto gdb_stream = MakeJAttachPacket(process_name, attach_info);
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue,
+ new EventDataBytes(gdb_stream.GetString().data(),
+ gdb_stream.GetSize()));
+ } else {
+ StreamString packet;
+ if (attach_info.GetWaitForLaunch()) {
+ if (!m_gdb_comm.GetVAttachOrWaitSupported()) {
+ packet.PutCString("vAttachWait");
+ } else {
+ if (attach_info.GetIgnoreExisting())
packet.PutCString("vAttachWait");
- } else {
- if (attach_info.GetIgnoreExisting())
- packet.PutCString("vAttachWait");
- else
- packet.PutCString("vAttachOrWait");
- }
- } else
- packet.PutCString("vAttachName");
- packet.PutChar(';');
- packet.PutBytesAsRawHex8(process_name, strlen(process_name),
- endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
-
- m_async_broadcaster.BroadcastEvent(
- eBroadcastBitAsyncContinue,
- new EventDataBytes(packet.GetString().data(), packet.GetSize()));
-
+ else
+ packet.PutCString("vAttachOrWait");
+ }
} else
- SetExitStatus(-1, error.AsCString());
+ packet.PutCString("vAttachName");
+ packet.PutChar(';');
+ packet.PutBytesAsRawHex8(process_name, strlen(process_name),
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue,
+ new EventDataBytes(packet.GetString().data(), packet.GetSize()));
}
return error;
}
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -65,10 +65,26 @@
/// with a given name and attaching llgs to that via the configured
/// Platform.
///
+ /// \param process_name
+ /// The process we'd like to attach to.
+ /// \param include_existing
+ /// Look for the process we'd like to attach to among the processes
+ /// already running.
+ /// \param custom_polling_interval
+ /// The polling interval the function should use in microseconds. Defaults
+ /// to 1000.
+ /// \param timeout
+ /// How long we should look for the process in seconds. Defaults to
+ /// infinity.
+ ///
/// \return
/// An Status object indicating the success or failure of the
/// attach operation.
- Status AttachWaitProcess(llvm::StringRef process_name, bool include_existing);
+ Status AttachWaitProcess(
+ llvm::StringRef process_name, bool include_existing,
+ llvm::Optional<std::chrono::microseconds> custom_polling_interval =
+ llvm::None,
+ llvm::Optional<std::chrono::seconds> timeout = llvm::None);
// NativeProcessProtocol::NativeDelegate overrides
void InitializeDelegate(NativeProcessProtocol *process) override;
@@ -187,6 +203,10 @@
PacketResult Handle_vAttachOrWait(StringExtractorGDBRemote &packet);
+ PacketResult Handle_qJAttachSupported(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_jAttach(StringExtractorGDBRemote &packet);
+
PacketResult Handle_D(StringExtractorGDBRemote &packet);
PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet);
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -168,6 +168,12 @@
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_vAttachOrWait,
&GDBRemoteCommunicationServerLLGS::Handle_vAttachOrWait);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qJAttachSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_qJAttachSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jAttach,
+ &GDBRemoteCommunicationServerLLGS::Handle_jAttach);
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_vCont,
&GDBRemoteCommunicationServerLLGS::Handle_vCont);
@@ -344,10 +350,13 @@
}
Status GDBRemoteCommunicationServerLLGS::AttachWaitProcess(
- llvm::StringRef process_name, bool include_existing) {
+ llvm::StringRef process_name, bool include_existing,
+ llvm::Optional<std::chrono::microseconds> custom_polling_interval,
+ llvm::Optional<std::chrono::seconds> timeout) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- std::chrono::milliseconds polling_interval = std::chrono::milliseconds(1);
+ auto polling_interval =
+ custom_polling_interval.getValueOr(std::chrono::microseconds(1000));
// Create the matcher used to search the process list.
ProcessInstanceInfoList exclusion_list;
@@ -376,8 +385,13 @@
return false;
};
+ auto target = std::chrono::steady_clock::now();
+ if (timeout.hasValue())
+ target = std::chrono::steady_clock::now() +
+ std::chrono::seconds(timeout.getValue());
+
ProcessInstanceInfoList loop_process_list;
- while (true) {
+ do {
loop_process_list.clear();
if (Host::FindProcesses(match_info, loop_process_list)) {
// Remove all the elements that are in the exclusion list.
@@ -407,9 +421,14 @@
}
}
// No matches, we have not found the process. Sleep until next poll.
- LLDB_LOG(log, "sleep {0} seconds", polling_interval);
+ LLDB_LOG(log, "sleep for {0}", polling_interval);
std::this_thread::sleep_for(polling_interval);
- }
+ } while (!timeout.hasValue() || std::chrono::steady_clock::now() < target);
+
+ // Timed out
+ Status error;
+ error.SetErrorString("attach timed out.");
+ return error;
}
void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
@@ -3332,6 +3351,55 @@
return SendStopReasonForState(m_debugged_process_up->GetState());
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_qJAttachSupported(
+ StringExtractorGDBRemote &packet) {
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jAttach(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ if (!packet.ConsumeFront("jAttach:"))
+ return SendIllFormedResponse(packet, "jAttach: Ill formed packet ");
+
+ auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+ if (!json_object ||
+ json_object->GetType() != lldb::eStructuredDataTypeDictionary)
+ return SendIllFormedResponse(packet, "jAttach: Ill formed packet ");
+
+ auto *json_dict = json_object->GetAsDictionary();
+
+ StringRef process_name;
+ llvm::Optional<std::chrono::microseconds> polling_interval;
+ llvm::Optional<std::chrono::seconds> polling_duration;
+ bool include_existing = false;
+ uint64_t temp;
+
+ json_dict->GetValueForKeyAsString("process_name", process_name);
+ json_dict->GetValueForKeyAsBoolean("include-existing", include_existing);
+ if (json_dict->GetValueForKeyAsInteger("waitfor-interval-usec", temp))
+ polling_interval = std::chrono::microseconds(temp);
+ if (json_dict->GetValueForKeyAsInteger("waitfor-duration-sec", temp))
+ polling_duration = std::chrono::seconds(temp);
+
+ LLDB_LOG(log, "attempting to attach to process named '{0}'", process_name);
+
+ Status error = AttachWaitProcess(process_name, include_existing,
+ polling_interval, polling_duration);
+ if (error.Fail()) {
+ LLDB_LOG(log, "failed to attach to process named '{0}': {1}", process_name,
+ error);
+ return SendErrorResponse(error);
+ }
+
+ // Notify we attached by sending a stop packet.
+ return SendStopReasonForState(m_debugged_process_up->GetState());
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -257,6 +257,8 @@
bool GetVAttachOrWaitSupported();
+ bool GetJAttachSupported();
+
bool GetSyncThreadStateSupported();
void ResetDiscoverableSettings(bool did_exec);
@@ -542,6 +544,7 @@
LazyBool m_supports_detach_stay_stopped;
LazyBool m_watchpoints_trigger_after_instruction;
LazyBool m_attach_or_wait_reply;
+ LazyBool m_j_attach_wait_reply;
LazyBool m_prepare_for_reg_writing_reply;
LazyBool m_supports_p;
LazyBool m_supports_x;
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -74,6 +74,7 @@
m_supports_detach_stay_stopped(eLazyBoolCalculate),
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
+ m_j_attach_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply(eLazyBoolCalculate),
m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate),
m_avoid_g_packets(eLazyBoolCalculate),
@@ -257,6 +258,20 @@
return m_attach_or_wait_reply == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetJAttachSupported() {
+ if (m_j_attach_wait_reply == eLazyBoolCalculate) {
+ m_j_attach_wait_reply = eLazyBoolNo;
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qJAttachSupported", response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ m_j_attach_wait_reply = eLazyBoolYes;
+ }
+ }
+ return m_j_attach_wait_reply == eLazyBoolYes;
+}
+
bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) {
m_prepare_for_reg_writing_reply = eLazyBoolNo;
@@ -291,6 +306,7 @@
m_supports_memory_region_info = eLazyBoolCalculate;
m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
m_attach_or_wait_reply = eLazyBoolCalculate;
+ m_j_attach_wait_reply = eLazyBoolCalculate;
m_avoid_g_packets = eLazyBoolCalculate;
m_supports_qXfer_auxv_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
Index: lldb/source/Commands/Options.td
===================================================================
--- lldb/source/Commands/Options.td
+++ lldb/source/Commands/Options.td
@@ -688,6 +688,12 @@
Group<2>, Desc<"Include existing processes when doing attach -w.">;
def process_attach_waitfor : Option<"waitfor", "w">, Group<2>,
Desc<"Wait for the process with <process-name> to launch.">;
+ def process_attach_waitfor_interval : Option<"waitfor-interval", "I">,
+ Group<2>, Arg<"WaitforInterval">,
+ Desc<"The interval that waitfor uses to poll the list of processes.">;
+ def process_attach_waitfor_duration : Option<"waitfor-duration", "d">,
+ Group<2>, Arg<"WaitforDuration">,
+ Desc<"The interval that waitfor uses to poll the list of processes.">;
}
let Command = "process continue" in {
Index: lldb/source/Commands/CommandObjectProcess.cpp
===================================================================
--- lldb/source/Commands/CommandObjectProcess.cpp
+++ lldb/source/Commands/CommandObjectProcess.cpp
@@ -307,6 +307,27 @@
attach_info.SetIgnoreExisting(false);
break;
+ case 'I': {
+ uint64_t interval;
+ if (option_arg.getAsInteger(0, interval)) {
+ error.SetErrorStringWithFormat("invalid polling interval '%s'",
+ option_arg.str().c_str());
+ } else {
+ attach_info.SetWaitForLaunchInterval(
+ std::chrono::microseconds(interval));
+ }
+ break;
+ }
+ case 'd': {
+ uint64_t duration;
+ if (option_arg.getAsInteger(0, duration)) {
+ error.SetErrorStringWithFormat("invalid duration '%s'",
+ option_arg.str().c_str());
+ } else {
+ attach_info.SetWaitForLaunchDuration(std::chrono::seconds(duration));
+ }
+ break;
+ }
default:
llvm_unreachable("Unimplemented option");
}
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -597,6 +597,8 @@
eArgTypeCommand,
eArgTypeColumnNum,
eArgTypeModuleUUID,
+ eArgTypeWaitforInterval,
+ eArgTypeWaitforDuration,
eArgTypeLastArg // Always keep this entry as the last entry in this
// enumeration!!
};
Index: lldb/include/lldb/Utility/StringExtractorGDBRemote.h
===================================================================
--- lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -122,6 +122,7 @@
eServerPacketType_qThreadExtraInfo,
eServerPacketType_qThreadStopInfo,
eServerPacketType_qVAttachOrWaitSupported,
+ eServerPacketType_qJAttachSupported,
eServerPacketType_qWatchpointSupportInfo,
eServerPacketType_qWatchpointSupportInfoSupported,
eServerPacketType_qXfer,
@@ -132,6 +133,7 @@
eServerPacketType_vAttach,
eServerPacketType_vAttachWait,
eServerPacketType_vAttachOrWait,
+ eServerPacketType_jAttach,
eServerPacketType_vAttachName,
eServerPacketType_vCont,
eServerPacketType_vCont_actions, // vCont?
Index: lldb/include/lldb/Target/Process.h
===================================================================
--- lldb/include/lldb/Target/Process.h
+++ lldb/include/lldb/Target/Process.h
@@ -130,6 +130,24 @@
void SetWaitForLaunch(bool b) { m_wait_for_launch = b; }
+ llvm::Optional<std::chrono::microseconds> GetWaitForLaunchInterval() const {
+ return m_wait_for_launch_interval;
+ }
+
+ void SetWaitForLaunchInterval(
+ llvm::Optional<std::chrono::microseconds> new_interval) {
+ m_wait_for_launch_interval = new_interval;
+ }
+
+ llvm::Optional<std::chrono::seconds> GetWaitForLaunchDuration() const {
+ return m_wait_for_launch_duration;
+ }
+
+ void
+ SetWaitForLaunchDuration(llvm::Optional<std::chrono::seconds> new_duration) {
+ m_wait_for_launch_duration = new_duration;
+ }
+
bool GetAsync() const { return m_async; }
void SetAsync(bool b) { m_async = b; }
@@ -159,6 +177,8 @@
m_plugin_name.clear();
m_resume_count = 0;
m_wait_for_launch = false;
+ m_wait_for_launch_interval = llvm::None;
+ m_wait_for_launch_duration = llvm::None;
m_ignore_existing = true;
m_continue_once_attached = false;
}
@@ -198,6 +218,8 @@
std::string m_plugin_name;
uint32_t m_resume_count; // How many times do we resume after launching
bool m_wait_for_launch;
+ llvm::Optional<std::chrono::microseconds> m_wait_for_launch_interval;
+ llvm::Optional<std::chrono::seconds> m_wait_for_launch_duration;
bool m_ignore_existing;
bool m_continue_once_attached; // Supports the use-case scenario of
// immediately continuing the process once
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits