40#include "llvm/Support/Threading.h"
42#define USEC_PER_SEC 1000000
57#define LLDB_PROPERTIES_processkdp
58#include "ProcessKDPProperties.inc"
61#define LLDB_PROPERTIES_processkdp
62#include "ProcessKDPPropertiesEnum.inc"
67 static llvm::StringRef GetSettingName() {
72 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
73 m_collection_sp->Initialize(g_processkdp_properties);
76 ~PluginProperties()
override =
default;
78 uint64_t GetPacketTimeout() {
79 const uint32_t idx = ePropertyKDPPacketTimeout;
80 return GetPropertyAtIndexAs<uint64_t>(
81 idx, g_processkdp_properties[idx].default_uint_value);
88 static PluginProperties g_settings;
95 return "KDP Remote protocol based debugging plug-in for darwin kernel "
108 if (crash_file_path == NULL)
109 process_sp = std::make_shared<ProcessKDP>(target_sp, listener_sp);
114 if (plugin_specified_by_name)
118 Module *exe_module = target_sp->GetExecutableModulePointer();
121 switch (triple_ref.getOS()) {
122 case llvm::Triple::Darwin:
124 case llvm::Triple::MacOSX:
125 case llvm::Triple::IOS:
126 case llvm::Triple::TvOS:
127 case llvm::Triple::WatchOS:
128 case llvm::Triple::XROS:
129 if (triple_ref.getVendor() == llvm::Triple::Apple) {
146 :
Process(target_sp, listener_sp),
147 m_comm(
"lldb.process.kdp-remote.communication"),
148 m_async_broadcaster(NULL,
"lldb.process.kdp-remote.async-broadcaster"),
150 m_kernel_thread_wp() {
152 "async thread should exit");
154 "async thread continue");
155 const uint64_t timeout_seconds =
157 if (timeout_seconds > 0)
173 error.SetErrorString(
"launching not supported in kdp-remote plug-in");
179 error.SetErrorString(
180 "attaching to a by process ID not supported in kdp-remote plug-in");
185 bool wait_for_launch) {
187 error.SetErrorString(
188 "attaching to a by process name not supported in kdp-remote plug-in");
198 arch.
GetTriple().setVendor(llvm::Triple::UnknownVendor);
199 arch.
GetTriple().setVendorName(llvm::StringRef());
214 if (remote_url.empty()) {
215 error.SetErrorStringWithFormat(
"empty connection URL");
219 std::unique_ptr<ConnectionFileDescriptor> conn_up(
224 const uint32_t max_retry_count = 1;
225 for (uint32_t retry_count = 0; retry_count < max_retry_count;
233 if (conn_up->IsConnected()) {
235 static_cast<const TCPSocket &
>(*conn_up->GetReadObject());
238 if (reply_port != 0) {
243 "Greetings from LLDB...")) {
274 module_spec.
GetUUID() = kernel_uuid;
301 if (module_sp.get() && module_sp->GetObjectFile()) {
307 if (exe_module_sp.get() != module_sp.get())
329 async_strm_sp->Printf(
"Version: %s\n", cstr);
330 async_strm_sp->Flush();
340 error.SetErrorString(
"KDP_REATTACH failed");
343 error.SetErrorString(
"KDP_REATTACH failed");
346 error.SetErrorString(
"invalid reply port from UDP connection");
350 error.SetErrorStringWithFormat(
"failed to connect to '%s'",
351 remote_url.str().c_str());
363 error.SetErrorString(
"launching not supported in kdp-remote plug-in");
371 error.SetErrorString(
372 "attach to process by ID is not supported in kdp remote debugging");
380 error.SetErrorString(
381 "attach to process by name is not supported in kdp remote debugging");
389 LLDB_LOGF(log,
"ProcessKDP::DidAttach()");
417 if (kernel_thread_sp) {
419 kernel_thread_sp->GetTemporaryResumeState();
421 LLDB_LOGF(log,
"ProcessKDP::DoResume() thread_resume_state = %s",
423 switch (thread_resume_state) {
427 LLDB_LOGF(log,
"ProcessKDP::DoResume() = suspended???");
432 kernel_thread_sp->GetRegisterContext());
437 "ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep (true);");
438 reg_ctx_sp->HardwareSingleStep(
true);
441 error.SetErrorStringWithFormat(
442 "KDP thread 0x%llx has no register context",
443 kernel_thread_sp->GetID());
449 kernel_thread_sp->GetRegisterContext());
452 LLDB_LOGF(log,
"ProcessKDP::DoResume () reg_ctx_sp->HardwareSingleStep "
454 reg_ctx_sp->HardwareSingleStep(
false);
457 error.SetErrorStringWithFormat(
458 "KDP thread 0x%llx has no register context",
459 kernel_thread_sp->GetID());
465 llvm_unreachable(
"invalid thread resume state");
470 LLDB_LOGF(log,
"ProcessKDP::DoResume () sending resume");
476 error.SetErrorString(
"KDP resume failed");
478 error.SetErrorString(
"kernel thread is suspended");
490 thread_sp = std::make_shared<ThreadKDP>(*
this,
g_kernel_tid);
510 return new_thread_list.
GetSize(
false) > 0;
529 error.SetErrorString(
"KDP cannot interrupt a running kernel");
538 LLDB_LOGF(log,
"ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
551 "ProcessKDP::DoDetach() detach packet sent successfully");
554 "ProcessKDP::DoDetach() connection channel shutdown failed");
571 bool keep_stopped =
false;
584 uint8_t *data_buffer = (uint8_t *)buf;
586 const size_t max_read_size = 512;
587 size_t total_bytes_read = 0;
590 while (total_bytes_read < size) {
591 size_t bytes_to_read_this_request = size - total_bytes_read;
592 if (bytes_to_read_this_request > max_read_size) {
593 bytes_to_read_this_request = max_read_size;
596 addr + total_bytes_read, data_buffer + total_bytes_read,
597 bytes_to_read_this_request,
error);
598 total_bytes_read += bytes_read;
599 if (
error.Fail() || bytes_read == 0) {
600 return total_bytes_read;
604 return total_bytes_read;
606 error.SetErrorString(
"not connected");
614 error.SetErrorString(
"not connected");
620 error.SetErrorString(
621 "memory allocation not supported in kdp remote debugging");
627 error.SetErrorString(
628 "memory deallocation not supported in kdp remote debugging");
634 return Status(
"Hardware breakpoints are not supported.");
643 error.SetErrorString(
"KDP set breakpoint failed");
664 error.SetErrorString(
"KDP remove breakpoint failed");
679 error.SetErrorString(
680 "sending signals is not supported in kdp remote debugging");
685 static llvm::once_flag g_once_flag;
687 llvm::call_once(g_once_flag, []() {
698 debugger, PluginProperties::GetSettingName())) {
699 const bool is_global_setting =
true;
702 "Properties for the kdp-remote process plug-in.", is_global_setting);
709 LLDB_LOGF(log,
"ProcessKDP::StartAsyncThread ()");
715 "<lldb.process.kdp-remote.async>", [
this] {
return AsyncThread(); });
718 "failed to launch host thread: {0}");
728 LLDB_LOGF(log,
"ProcessKDP::StopAsyncThread ()");
742 "ProcessKDP::AsyncThread(pid = %" PRIu64
") thread starting...",
747 const uint32_t desired_event_mask =
750 if (listener_sp->StartListeningForEvents(
755 "ProcessKDP::AsyncThread (pid = %" PRIu64
756 ") listener.WaitForEvent (NULL, event_sp)...",
758 if (listener_sp->GetEvent(event_sp, std::nullopt)) {
759 uint32_t event_type = event_sp->GetType();
761 "ProcessKDP::AsyncThread (pid = %" PRIu64
762 ") Got an event of type: %d...",
768 bool is_running =
false;
771 switch (event_type) {
779 thread_sp->GetRegisterContext());
781 reg_ctx_sp->InvalidateAllRegisters();
782 static_cast<ThreadKDP *
>(thread_sp.get())
783 ->SetStopInfoFrom_KDP_EXCEPTION(exc_reply_packet);
793 if (listener_sp->GetEvent(event_sp,
794 std::chrono::microseconds(0))) {
796 event_type = event_sp->GetType();
803 "ProcessKDP::AsyncThread (pid = %" PRIu64
804 ") got eBroadcastBitAsyncThreadShouldExit...",
812 "ProcessKDP::AsyncThread (pid = %" PRIu64
813 ") got unknown event 0x%8.8x",
819 }
while (is_running);
822 "ProcessKDP::AsyncThread (pid = %" PRIu64
823 ") listener.WaitForEvent (NULL, event_sp) => false",
830 LLDB_LOGF(log,
"ProcessKDP::AsyncThread(pid = %" PRIu64
") thread exiting...",
848 "Send a custom packet through the KDP protocol by "
849 "specifying the command byte and the packet "
850 "payload data. A packet will be sent with a "
851 "correct header and payload, and the raw result "
852 "bytes will be displayed as a string value. ",
856 "Specify the command byte to use when sending the KDP "
860 "Specify packet payload bytes as a hex ASCII string with "
861 "no spaces or hex prefixes.",
873 "the --command option must be set to a valid command byte");
875 const uint64_t command_byte =
877 if (command_byte > 0 && command_byte <= UINT8_MAX) {
884 std::vector<uint8_t> payload_bytes;
885 const char *ascii_hex_bytes_cstr =
887 if (ascii_hex_bytes_cstr && ascii_hex_bytes_cstr[0]) {
889 const size_t ascii_hex_bytes_cstr_len =
891 if (ascii_hex_bytes_cstr_len & 1) {
893 "even number of ASCII hex "
895 ascii_hex_bytes_cstr);
898 payload_bytes.resize(ascii_hex_bytes_cstr_len / 2);
899 if (extractor.
GetHexBytes(payload_bytes,
'\xdd') !=
900 payload_bytes.size()) {
902 "ASCII hex characters (no "
903 "spaces or hex prefixes): '%s'",
904 ascii_hex_bytes_cstr);
912 payload_bytes.empty() ? NULL : payload_bytes.data(),
913 payload_bytes.size(), reply,
error);
915 if (
error.Success()) {
925 const char *error_cstr =
error.AsCString();
926 if (error_cstr && error_cstr[0])
935 "to send KDP packets, state is %s",
943 ", valid values are 1 - 255",
955 "Commands that deal with KDP remote packets.",
969 interpreter,
"process plugin",
970 "Commands for operating on a ProcessKDP process.",
971 "process plugin <subcommand> [<subcommand-options>]") {
981 m_command_sp = std::make_shared<CommandObjectMultiwordProcessKDP>(
982 GetTarget().GetDebugger().GetCommandInterpreter());
static llvm::raw_ostream & error(Stream &strm)
static PluginProperties & GetGlobalPluginProperties()
#define LLDB_LOGF(log,...)
#define LLDB_LOG_ERROR(log, error,...)
#define LLDB_LOGV(log,...)
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
static PluginProperties & GetGlobalPluginProperties()
static const lldb::tid_t g_kernel_tid
CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter)
~CommandObjectMultiwordProcessKDP() override=default
CommandObjectProcessKDPPacketSend(CommandInterpreter &interpreter)
OptionGroupOptions m_option_group
OptionGroupUInt64 m_command_byte
void DoExecute(Args &command, CommandReturnObject &result) override
Options * GetOptions() override
OptionGroupString m_packet_data
~CommandObjectProcessKDPPacketSend() override=default
~CommandObjectProcessKDPPacket() override=default
CommandObjectProcessKDPPacket(CommandInterpreter &interpreter)
bool SendRequestBreakpoint(bool set, lldb::addr_t addr)
bool SendRequestConnect(uint16_t reply_port, uint16_t exc_port, const char *greeting)
std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout)
uint32_t SendRequestWriteMemory(lldb::addr_t addr, const void *src, uint32_t src_len, lldb_private::Status &error)
bool SendRawRequest(uint8_t command_byte, const void *src, uint32_t src_len, lldb_private::DataExtractor &reply, lldb_private::Status &error)
uint32_t SendRequestReadMemory(lldb::addr_t addr, void *dst, uint32_t dst_size, lldb_private::Status &error)
lldb::addr_t GetLoadAddress()
bool SendRequestDisconnect()
const char * GetKernelVersion()
lldb_private::UUID GetUUID()
size_t WaitForPacketWithTimeoutMicroSeconds(lldb_private::DataExtractor &response, uint32_t usec)
bool RemoteIsDarwinKernel()
bool LocalBreakpointsAreSupported()
bool SendRequestReattach(uint16_t reply_port)
static llvm::StringRef GetPluginNameStatic()
lldb_private::Status DoWillLaunch(lldb_private::Module *module) override
Called before launching to a process.
lldb_private::Broadcaster m_async_broadcaster
@ eBroadcastBitAsyncThreadShouldExit
@ eBroadcastBitAsyncContinue
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Status &error) override
Actually do the reading of memory from a process.
lldb::CommandObjectSP m_command_sp
void DidAttach(lldb_private::ArchSpec &process_arch) override
Called after attaching a process.
ProcessKDP(lldb::TargetSP target_sp, lldb::ListenerSP listener)
lldb_private::Status EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override
lldb::ThreadSP GetKernelThread()
static llvm::StringRef GetPluginDescriptionStatic()
llvm::StringRef m_dyld_plugin_name
bool GetHostArchitecture(lldb_private::ArchSpec &arch)
lldb::ThreadWP m_kernel_thread_wp
lldb_private::Status DoLaunch(lldb_private::Module *exe_module, lldb_private::ProcessLaunchInfo &launch_info) override
Launch a new process.
lldb_private::Status DoSignal(int signal) override
Sends a process a UNIX signal signal.
void RefreshStateAfterStop() override
Currently called as part of ShouldStop.
lldb_private::HostThread m_async_thread
lldb_private::DynamicLoader * GetDynamicLoader() override
Get the dynamic loader plug-in for this process.
CommunicationKDP & GetCommunication()
lldb_private::Status WillResume() override
Called before resuming to a process.
lldb_private::Status DoHalt(bool &caused_stop) override
Halts a running process.
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const lldb_private::FileSpec *crash_file_path, bool can_connect)
lldb::addr_t m_kernel_load_addr
lldb_private::Status DoConnectRemote(llvm::StringRef remote_url) override
Attach to a remote system via a URL.
bool IsAlive() override
Check if a process is still alive.
lldb_private::CommandObject * GetPluginCommandObject() override
Return a multi-word command object that can be used to expose plug-in specific commands.
lldb_private::Status DoAttachToProcessWithName(const char *process_name, const lldb_private::ProcessAttachInfo &attach_info) override
Attach to an existing process using a partial process name.
lldb_private::Status DoWillAttachToProcessWithName(const char *process_name, bool wait_for_launch) override
Called before attaching to a process.
lldb::addr_t GetImageInfoAddress() override
Get the image information address for the current process.
bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override
Update the thread list following process plug-in's specific logic.
static void DebuggerInitialize(lldb_private::Debugger &debugger)
CommunicationKDP m_comm
Broadcaster event bits definitions.
lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, lldb_private::Status &error) override
Actually allocate memory in the process.
lldb_private::Status DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override
lldb_private::Status DoWillAttachToProcessWithID(lldb::pid_t pid) override
Called before attaching to a process.
lldb_private::Status DoAttachToProcessWithID(lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override
Attach to an existing process using a process ID.
size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, lldb_private::Status &error) override
Actually do the writing of memory to a process.
bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override
Check if a plug-in instance can debug the file in module.
lldb_private::Status DoDetach(bool keep_stopped) override
Detaches from a running or stopped process.
lldb_private::Status DoDeallocateMemory(lldb::addr_t ptr) override
Actually deallocate memory in the process.
lldb_private::Status DoDestroy() override
lldb_private::Status DoResume() override
Resumes all of a process's threads as configured using the Thread run control functions.
static llvm::StringRef GetPluginNameStatic()
An architecture specification class.
void Clear()
Clears the object state.
llvm::Triple & GetTriple()
Architecture triple accessor.
bool SetArchitecture(ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os=0)
Change the architecture object type, CPU type and OS type.
void MergeFrom(const ArchSpec &other)
Merges fields from another ArchSpec into this ArchSpec.
A command line argument class.
Class that manages the actual breakpoint that will be inserted into the running program.
BreakpointSite::Type GetType() const
void SetType(BreakpointSite::Type type)
bool IsEnabled() const
Tells whether the current breakpoint site is enabled or not.
void SetEnabled(bool enabled)
Sets whether the current breakpoint site is enabled or not.
void SetEventName(uint32_t event_mask, const char *name)
Set the name for an event bit.
void BroadcastEvent(lldb::EventSP &event_sp)
Broadcast an event which has no associated data.
ExecutionContext GetExecutionContext() const
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandInterpreter & m_interpreter
void AppendMessage(llvm::StringRef in_string)
void void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
bool IsConnected() const
Check if the connection is valid.
virtual void SetConnection(std::unique_ptr< Connection > connection)
Sets the connection that it to be used by this class.
virtual lldb::ConnectionStatus Disconnect(Status *error_ptr=nullptr)
Disconnect the communications connection if one is currently connected.
A class to manage flag bits.
lldb::StreamSP GetAsyncOutputStream()
A plug-in interface definition class for dynamic loaders.
static DynamicLoader * FindPlugin(Process *process, llvm::StringRef plugin_name)
Find a dynamic loader plugin for a given process.
Process * GetProcessPtr() const
Returns a pointer to the process object.
static FileSystem & Instance()
Status Join(lldb::thread_result_t *result)
static lldb::ListenerSP MakeListener(const char *name)
void PutCString(const char *cstr)
ArchSpec & GetArchitecture()
FileSpec & GetSymbolFileSpec()
A class that describes an executable image and its associated object and symbol files.
virtual ObjectFile * GetObjectFile()
Get the object file representation for the current architecture.
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
A plug-in interface definition class for object file parsers.
@ eTypeExecutable
A normal executable.
void Append(OptionGroup *group)
Append options from a OptionGroup class.
OptionValueString & GetOptionValue()
OptionValueUInt64 & GetOptionValue()
const char * GetCurrentValue() const
bool OptionWasSet() const
std::optional< T > GetValueAs() const
A command line option parsing protocol class.
static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, Status &error, bool force_lookup=true, bool copy_executable=true)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool CreateSettingForProcessPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec)
static lldb::OptionValuePropertiesSP GetSettingForProcessPlugin(Debugger &debugger, llvm::StringRef setting_name)
static FileSpec LocateExecutableSymbolFile(const ModuleSpec &module_spec, const FileSpecList &default_search_paths)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A plug-in interface definition class for debugging a process.
virtual Status DisableSoftwareBreakpoint(BreakpointSite *bp_site)
lldb::pid_t GetID() const
Returns the pid of the process or LLDB_INVALID_PROCESS_ID if there is no known pid.
ThreadList & GetThreadList()
void ResumePrivateStateThread()
void SetCanJIT(bool can_jit)
Sets whether executing JIT-compiled code in this process is possible.
lldb::DynamicLoaderUP m_dyld_up
void UpdateThreadListIfNeeded()
lldb::StateType GetState()
Get accessor for the current process state.
virtual Status EnableSoftwareBreakpoint(BreakpointSite *bp_site)
virtual bool IsAlive()
Check if a process is still alive.
bool m_destroy_in_process
virtual void DidAttach(ArchSpec &process_arch)
Called after attaching a process.
void SetID(lldb::pid_t new_pid)
Sets the stored pid.
void SetPrivateState(lldb::StateType state)
virtual void Finalize(bool destructing)
This object is about to be destroyed, do any necessary cleanup.
ThreadList m_thread_list
The threads for this process as the user will see them.
Target & GetTarget()
Get the target object pointer for this module.
virtual lldb::OptionValuePropertiesSP GetValueProperties() const
virtual lldb::addr_t GetLoadAddress() const
bool HardwareRequired() const
llvm::StringRef GetString() const
size_t PutBytesAsRawHex8(const void *src, size_t src_len, lldb::ByteOrder src_byte_order=lldb::eByteOrderInvalid, lldb::ByteOrder dst_byte_order=lldb::eByteOrderInvalid)
uint16_t GetLocalPortNumber() const
bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform=false, bool merge=true)
Set the architecture for this target.
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
static FileSpecList GetDefaultDebugFileSearchPaths()
const ArchSpec & GetArchitecture() const
void SetExecutableModule(lldb::ModuleSP &module_sp, LoadDependentFiles load_dependent_files=eLoadDependentsDefault)
Set the main executable module.
void AddThread(const lldb::ThreadSP &thread_sp)
static llvm::Expected< HostThread > LaunchThread(llvm::StringRef name, std::function< lldb::thread_result_t()> thread_function, size_t min_stack_byte_size=0)
lldb::ThreadSP FindThreadByProtocolID(lldb::tid_t tid, bool can_update=true)
uint32_t GetSize(bool can_update=true)
void RefreshStateAfterStop()
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
lldb::ByteOrder InlHostByteOrder()
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
bool StateIsStoppedState(lldb::StateType state, bool must_exist)
Check if a state represents a state where the process or thread is stopped.
const char * StateAsCString(lldb::StateType state)
Converts a StateType to a C string.
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
@ eConnectionStatusSuccess
Success.
StateType
Process and Thread States.
@ eStateDetached
Process has been detached and can't be examined.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
std::shared_ptr< lldb_private::Stream > StreamSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Event > EventSP
@ eReturnStatusSuccessFinishResult
std::shared_ptr< lldb_private::Listener > ListenerSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
std::shared_ptr< lldb_private::Module > ModuleSP