159ec512cSGreg Clayton //===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===//
2f9765acdSGreg Clayton //
3f9765acdSGreg Clayton //                     The LLVM Compiler Infrastructure
4f9765acdSGreg Clayton //
5f9765acdSGreg Clayton // This file is distributed under the University of Illinois Open Source
6f9765acdSGreg Clayton // License. See LICENSE.TXT for details.
7f9765acdSGreg Clayton //
8f9765acdSGreg Clayton //===----------------------------------------------------------------------===//
9f9765acdSGreg Clayton 
10f9765acdSGreg Clayton // C Includes
11f9765acdSGreg Clayton #include <errno.h>
12f9765acdSGreg Clayton #include <stdlib.h>
13f9765acdSGreg Clayton 
14f9765acdSGreg Clayton // C++ Includes
15f9765acdSGreg Clayton // Other libraries and framework includes
163a29bdbeSGreg Clayton #include "lldb/Core/ConnectionFileDescriptor.h"
1707e66e3eSGreg Clayton #include "lldb/Core/Debugger.h"
18f9765acdSGreg Clayton #include "lldb/Core/PluginManager.h"
191f746071SGreg Clayton #include "lldb/Core/Module.h"
20*4bd4e7e3SJason Molenda #include "lldb/Core/ModuleSpec.h"
21f9765acdSGreg Clayton #include "lldb/Core/State.h"
22*4bd4e7e3SJason Molenda #include "lldb/Core/UUID.h"
23f9765acdSGreg Clayton #include "lldb/Host/Host.h"
24*4bd4e7e3SJason Molenda #include "lldb/Host/Symbols.h"
251f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h"
267925fbbaSGreg Clayton #include "lldb/Target/RegisterContext.h"
2757508026SGreg Clayton #include "lldb/Target/Target.h"
28a63d08c9SGreg Clayton #include "lldb/Target/Thread.h"
29f9765acdSGreg Clayton 
30f9765acdSGreg Clayton // Project includes
31f9765acdSGreg Clayton #include "ProcessKDP.h"
32f9765acdSGreg Clayton #include "ProcessKDPLog.h"
33a63d08c9SGreg Clayton #include "ThreadKDP.h"
34f9765acdSGreg Clayton 
35f9765acdSGreg Clayton using namespace lldb;
36f9765acdSGreg Clayton using namespace lldb_private;
37f9765acdSGreg Clayton 
38f9765acdSGreg Clayton const char *
39f9765acdSGreg Clayton ProcessKDP::GetPluginNameStatic()
40f9765acdSGreg Clayton {
41f9765acdSGreg Clayton     return "kdp-remote";
42f9765acdSGreg Clayton }
43f9765acdSGreg Clayton 
44f9765acdSGreg Clayton const char *
45f9765acdSGreg Clayton ProcessKDP::GetPluginDescriptionStatic()
46f9765acdSGreg Clayton {
47f9765acdSGreg Clayton     return "KDP Remote protocol based debugging plug-in for darwin kernel debugging.";
48f9765acdSGreg Clayton }
49f9765acdSGreg Clayton 
50f9765acdSGreg Clayton void
51f9765acdSGreg Clayton ProcessKDP::Terminate()
52f9765acdSGreg Clayton {
53f9765acdSGreg Clayton     PluginManager::UnregisterPlugin (ProcessKDP::CreateInstance);
54f9765acdSGreg Clayton }
55f9765acdSGreg Clayton 
56f9765acdSGreg Clayton 
57c3776bf2SGreg Clayton lldb::ProcessSP
58c3776bf2SGreg Clayton ProcessKDP::CreateInstance (Target &target,
59c3776bf2SGreg Clayton                             Listener &listener,
60c3776bf2SGreg Clayton                             const FileSpec *crash_file_path)
61f9765acdSGreg Clayton {
62c3776bf2SGreg Clayton     lldb::ProcessSP process_sp;
63c3776bf2SGreg Clayton     if (crash_file_path == NULL)
64c3776bf2SGreg Clayton         process_sp.reset(new ProcessKDP (target, listener));
65c3776bf2SGreg Clayton     return process_sp;
66f9765acdSGreg Clayton }
67f9765acdSGreg Clayton 
68f9765acdSGreg Clayton bool
693a29bdbeSGreg Clayton ProcessKDP::CanDebug(Target &target, bool plugin_specified_by_name)
70f9765acdSGreg Clayton {
71596ed24eSGreg Clayton     if (plugin_specified_by_name)
72596ed24eSGreg Clayton         return true;
73596ed24eSGreg Clayton 
74f9765acdSGreg Clayton     // For now we are just making sure the file exists for a given module
75aa149cbdSGreg Clayton     Module *exe_module = target.GetExecutableModulePointer();
76aa149cbdSGreg Clayton     if (exe_module)
77f9765acdSGreg Clayton     {
78f9765acdSGreg Clayton         const llvm::Triple &triple_ref = target.GetArchitecture().GetTriple();
7970512317SGreg Clayton         switch (triple_ref.getOS())
8070512317SGreg Clayton         {
8170512317SGreg Clayton             case llvm::Triple::Darwin:  // Should use "macosx" for desktop and "ios" for iOS, but accept darwin just in case
8270512317SGreg Clayton             case llvm::Triple::MacOSX:  // For desktop targets
8370512317SGreg Clayton             case llvm::Triple::IOS:     // For arm targets
8470512317SGreg Clayton                 if (triple_ref.getVendor() == llvm::Triple::Apple)
85f9765acdSGreg Clayton                 {
86aa149cbdSGreg Clayton                     ObjectFile *exe_objfile = exe_module->GetObjectFile();
87f9765acdSGreg Clayton                     if (exe_objfile->GetType() == ObjectFile::eTypeExecutable &&
88f9765acdSGreg Clayton                         exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
89f9765acdSGreg Clayton                         return true;
90f9765acdSGreg Clayton                 }
9170512317SGreg Clayton                 break;
9270512317SGreg Clayton 
9370512317SGreg Clayton             default:
9470512317SGreg Clayton                 break;
9570512317SGreg Clayton         }
96f9765acdSGreg Clayton     }
97596ed24eSGreg Clayton     return false;
983a29bdbeSGreg Clayton }
99f9765acdSGreg Clayton 
100f9765acdSGreg Clayton //----------------------------------------------------------------------
101f9765acdSGreg Clayton // ProcessKDP constructor
102f9765acdSGreg Clayton //----------------------------------------------------------------------
103f9765acdSGreg Clayton ProcessKDP::ProcessKDP(Target& target, Listener &listener) :
104f9765acdSGreg Clayton     Process (target, listener),
105f9765acdSGreg Clayton     m_comm("lldb.process.kdp-remote.communication"),
1064bddaeb5SJim Ingham     m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"),
10797d5cf05SGreg Clayton     m_async_thread (LLDB_INVALID_HOST_THREAD),
10897d5cf05SGreg Clayton     m_destroy_in_process (false)
109f9765acdSGreg Clayton {
1107925fbbaSGreg Clayton     m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
1117925fbbaSGreg Clayton     m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
112f9765acdSGreg Clayton }
113f9765acdSGreg Clayton 
114f9765acdSGreg Clayton //----------------------------------------------------------------------
115f9765acdSGreg Clayton // Destructor
116f9765acdSGreg Clayton //----------------------------------------------------------------------
117f9765acdSGreg Clayton ProcessKDP::~ProcessKDP()
118f9765acdSGreg Clayton {
119f9765acdSGreg Clayton     Clear();
120e24c4acfSGreg Clayton     // We need to call finalize on the process before destroying ourselves
121e24c4acfSGreg Clayton     // to make sure all of the broadcaster cleanup goes as planned. If we
122e24c4acfSGreg Clayton     // destruct this class, then Process::~Process() might have problems
123e24c4acfSGreg Clayton     // trying to fully destroy the broadcaster.
124e24c4acfSGreg Clayton     Finalize();
125f9765acdSGreg Clayton }
126f9765acdSGreg Clayton 
127f9765acdSGreg Clayton //----------------------------------------------------------------------
128f9765acdSGreg Clayton // PluginInterface
129f9765acdSGreg Clayton //----------------------------------------------------------------------
130f9765acdSGreg Clayton const char *
131f9765acdSGreg Clayton ProcessKDP::GetPluginName()
132f9765acdSGreg Clayton {
133f9765acdSGreg Clayton     return "Process debugging plug-in that uses the Darwin KDP remote protocol";
134f9765acdSGreg Clayton }
135f9765acdSGreg Clayton 
136f9765acdSGreg Clayton const char *
137f9765acdSGreg Clayton ProcessKDP::GetShortPluginName()
138f9765acdSGreg Clayton {
139f9765acdSGreg Clayton     return GetPluginNameStatic();
140f9765acdSGreg Clayton }
141f9765acdSGreg Clayton 
142f9765acdSGreg Clayton uint32_t
143f9765acdSGreg Clayton ProcessKDP::GetPluginVersion()
144f9765acdSGreg Clayton {
145f9765acdSGreg Clayton     return 1;
146f9765acdSGreg Clayton }
147f9765acdSGreg Clayton 
148f9765acdSGreg Clayton Error
149f9765acdSGreg Clayton ProcessKDP::WillLaunch (Module* module)
150f9765acdSGreg Clayton {
151f9765acdSGreg Clayton     Error error;
152f9765acdSGreg Clayton     error.SetErrorString ("launching not supported in kdp-remote plug-in");
153f9765acdSGreg Clayton     return error;
154f9765acdSGreg Clayton }
155f9765acdSGreg Clayton 
156f9765acdSGreg Clayton Error
157f9765acdSGreg Clayton ProcessKDP::WillAttachToProcessWithID (lldb::pid_t pid)
158f9765acdSGreg Clayton {
159f9765acdSGreg Clayton     Error error;
160f9765acdSGreg Clayton     error.SetErrorString ("attaching to a by process ID not supported in kdp-remote plug-in");
161f9765acdSGreg Clayton     return error;
162f9765acdSGreg Clayton }
163f9765acdSGreg Clayton 
164f9765acdSGreg Clayton Error
165f9765acdSGreg Clayton ProcessKDP::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
166f9765acdSGreg Clayton {
167f9765acdSGreg Clayton     Error error;
168f9765acdSGreg Clayton     error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in");
169f9765acdSGreg Clayton     return error;
170f9765acdSGreg Clayton }
171f9765acdSGreg Clayton 
172f9765acdSGreg Clayton Error
173*4bd4e7e3SJason Molenda ProcessKDP::DoConnectRemote (Stream *strm, const char *remote_url)
174f9765acdSGreg Clayton {
175f9765acdSGreg Clayton     Error error;
1763a29bdbeSGreg Clayton 
1777925fbbaSGreg Clayton     // Don't let any JIT happen when doing KDP as we can't allocate
1787925fbbaSGreg Clayton     // memory and we don't want to be mucking with threads that might
1797925fbbaSGreg Clayton     // already be handling exceptions
1807925fbbaSGreg Clayton     SetCanJIT(false);
1817925fbbaSGreg Clayton 
1823a29bdbeSGreg Clayton     if (remote_url == NULL || remote_url[0] == '\0')
1837925fbbaSGreg Clayton     {
1847925fbbaSGreg Clayton         error.SetErrorStringWithFormat ("invalid connection URL '%s'", remote_url);
1857925fbbaSGreg Clayton         return error;
1867925fbbaSGreg Clayton     }
1873a29bdbeSGreg Clayton 
1883a29bdbeSGreg Clayton     std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
1893a29bdbeSGreg Clayton     if (conn_ap.get())
1903a29bdbeSGreg Clayton     {
1913a29bdbeSGreg Clayton         // Only try once for now.
1923a29bdbeSGreg Clayton         // TODO: check if we should be retrying?
1933a29bdbeSGreg Clayton         const uint32_t max_retry_count = 1;
1943a29bdbeSGreg Clayton         for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count)
1953a29bdbeSGreg Clayton         {
1963a29bdbeSGreg Clayton             if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess)
1973a29bdbeSGreg Clayton                 break;
1983a29bdbeSGreg Clayton             usleep (100000);
1993a29bdbeSGreg Clayton         }
2003a29bdbeSGreg Clayton     }
2013a29bdbeSGreg Clayton 
2023a29bdbeSGreg Clayton     if (conn_ap->IsConnected())
2033a29bdbeSGreg Clayton     {
2043a29bdbeSGreg Clayton         const uint16_t reply_port = conn_ap->GetReadPort ();
2053a29bdbeSGreg Clayton 
2063a29bdbeSGreg Clayton         if (reply_port != 0)
2073a29bdbeSGreg Clayton         {
2083a29bdbeSGreg Clayton             m_comm.SetConnection(conn_ap.release());
2093a29bdbeSGreg Clayton 
2103a29bdbeSGreg Clayton             if (m_comm.SendRequestReattach(reply_port))
2113a29bdbeSGreg Clayton             {
2123a29bdbeSGreg Clayton                 if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB..."))
2133a29bdbeSGreg Clayton                 {
2143a29bdbeSGreg Clayton                     m_comm.GetVersion();
2153a29bdbeSGreg Clayton                     uint32_t cpu = m_comm.GetCPUType();
2163a29bdbeSGreg Clayton                     uint32_t sub = m_comm.GetCPUSubtype();
2173a29bdbeSGreg Clayton                     ArchSpec kernel_arch;
2183a29bdbeSGreg Clayton                     kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
2193a29bdbeSGreg Clayton                     m_target.SetArchitecture(kernel_arch);
220*4bd4e7e3SJason Molenda 
221*4bd4e7e3SJason Molenda                     /* Get the kernel's UUID and load address via kdp-kernelversion packet.  */
222*4bd4e7e3SJason Molenda 
223*4bd4e7e3SJason Molenda                     UUID kernel_uuid = m_comm.GetUUID ();
224*4bd4e7e3SJason Molenda                     addr_t kernel_load_addr = m_comm.GetLoadAddress ();
225*4bd4e7e3SJason Molenda                     if (strm)
226*4bd4e7e3SJason Molenda                     {
227*4bd4e7e3SJason Molenda                         char uuidbuf[64];
228*4bd4e7e3SJason Molenda                         strm->Printf ("Kernel UUID: %s\n", kernel_uuid.GetAsCString (uuidbuf, sizeof (uuidbuf)));
229*4bd4e7e3SJason Molenda                         strm->Printf ("Load Address: 0x%llx\n", kernel_load_addr);
230*4bd4e7e3SJason Molenda                         strm->Flush ();
231*4bd4e7e3SJason Molenda                     }
232*4bd4e7e3SJason Molenda 
233*4bd4e7e3SJason Molenda                     /* Set the kernel's LoadAddress based on the information from kdp.
234*4bd4e7e3SJason Molenda                        This would normally be handled by the DynamicLoaderDarwinKernel plugin but there's no easy
235*4bd4e7e3SJason Molenda                        way to communicate the UUID / load addr from kdp back up to that plugin so we'll set it here. */
236*4bd4e7e3SJason Molenda                     ModuleSP exe_module_sp = m_target.GetExecutableModule ();
237*4bd4e7e3SJason Molenda                     bool find_and_load_kernel = true;
238*4bd4e7e3SJason Molenda                     if (exe_module_sp.get ())
239*4bd4e7e3SJason Molenda                     {
240*4bd4e7e3SJason Molenda                         ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
241*4bd4e7e3SJason Molenda                         if (exe_objfile->GetType() == ObjectFile::eTypeExecutable &&
242*4bd4e7e3SJason Molenda                             exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
243*4bd4e7e3SJason Molenda                         {
244*4bd4e7e3SJason Molenda                             UUID exe_objfile_uuid;
245*4bd4e7e3SJason Molenda                             if (exe_objfile->GetUUID (&exe_objfile_uuid) && kernel_uuid == exe_objfile_uuid
246*4bd4e7e3SJason Molenda                                 && exe_objfile->GetHeaderAddress().IsValid())
247*4bd4e7e3SJason Molenda                             {
248*4bd4e7e3SJason Molenda                                 find_and_load_kernel = false;
249*4bd4e7e3SJason Molenda                                 addr_t slide = kernel_load_addr - exe_objfile->GetHeaderAddress().GetFileAddress();
250*4bd4e7e3SJason Molenda                                 if (slide != 0)
251*4bd4e7e3SJason Molenda                                 {
252*4bd4e7e3SJason Molenda                                     bool changed = false;
253*4bd4e7e3SJason Molenda                                     exe_module_sp->SetLoadAddress (m_target, slide, changed);
254*4bd4e7e3SJason Molenda                                     if (changed)
255*4bd4e7e3SJason Molenda                                     {
256*4bd4e7e3SJason Molenda                                         ModuleList modlist;
257*4bd4e7e3SJason Molenda                                         modlist.Append (exe_module_sp);
258*4bd4e7e3SJason Molenda                                         m_target.ModulesDidLoad (modlist);
259*4bd4e7e3SJason Molenda                                     }
260*4bd4e7e3SJason Molenda                                 }
261*4bd4e7e3SJason Molenda                             }
262*4bd4e7e3SJason Molenda                         }
263*4bd4e7e3SJason Molenda                     }
264*4bd4e7e3SJason Molenda 
265*4bd4e7e3SJason Molenda                     // If the executable binary is not the same as the kernel being run on the remote host,
266*4bd4e7e3SJason Molenda                     // see if Symbols::DownloadObjectAndSymbolFile can find us a symbol file based on the UUID
267*4bd4e7e3SJason Molenda                     // and if so, load it at the correct address.
268*4bd4e7e3SJason Molenda                     if (find_and_load_kernel && kernel_load_addr != LLDB_INVALID_ADDRESS && kernel_uuid.IsValid())
269*4bd4e7e3SJason Molenda                     {
270*4bd4e7e3SJason Molenda                         ModuleSpec sym_spec;
271*4bd4e7e3SJason Molenda                         sym_spec.GetUUID() = kernel_uuid;
272*4bd4e7e3SJason Molenda                         if (Symbols::DownloadObjectAndSymbolFile (sym_spec)
273*4bd4e7e3SJason Molenda                             && sym_spec.GetArchitecture().IsValid()
274*4bd4e7e3SJason Molenda                             && sym_spec.GetSymbolFileSpec().Exists())
275*4bd4e7e3SJason Molenda                         {
276*4bd4e7e3SJason Molenda                             ModuleSP kernel_sp = m_target.GetSharedModule (sym_spec);
277*4bd4e7e3SJason Molenda                             if (kernel_sp.get())
278*4bd4e7e3SJason Molenda                             {
279*4bd4e7e3SJason Molenda                                 m_target.SetExecutableModule(kernel_sp, false);
280*4bd4e7e3SJason Molenda                                 if (kernel_sp->GetObjectFile() && kernel_sp->GetObjectFile()->GetHeaderAddress().IsValid())
281*4bd4e7e3SJason Molenda                                 {
282*4bd4e7e3SJason Molenda                                     addr_t slide = kernel_load_addr - kernel_sp->GetObjectFile()->GetHeaderAddress().GetFileAddress();
283*4bd4e7e3SJason Molenda                                     bool changed = false;
284*4bd4e7e3SJason Molenda                                     kernel_sp->SetLoadAddress (m_target, slide, changed);
285*4bd4e7e3SJason Molenda                                     if (changed)
286*4bd4e7e3SJason Molenda                                     {
287*4bd4e7e3SJason Molenda                                         ModuleList modlist;
288*4bd4e7e3SJason Molenda                                         modlist.Append (kernel_sp);
289*4bd4e7e3SJason Molenda                                         m_target.ModulesDidLoad (modlist);
290*4bd4e7e3SJason Molenda                                     }
291*4bd4e7e3SJason Molenda                                     if (strm)
292*4bd4e7e3SJason Molenda                                     {
293*4bd4e7e3SJason Molenda                                         strm->Printf ("Loaded kernel file %s/%s\n",
294*4bd4e7e3SJason Molenda                                                       kernel_sp->GetFileSpec().GetDirectory().AsCString(),
295*4bd4e7e3SJason Molenda                                                       kernel_sp->GetFileSpec().GetFilename().AsCString());
296*4bd4e7e3SJason Molenda                                         strm->Flush ();
297*4bd4e7e3SJason Molenda                                     }
298*4bd4e7e3SJason Molenda                                 }
299*4bd4e7e3SJason Molenda                             }
300*4bd4e7e3SJason Molenda                         }
301*4bd4e7e3SJason Molenda                     }
302*4bd4e7e3SJason Molenda 
303*4bd4e7e3SJason Molenda 
30497d5cf05SGreg Clayton                     // Set the thread ID
30597d5cf05SGreg Clayton                     UpdateThreadListIfNeeded ();
306a63d08c9SGreg Clayton                     SetID (1);
30756d9a1b3SGreg Clayton                     GetThreadList ();
308a63d08c9SGreg Clayton                     SetPrivateState (eStateStopped);
30907e66e3eSGreg Clayton                     StreamSP async_strm_sp(m_target.GetDebugger().GetAsyncOutputStream());
31007e66e3eSGreg Clayton                     if (async_strm_sp)
31107e66e3eSGreg Clayton                     {
3125b88216dSGreg Clayton                         const char *cstr;
3135b88216dSGreg Clayton                         if ((cstr = m_comm.GetKernelVersion ()) != NULL)
31407e66e3eSGreg Clayton                         {
3155b88216dSGreg Clayton                             async_strm_sp->Printf ("Version: %s\n", cstr);
31607e66e3eSGreg Clayton                             async_strm_sp->Flush();
31707e66e3eSGreg Clayton                         }
3185b88216dSGreg Clayton //                      if ((cstr = m_comm.GetImagePath ()) != NULL)
3195b88216dSGreg Clayton //                      {
3205b88216dSGreg Clayton //                          async_strm_sp->Printf ("Image Path: %s\n", cstr);
3215b88216dSGreg Clayton //                          async_strm_sp->Flush();
3225b88216dSGreg Clayton //                      }
32307e66e3eSGreg Clayton                     }
3243a29bdbeSGreg Clayton                 }
32597d5cf05SGreg Clayton                 else
32697d5cf05SGreg Clayton                 {
32797d5cf05SGreg Clayton                     puts ("KDP_CONNECT failed"); // REMOVE THIS
32897d5cf05SGreg Clayton                     error.SetErrorString("KDP_REATTACH failed");
32997d5cf05SGreg Clayton                 }
3303a29bdbeSGreg Clayton             }
3313a29bdbeSGreg Clayton             else
3323a29bdbeSGreg Clayton             {
33397d5cf05SGreg Clayton                 puts ("KDP_REATTACH failed"); // REMOVE THIS
33497d5cf05SGreg Clayton                 error.SetErrorString("KDP_REATTACH failed");
3353a29bdbeSGreg Clayton             }
3363a29bdbeSGreg Clayton         }
3373a29bdbeSGreg Clayton         else
3383a29bdbeSGreg Clayton         {
3393a29bdbeSGreg Clayton             error.SetErrorString("invalid reply port from UDP connection");
3403a29bdbeSGreg Clayton         }
3413a29bdbeSGreg Clayton     }
3423a29bdbeSGreg Clayton     else
3433a29bdbeSGreg Clayton     {
3443a29bdbeSGreg Clayton         if (error.Success())
3453a29bdbeSGreg Clayton             error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url);
3463a29bdbeSGreg Clayton     }
3473a29bdbeSGreg Clayton     if (error.Fail())
3483a29bdbeSGreg Clayton         m_comm.Disconnect();
3493a29bdbeSGreg Clayton 
350f9765acdSGreg Clayton     return error;
351f9765acdSGreg Clayton }
352f9765acdSGreg Clayton 
353f9765acdSGreg Clayton //----------------------------------------------------------------------
354f9765acdSGreg Clayton // Process Control
355f9765acdSGreg Clayton //----------------------------------------------------------------------
356f9765acdSGreg Clayton Error
357982c9762SGreg Clayton ProcessKDP::DoLaunch (Module *exe_module,
358982c9762SGreg Clayton                       const ProcessLaunchInfo &launch_info)
359f9765acdSGreg Clayton {
360f9765acdSGreg Clayton     Error error;
361f9765acdSGreg Clayton     error.SetErrorString ("launching not supported in kdp-remote plug-in");
362f9765acdSGreg Clayton     return error;
363f9765acdSGreg Clayton }
364f9765acdSGreg Clayton 
365f9765acdSGreg Clayton 
366f9765acdSGreg Clayton Error
367f9765acdSGreg Clayton ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid)
368f9765acdSGreg Clayton {
369f9765acdSGreg Clayton     Error error;
370f9765acdSGreg Clayton     error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging");
371f9765acdSGreg Clayton     return error;
372f9765acdSGreg Clayton }
373f9765acdSGreg Clayton 
374f9765acdSGreg Clayton Error
37584647048SHan Ming Ong ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
37684647048SHan Ming Ong {
37784647048SHan Ming Ong     Error error;
37884647048SHan Ming Ong     error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging");
37984647048SHan Ming Ong     return error;
38084647048SHan Ming Ong }
38184647048SHan Ming Ong 
38284647048SHan Ming Ong Error
38384647048SHan Ming Ong ProcessKDP::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch, const ProcessAttachInfo &attach_info)
384f9765acdSGreg Clayton {
385f9765acdSGreg Clayton     Error error;
386f9765acdSGreg Clayton     error.SetErrorString ("attach to process by name is not suppported in kdp remote debugging");
387f9765acdSGreg Clayton     return error;
388f9765acdSGreg Clayton }
389f9765acdSGreg Clayton 
390f9765acdSGreg Clayton 
391f9765acdSGreg Clayton void
392f9765acdSGreg Clayton ProcessKDP::DidAttach ()
393f9765acdSGreg Clayton {
394f9765acdSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
395f9765acdSGreg Clayton     if (log)
39654cb8f83SJohnny Chen         log->Printf ("ProcessKDP::DidAttach()");
397f9765acdSGreg Clayton     if (GetID() != LLDB_INVALID_PROCESS_ID)
398f9765acdSGreg Clayton     {
399f9765acdSGreg Clayton         // TODO: figure out the register context that we will use
400f9765acdSGreg Clayton     }
401f9765acdSGreg Clayton }
402f9765acdSGreg Clayton 
403f9765acdSGreg Clayton Error
404f9765acdSGreg Clayton ProcessKDP::WillResume ()
405f9765acdSGreg Clayton {
406f9765acdSGreg Clayton     return Error();
407f9765acdSGreg Clayton }
408f9765acdSGreg Clayton 
409f9765acdSGreg Clayton Error
410f9765acdSGreg Clayton ProcessKDP::DoResume ()
411f9765acdSGreg Clayton {
412f9765acdSGreg Clayton     Error error;
4137925fbbaSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
4147925fbbaSGreg Clayton     // Only start the async thread if we try to do any process control
4157925fbbaSGreg Clayton     if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
4167925fbbaSGreg Clayton         StartAsyncThread ();
4177925fbbaSGreg Clayton 
41897d5cf05SGreg Clayton     bool resume = false;
4197925fbbaSGreg Clayton 
42097d5cf05SGreg Clayton     // With KDP there is only one thread we can tell what to do
42197d5cf05SGreg Clayton     ThreadSP kernel_thread_sp (GetKernelThread(m_thread_list, m_thread_list));
42297d5cf05SGreg Clayton     if (kernel_thread_sp)
4234b1b8b3eSGreg Clayton     {
42497d5cf05SGreg Clayton         const StateType thread_resume_state = kernel_thread_sp->GetTemporaryResumeState();
4257925fbbaSGreg Clayton         switch (thread_resume_state)
4264b1b8b3eSGreg Clayton         {
4277925fbbaSGreg Clayton             case eStateSuspended:
4287925fbbaSGreg Clayton                 // Nothing to do here when a thread will stay suspended
4297925fbbaSGreg Clayton                 // we just leave the CPU mask bit set to zero for the thread
43097d5cf05SGreg Clayton                 puts("REMOVE THIS: ProcessKDP::DoResume () -- thread suspended");
4317925fbbaSGreg Clayton                 break;
4327925fbbaSGreg Clayton 
4337925fbbaSGreg Clayton             case eStateStepping:
43497d5cf05SGreg Clayton                 puts("REMOVE THIS: ProcessKDP::DoResume () -- thread stepping");
43597d5cf05SGreg Clayton                 kernel_thread_sp->GetRegisterContext()->HardwareSingleStep (true);
43697d5cf05SGreg Clayton                 resume = true;
4377925fbbaSGreg Clayton                 break;
4387925fbbaSGreg Clayton 
43997d5cf05SGreg Clayton             case eStateRunning:
44097d5cf05SGreg Clayton                 puts("REMOVE THIS: ProcessKDP::DoResume () -- thread running");
44197d5cf05SGreg Clayton                 kernel_thread_sp->GetRegisterContext()->HardwareSingleStep (false);
44297d5cf05SGreg Clayton                 resume = true;
4437925fbbaSGreg Clayton                 break;
4447925fbbaSGreg Clayton 
4457925fbbaSGreg Clayton             default:
44697d5cf05SGreg Clayton                 // The only valid thread resume states are listed above
4477925fbbaSGreg Clayton                 assert (!"invalid thread resume state");
4487925fbbaSGreg Clayton                 break;
4494b1b8b3eSGreg Clayton         }
4504b1b8b3eSGreg Clayton     }
4517925fbbaSGreg Clayton 
45297d5cf05SGreg Clayton     if (resume)
45397d5cf05SGreg Clayton     {
45497d5cf05SGreg Clayton         if (log)
45597d5cf05SGreg Clayton             log->Printf ("ProcessKDP::DoResume () sending resume");
45697d5cf05SGreg Clayton 
45797d5cf05SGreg Clayton         if (m_comm.SendRequestResume ())
4587925fbbaSGreg Clayton         {
4597925fbbaSGreg Clayton             m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue);
4607925fbbaSGreg Clayton             SetPrivateState(eStateRunning);
4617925fbbaSGreg Clayton         }
4624b1b8b3eSGreg Clayton         else
46307e66e3eSGreg Clayton             error.SetErrorString ("KDP resume failed");
4647925fbbaSGreg Clayton     }
4657925fbbaSGreg Clayton     else
4667925fbbaSGreg Clayton     {
46797d5cf05SGreg Clayton         error.SetErrorString ("kernel thread is suspended");
4687925fbbaSGreg Clayton     }
4697925fbbaSGreg Clayton 
470f9765acdSGreg Clayton     return error;
471f9765acdSGreg Clayton }
472f9765acdSGreg Clayton 
47397d5cf05SGreg Clayton lldb::ThreadSP
47497d5cf05SGreg Clayton ProcessKDP::GetKernelThread(ThreadList &old_thread_list, ThreadList &new_thread_list)
47597d5cf05SGreg Clayton {
47697d5cf05SGreg Clayton     // KDP only tells us about one thread/core. Any other threads will usually
47797d5cf05SGreg Clayton     // be the ones that are read from memory by the OS plug-ins.
47897d5cf05SGreg Clayton     const lldb::tid_t kernel_tid = 1;
47997d5cf05SGreg Clayton     ThreadSP thread_sp (old_thread_list.FindThreadByID (kernel_tid, false));
48097d5cf05SGreg Clayton     if (!thread_sp)
48197d5cf05SGreg Clayton     {
48297d5cf05SGreg Clayton         thread_sp.reset(new ThreadKDP (shared_from_this(), kernel_tid));
48397d5cf05SGreg Clayton         new_thread_list.AddThread(thread_sp);
48497d5cf05SGreg Clayton     }
48597d5cf05SGreg Clayton     return thread_sp;
48697d5cf05SGreg Clayton }
48797d5cf05SGreg Clayton 
48897d5cf05SGreg Clayton 
48997d5cf05SGreg Clayton 
49097d5cf05SGreg Clayton 
4919fc13556SGreg Clayton bool
49256d9a1b3SGreg Clayton ProcessKDP::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
493f9765acdSGreg Clayton {
494f9765acdSGreg Clayton     // locker will keep a mutex locked until it goes out of scope
495f9765acdSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD));
496f9765acdSGreg Clayton     if (log && log->GetMask().Test(KDP_LOG_VERBOSE))
49781c22f61SGreg Clayton         log->Printf ("ProcessKDP::%s (pid = %llu)", __FUNCTION__, GetID());
498f9765acdSGreg Clayton 
49997d5cf05SGreg Clayton     // Even though there is a CPU mask, it doesn't mean to can see each CPU
50097d5cf05SGreg Clayton     // indivudually, there is really only one. Lets call this thread 1.
50197d5cf05SGreg Clayton     GetKernelThread (old_thread_list, new_thread_list);
50297d5cf05SGreg Clayton 
5039fc13556SGreg Clayton     return new_thread_list.GetSize(false) > 0;
504f9765acdSGreg Clayton }
505f9765acdSGreg Clayton 
506f9765acdSGreg Clayton void
507f9765acdSGreg Clayton ProcessKDP::RefreshStateAfterStop ()
508f9765acdSGreg Clayton {
509f9765acdSGreg Clayton     // Let all threads recover from stopping and do any clean up based
510f9765acdSGreg Clayton     // on the previous thread state (if any).
511f9765acdSGreg Clayton     m_thread_list.RefreshStateAfterStop();
512f9765acdSGreg Clayton }
513f9765acdSGreg Clayton 
514f9765acdSGreg Clayton Error
515f9765acdSGreg Clayton ProcessKDP::DoHalt (bool &caused_stop)
516f9765acdSGreg Clayton {
517f9765acdSGreg Clayton     Error error;
518f9765acdSGreg Clayton 
51997d5cf05SGreg Clayton     if (m_comm.IsRunning())
520f9765acdSGreg Clayton     {
52197d5cf05SGreg Clayton         if (m_destroy_in_process)
52297d5cf05SGreg Clayton         {
52397d5cf05SGreg Clayton             // If we are attemping to destroy, we need to not return an error to
52497d5cf05SGreg Clayton             // Halt or DoDestroy won't get called.
52597d5cf05SGreg Clayton             // We are also currently running, so send a process stopped event
52697d5cf05SGreg Clayton             SetPrivateState (eStateStopped);
527f9765acdSGreg Clayton         }
528f9765acdSGreg Clayton         else
529f9765acdSGreg Clayton         {
53097d5cf05SGreg Clayton             error.SetErrorString ("KDP cannot interrupt a running kernel");
531f9765acdSGreg Clayton         }
532f9765acdSGreg Clayton     }
533f9765acdSGreg Clayton     return error;
534f9765acdSGreg Clayton }
535f9765acdSGreg Clayton 
536f9765acdSGreg Clayton Error
537f9765acdSGreg Clayton ProcessKDP::DoDetach()
538f9765acdSGreg Clayton {
539f9765acdSGreg Clayton     Error error;
540f9765acdSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
541f9765acdSGreg Clayton     if (log)
542f9765acdSGreg Clayton         log->Printf ("ProcessKDP::DoDetach()");
543f9765acdSGreg Clayton 
54497d5cf05SGreg Clayton     if (m_comm.IsRunning())
54597d5cf05SGreg Clayton     {
54697d5cf05SGreg Clayton         // We are running and we can't interrupt a running kernel, so we need
54797d5cf05SGreg Clayton         // to just close the connection to the kernel and hope for the best
54897d5cf05SGreg Clayton     }
54997d5cf05SGreg Clayton     else
55097d5cf05SGreg Clayton     {
551f9765acdSGreg Clayton         DisableAllBreakpointSites ();
552f9765acdSGreg Clayton 
553f9765acdSGreg Clayton         m_thread_list.DiscardThreadPlans();
554f9765acdSGreg Clayton 
5553a29bdbeSGreg Clayton         if (m_comm.IsConnected())
5563a29bdbeSGreg Clayton         {
5573a29bdbeSGreg Clayton 
5583a29bdbeSGreg Clayton             m_comm.SendRequestDisconnect();
5593a29bdbeSGreg Clayton 
56057508026SGreg Clayton             size_t response_size = m_comm.Disconnect ();
561f9765acdSGreg Clayton             if (log)
562f9765acdSGreg Clayton             {
563f9765acdSGreg Clayton                 if (response_size)
564f9765acdSGreg Clayton                     log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
565f9765acdSGreg Clayton                 else
566f9765acdSGreg Clayton                     log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
567f9765acdSGreg Clayton             }
5683a29bdbeSGreg Clayton         }
56997d5cf05SGreg Clayton     }
570f9765acdSGreg Clayton     StopAsyncThread ();
57174d4193eSGreg Clayton     m_comm.Clear();
572f9765acdSGreg Clayton 
573f9765acdSGreg Clayton     SetPrivateState (eStateDetached);
574f9765acdSGreg Clayton     ResumePrivateStateThread();
575f9765acdSGreg Clayton 
576f9765acdSGreg Clayton     //KillDebugserverProcess ();
577f9765acdSGreg Clayton     return error;
578f9765acdSGreg Clayton }
579f9765acdSGreg Clayton 
580f9765acdSGreg Clayton Error
58197d5cf05SGreg Clayton ProcessKDP::WillDestroy ()
58297d5cf05SGreg Clayton {
58397d5cf05SGreg Clayton     Error error;
58497d5cf05SGreg Clayton     m_destroy_in_process = true;
58597d5cf05SGreg Clayton     return error;
58697d5cf05SGreg Clayton }
58797d5cf05SGreg Clayton 
58897d5cf05SGreg Clayton Error
589f9765acdSGreg Clayton ProcessKDP::DoDestroy ()
590f9765acdSGreg Clayton {
5917925fbbaSGreg Clayton     // For KDP there really is no difference between destroy and detach
5927925fbbaSGreg Clayton     return DoDetach();
593f9765acdSGreg Clayton }
594f9765acdSGreg Clayton 
595f9765acdSGreg Clayton //------------------------------------------------------------------
596f9765acdSGreg Clayton // Process Queries
597f9765acdSGreg Clayton //------------------------------------------------------------------
598f9765acdSGreg Clayton 
599f9765acdSGreg Clayton bool
600f9765acdSGreg Clayton ProcessKDP::IsAlive ()
601f9765acdSGreg Clayton {
602f9765acdSGreg Clayton     return m_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
603f9765acdSGreg Clayton }
604f9765acdSGreg Clayton 
605f9765acdSGreg Clayton //------------------------------------------------------------------
606f9765acdSGreg Clayton // Process Memory
607f9765acdSGreg Clayton //------------------------------------------------------------------
608f9765acdSGreg Clayton size_t
609f9765acdSGreg Clayton ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
610f9765acdSGreg Clayton {
611a63d08c9SGreg Clayton     if (m_comm.IsConnected())
612a63d08c9SGreg Clayton         return m_comm.SendRequestReadMemory (addr, buf, size, error);
613a63d08c9SGreg Clayton     error.SetErrorString ("not connected");
614f9765acdSGreg Clayton     return 0;
615f9765acdSGreg Clayton }
616f9765acdSGreg Clayton 
617f9765acdSGreg Clayton size_t
618f9765acdSGreg Clayton ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
619f9765acdSGreg Clayton {
6207925fbbaSGreg Clayton     if (m_comm.IsConnected())
6217925fbbaSGreg Clayton         return m_comm.SendRequestWriteMemory (addr, buf, size, error);
6227925fbbaSGreg Clayton     error.SetErrorString ("not connected");
623f9765acdSGreg Clayton     return 0;
624f9765acdSGreg Clayton }
625f9765acdSGreg Clayton 
626f9765acdSGreg Clayton lldb::addr_t
627f9765acdSGreg Clayton ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
628f9765acdSGreg Clayton {
629f9765acdSGreg Clayton     error.SetErrorString ("memory allocation not suppported in kdp remote debugging");
630f9765acdSGreg Clayton     return LLDB_INVALID_ADDRESS;
631f9765acdSGreg Clayton }
632f9765acdSGreg Clayton 
633f9765acdSGreg Clayton Error
634f9765acdSGreg Clayton ProcessKDP::DoDeallocateMemory (lldb::addr_t addr)
635f9765acdSGreg Clayton {
636f9765acdSGreg Clayton     Error error;
637f9765acdSGreg Clayton     error.SetErrorString ("memory deallocation not suppported in kdp remote debugging");
638f9765acdSGreg Clayton     return error;
639f9765acdSGreg Clayton }
640f9765acdSGreg Clayton 
641f9765acdSGreg Clayton Error
642f9765acdSGreg Clayton ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site)
643f9765acdSGreg Clayton {
64407e66e3eSGreg Clayton     if (m_comm.LocalBreakpointsAreSupported ())
64507e66e3eSGreg Clayton     {
64607e66e3eSGreg Clayton         Error error;
6475b88216dSGreg Clayton         if (!bp_site->IsEnabled())
6485b88216dSGreg Clayton         {
6495b88216dSGreg Clayton             if (m_comm.SendRequestBreakpoint(true, bp_site->GetLoadAddress()))
6505b88216dSGreg Clayton             {
6515b88216dSGreg Clayton                 bp_site->SetEnabled(true);
6525b88216dSGreg Clayton                 bp_site->SetType (BreakpointSite::eExternal);
6535b88216dSGreg Clayton             }
6545b88216dSGreg Clayton             else
6555b88216dSGreg Clayton             {
65607e66e3eSGreg Clayton                 error.SetErrorString ("KDP set breakpoint failed");
6575b88216dSGreg Clayton             }
6585b88216dSGreg Clayton         }
65907e66e3eSGreg Clayton         return error;
66007e66e3eSGreg Clayton     }
661f9765acdSGreg Clayton     return EnableSoftwareBreakpoint (bp_site);
662f9765acdSGreg Clayton }
663f9765acdSGreg Clayton 
664f9765acdSGreg Clayton Error
665f9765acdSGreg Clayton ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site)
666f9765acdSGreg Clayton {
66707e66e3eSGreg Clayton     if (m_comm.LocalBreakpointsAreSupported ())
66807e66e3eSGreg Clayton     {
66907e66e3eSGreg Clayton         Error error;
6705b88216dSGreg Clayton         if (bp_site->IsEnabled())
6715b88216dSGreg Clayton         {
6725b88216dSGreg Clayton             BreakpointSite::Type bp_type = bp_site->GetType();
6735b88216dSGreg Clayton             if (bp_type == BreakpointSite::eExternal)
6745b88216dSGreg Clayton             {
67597d5cf05SGreg Clayton                 if (m_destroy_in_process && m_comm.IsRunning())
67697d5cf05SGreg Clayton                 {
67797d5cf05SGreg Clayton                     // We are trying to destroy our connection and we are running
67897d5cf05SGreg Clayton                     bp_site->SetEnabled(false);
67997d5cf05SGreg Clayton                 }
68097d5cf05SGreg Clayton                 else
68197d5cf05SGreg Clayton                 {
6825b88216dSGreg Clayton                     if (m_comm.SendRequestBreakpoint(false, bp_site->GetLoadAddress()))
6835b88216dSGreg Clayton                         bp_site->SetEnabled(false);
6845b88216dSGreg Clayton                     else
68507e66e3eSGreg Clayton                         error.SetErrorString ("KDP remove breakpoint failed");
6865b88216dSGreg Clayton                 }
68797d5cf05SGreg Clayton             }
6885b88216dSGreg Clayton             else
6895b88216dSGreg Clayton             {
6905b88216dSGreg Clayton                 error = DisableSoftwareBreakpoint (bp_site);
6915b88216dSGreg Clayton             }
6925b88216dSGreg Clayton         }
69307e66e3eSGreg Clayton         return error;
69407e66e3eSGreg Clayton     }
695f9765acdSGreg Clayton     return DisableSoftwareBreakpoint (bp_site);
696f9765acdSGreg Clayton }
697f9765acdSGreg Clayton 
698f9765acdSGreg Clayton Error
69901a67860SJohnny Chen ProcessKDP::EnableWatchpoint (Watchpoint *wp)
700f9765acdSGreg Clayton {
701f9765acdSGreg Clayton     Error error;
702f9765acdSGreg Clayton     error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
703f9765acdSGreg Clayton     return error;
704f9765acdSGreg Clayton }
705f9765acdSGreg Clayton 
706f9765acdSGreg Clayton Error
70701a67860SJohnny Chen ProcessKDP::DisableWatchpoint (Watchpoint *wp)
708f9765acdSGreg Clayton {
709f9765acdSGreg Clayton     Error error;
710f9765acdSGreg Clayton     error.SetErrorString ("watchpoints are not suppported in kdp remote debugging");
711f9765acdSGreg Clayton     return error;
712f9765acdSGreg Clayton }
713f9765acdSGreg Clayton 
714f9765acdSGreg Clayton void
715f9765acdSGreg Clayton ProcessKDP::Clear()
716f9765acdSGreg Clayton {
717f9765acdSGreg Clayton     m_thread_list.Clear();
718f9765acdSGreg Clayton }
719f9765acdSGreg Clayton 
720f9765acdSGreg Clayton Error
721f9765acdSGreg Clayton ProcessKDP::DoSignal (int signo)
722f9765acdSGreg Clayton {
723f9765acdSGreg Clayton     Error error;
724f9765acdSGreg Clayton     error.SetErrorString ("sending signals is not suppported in kdp remote debugging");
725f9765acdSGreg Clayton     return error;
726f9765acdSGreg Clayton }
727f9765acdSGreg Clayton 
728f9765acdSGreg Clayton void
729f9765acdSGreg Clayton ProcessKDP::Initialize()
730f9765acdSGreg Clayton {
731f9765acdSGreg Clayton     static bool g_initialized = false;
732f9765acdSGreg Clayton 
733f9765acdSGreg Clayton     if (g_initialized == false)
734f9765acdSGreg Clayton     {
735f9765acdSGreg Clayton         g_initialized = true;
736f9765acdSGreg Clayton         PluginManager::RegisterPlugin (GetPluginNameStatic(),
737f9765acdSGreg Clayton                                        GetPluginDescriptionStatic(),
738f9765acdSGreg Clayton                                        CreateInstance);
739f9765acdSGreg Clayton 
740f9765acdSGreg Clayton         Log::Callbacks log_callbacks = {
741f9765acdSGreg Clayton             ProcessKDPLog::DisableLog,
742f9765acdSGreg Clayton             ProcessKDPLog::EnableLog,
743f9765acdSGreg Clayton             ProcessKDPLog::ListLogCategories
744f9765acdSGreg Clayton         };
745f9765acdSGreg Clayton 
746f9765acdSGreg Clayton         Log::RegisterLogChannel (ProcessKDP::GetPluginNameStatic(), log_callbacks);
747f9765acdSGreg Clayton     }
748f9765acdSGreg Clayton }
749f9765acdSGreg Clayton 
750f9765acdSGreg Clayton bool
751f9765acdSGreg Clayton ProcessKDP::StartAsyncThread ()
752f9765acdSGreg Clayton {
753f9765acdSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
754f9765acdSGreg Clayton 
755f9765acdSGreg Clayton     if (log)
7567925fbbaSGreg Clayton         log->Printf ("ProcessKDP::StartAsyncThread ()");
757f9765acdSGreg Clayton 
7587925fbbaSGreg Clayton     if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
7597925fbbaSGreg Clayton         return true;
7607925fbbaSGreg Clayton 
761f9765acdSGreg Clayton     m_async_thread = Host::ThreadCreate ("<lldb.process.kdp-remote.async>", ProcessKDP::AsyncThread, this, NULL);
762f9765acdSGreg Clayton     return IS_VALID_LLDB_HOST_THREAD(m_async_thread);
763f9765acdSGreg Clayton }
764f9765acdSGreg Clayton 
765f9765acdSGreg Clayton void
766f9765acdSGreg Clayton ProcessKDP::StopAsyncThread ()
767f9765acdSGreg Clayton {
768f9765acdSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS));
769f9765acdSGreg Clayton 
770f9765acdSGreg Clayton     if (log)
7717925fbbaSGreg Clayton         log->Printf ("ProcessKDP::StopAsyncThread ()");
772f9765acdSGreg Clayton 
773f9765acdSGreg Clayton     m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
774f9765acdSGreg Clayton 
775f9765acdSGreg Clayton     // Stop the stdio thread
776f9765acdSGreg Clayton     if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
777f9765acdSGreg Clayton     {
778f9765acdSGreg Clayton         Host::ThreadJoin (m_async_thread, NULL, NULL);
7797925fbbaSGreg Clayton         m_async_thread = LLDB_INVALID_HOST_THREAD;
780f9765acdSGreg Clayton     }
781f9765acdSGreg Clayton }
782f9765acdSGreg Clayton 
783f9765acdSGreg Clayton 
784f9765acdSGreg Clayton void *
785f9765acdSGreg Clayton ProcessKDP::AsyncThread (void *arg)
786f9765acdSGreg Clayton {
787f9765acdSGreg Clayton     ProcessKDP *process = (ProcessKDP*) arg;
788f9765acdSGreg Clayton 
7897925fbbaSGreg Clayton     const lldb::pid_t pid = process->GetID();
7907925fbbaSGreg Clayton 
791f9765acdSGreg Clayton     LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS));
792f9765acdSGreg Clayton     if (log)
7937925fbbaSGreg Clayton         log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %llu) thread starting...", arg, pid);
794f9765acdSGreg Clayton 
795f9765acdSGreg Clayton     Listener listener ("ProcessKDP::AsyncThread");
796f9765acdSGreg Clayton     EventSP event_sp;
797f9765acdSGreg Clayton     const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
798f9765acdSGreg Clayton                                         eBroadcastBitAsyncThreadShouldExit;
799f9765acdSGreg Clayton 
8007925fbbaSGreg Clayton 
801f9765acdSGreg Clayton     if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
802f9765acdSGreg Clayton     {
803f9765acdSGreg Clayton         bool done = false;
804f9765acdSGreg Clayton         while (!done)
805f9765acdSGreg Clayton         {
806f9765acdSGreg Clayton             if (log)
8077925fbbaSGreg Clayton                 log->Printf ("ProcessKDP::AsyncThread (pid = %llu) listener.WaitForEvent (NULL, event_sp)...",
8087925fbbaSGreg Clayton                              pid);
809f9765acdSGreg Clayton             if (listener.WaitForEvent (NULL, event_sp))
810f9765acdSGreg Clayton             {
8117925fbbaSGreg Clayton                 uint32_t event_type = event_sp->GetType();
812f9765acdSGreg Clayton                 if (log)
8137925fbbaSGreg Clayton                     log->Printf ("ProcessKDP::AsyncThread (pid = %llu) Got an event of type: %d...",
8147925fbbaSGreg Clayton                                  pid,
8157925fbbaSGreg Clayton                                  event_type);
816f9765acdSGreg Clayton 
8177925fbbaSGreg Clayton                 // When we are running, poll for 1 second to try and get an exception
8187925fbbaSGreg Clayton                 // to indicate the process has stopped. If we don't get one, check to
8197925fbbaSGreg Clayton                 // make sure no one asked us to exit
8207925fbbaSGreg Clayton                 bool is_running = false;
8217925fbbaSGreg Clayton                 DataExtractor exc_reply_packet;
8227925fbbaSGreg Clayton                 do
8237925fbbaSGreg Clayton                 {
824f9765acdSGreg Clayton                     switch (event_type)
825f9765acdSGreg Clayton                     {
826f9765acdSGreg Clayton                     case eBroadcastBitAsyncContinue:
827f9765acdSGreg Clayton                         {
8287925fbbaSGreg Clayton                             is_running = true;
8297925fbbaSGreg Clayton                             if (process->m_comm.WaitForPacketWithTimeoutMicroSeconds (exc_reply_packet, 1 * USEC_PER_SEC))
830f9765acdSGreg Clayton                             {
83197d5cf05SGreg Clayton                                 ThreadSP thread_sp (process->GetKernelThread(process->GetThreadList(), process->GetThreadList()));
83297d5cf05SGreg Clayton                                 thread_sp->GetRegisterContext()->InvalidateAllRegisters();
83397d5cf05SGreg Clayton                                 static_cast<ThreadKDP *>(thread_sp.get())->SetStopInfoFrom_KDP_EXCEPTION (exc_reply_packet);
83497d5cf05SGreg Clayton 
8357925fbbaSGreg Clayton                                 // TODO: parse the stop reply packet
8367925fbbaSGreg Clayton                                 is_running = false;
8377925fbbaSGreg Clayton                                 process->SetPrivateState(eStateStopped);
8387925fbbaSGreg Clayton                             }
8397925fbbaSGreg Clayton                             else
8407925fbbaSGreg Clayton                             {
8417925fbbaSGreg Clayton                                 // Check to see if we are supposed to exit. There is no way to
8427925fbbaSGreg Clayton                                 // interrupt a running kernel, so all we can do is wait for an
8437925fbbaSGreg Clayton                                 // exception or detach...
8447925fbbaSGreg Clayton                                 if (listener.GetNextEvent(event_sp))
8457925fbbaSGreg Clayton                                 {
8467925fbbaSGreg Clayton                                     // We got an event, go through the loop again
8477925fbbaSGreg Clayton                                     event_type = event_sp->GetType();
8487925fbbaSGreg Clayton                                 }
849f9765acdSGreg Clayton                             }
850f9765acdSGreg Clayton                         }
851f9765acdSGreg Clayton                         break;
852f9765acdSGreg Clayton 
853f9765acdSGreg Clayton                     case eBroadcastBitAsyncThreadShouldExit:
854f9765acdSGreg Clayton                         if (log)
8557925fbbaSGreg Clayton                             log->Printf ("ProcessKDP::AsyncThread (pid = %llu) got eBroadcastBitAsyncThreadShouldExit...",
8567925fbbaSGreg Clayton                                          pid);
857f9765acdSGreg Clayton                         done = true;
8587925fbbaSGreg Clayton                         is_running = false;
859f9765acdSGreg Clayton                         break;
860f9765acdSGreg Clayton 
861f9765acdSGreg Clayton                     default:
862f9765acdSGreg Clayton                         if (log)
8637925fbbaSGreg Clayton                             log->Printf ("ProcessKDP::AsyncThread (pid = %llu) got unknown event 0x%8.8x",
8647925fbbaSGreg Clayton                                          pid,
8657925fbbaSGreg Clayton                                          event_type);
866f9765acdSGreg Clayton                         done = true;
8677925fbbaSGreg Clayton                         is_running = false;
868f9765acdSGreg Clayton                         break;
869f9765acdSGreg Clayton                     }
8707925fbbaSGreg Clayton                 } while (is_running);
871f9765acdSGreg Clayton             }
872f9765acdSGreg Clayton             else
873f9765acdSGreg Clayton             {
874f9765acdSGreg Clayton                 if (log)
8757925fbbaSGreg Clayton                     log->Printf ("ProcessKDP::AsyncThread (pid = %llu) listener.WaitForEvent (NULL, event_sp) => false",
8767925fbbaSGreg Clayton                                  pid);
877f9765acdSGreg Clayton                 done = true;
878f9765acdSGreg Clayton             }
879f9765acdSGreg Clayton         }
880f9765acdSGreg Clayton     }
881f9765acdSGreg Clayton 
882f9765acdSGreg Clayton     if (log)
8837925fbbaSGreg Clayton         log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %llu) thread exiting...",
8847925fbbaSGreg Clayton                      arg,
8857925fbbaSGreg Clayton                      pid);
886f9765acdSGreg Clayton 
887f9765acdSGreg Clayton     process->m_async_thread = LLDB_INVALID_HOST_THREAD;
888f9765acdSGreg Clayton     return NULL;
889f9765acdSGreg Clayton }
890f9765acdSGreg Clayton 
891f9765acdSGreg Clayton 
892