1*8a203bb2SWalter Erquinigo //===-- ProcessTrace.cpp --------------------------------------------------===//
2*8a203bb2SWalter Erquinigo //
3*8a203bb2SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*8a203bb2SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
5*8a203bb2SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*8a203bb2SWalter Erquinigo //
7*8a203bb2SWalter Erquinigo //===----------------------------------------------------------------------===//
8*8a203bb2SWalter Erquinigo 
9*8a203bb2SWalter Erquinigo #include "lldb/Target/ProcessTrace.h"
10*8a203bb2SWalter Erquinigo 
11*8a203bb2SWalter Erquinigo #include <memory>
12*8a203bb2SWalter Erquinigo 
13*8a203bb2SWalter Erquinigo #include "lldb/Core/Module.h"
14*8a203bb2SWalter Erquinigo #include "lldb/Core/PluginManager.h"
15*8a203bb2SWalter Erquinigo #include "lldb/Target/Target.h"
16*8a203bb2SWalter Erquinigo 
17*8a203bb2SWalter Erquinigo using namespace lldb;
18*8a203bb2SWalter Erquinigo using namespace lldb_private;
19*8a203bb2SWalter Erquinigo 
20*8a203bb2SWalter Erquinigo ConstString ProcessTrace::GetPluginNameStatic() {
21*8a203bb2SWalter Erquinigo   static ConstString g_name("trace");
22*8a203bb2SWalter Erquinigo   return g_name;
23*8a203bb2SWalter Erquinigo }
24*8a203bb2SWalter Erquinigo 
25*8a203bb2SWalter Erquinigo const char *ProcessTrace::GetPluginDescriptionStatic() {
26*8a203bb2SWalter Erquinigo   return "Trace process plug-in.";
27*8a203bb2SWalter Erquinigo }
28*8a203bb2SWalter Erquinigo 
29*8a203bb2SWalter Erquinigo void ProcessTrace::Terminate() {
30*8a203bb2SWalter Erquinigo   PluginManager::UnregisterPlugin(ProcessTrace::CreateInstance);
31*8a203bb2SWalter Erquinigo }
32*8a203bb2SWalter Erquinigo 
33*8a203bb2SWalter Erquinigo ProcessSP ProcessTrace::CreateInstance(TargetSP target_sp,
34*8a203bb2SWalter Erquinigo                                        ListenerSP listener_sp,
35*8a203bb2SWalter Erquinigo                                        const FileSpec *crash_file) {
36*8a203bb2SWalter Erquinigo   return std::make_shared<ProcessTrace>(target_sp, listener_sp);
37*8a203bb2SWalter Erquinigo }
38*8a203bb2SWalter Erquinigo 
39*8a203bb2SWalter Erquinigo bool ProcessTrace::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) {
40*8a203bb2SWalter Erquinigo   return plugin_specified_by_name;
41*8a203bb2SWalter Erquinigo }
42*8a203bb2SWalter Erquinigo 
43*8a203bb2SWalter Erquinigo ProcessTrace::ProcessTrace(TargetSP target_sp, ListenerSP listener_sp)
44*8a203bb2SWalter Erquinigo     : Process(target_sp, listener_sp) {}
45*8a203bb2SWalter Erquinigo 
46*8a203bb2SWalter Erquinigo ProcessTrace::~ProcessTrace() {
47*8a203bb2SWalter Erquinigo   Clear();
48*8a203bb2SWalter Erquinigo   // We need to call finalize on the process before destroying ourselves to
49*8a203bb2SWalter Erquinigo   // make sure all of the broadcaster cleanup goes as planned. If we destruct
50*8a203bb2SWalter Erquinigo   // this class, then Process::~Process() might have problems trying to fully
51*8a203bb2SWalter Erquinigo   // destroy the broadcaster.
52*8a203bb2SWalter Erquinigo   Finalize();
53*8a203bb2SWalter Erquinigo }
54*8a203bb2SWalter Erquinigo 
55*8a203bb2SWalter Erquinigo ConstString ProcessTrace::GetPluginName() { return GetPluginNameStatic(); }
56*8a203bb2SWalter Erquinigo 
57*8a203bb2SWalter Erquinigo uint32_t ProcessTrace::GetPluginVersion() { return 1; }
58*8a203bb2SWalter Erquinigo 
59*8a203bb2SWalter Erquinigo void ProcessTrace::DidAttach(ArchSpec &process_arch) {
60*8a203bb2SWalter Erquinigo   ListenerSP listener_sp(
61*8a203bb2SWalter Erquinigo       Listener::MakeListener("lldb.process_trace.did_attach_listener"));
62*8a203bb2SWalter Erquinigo   HijackProcessEvents(listener_sp);
63*8a203bb2SWalter Erquinigo 
64*8a203bb2SWalter Erquinigo   SetCanJIT(false);
65*8a203bb2SWalter Erquinigo   StartPrivateStateThread();
66*8a203bb2SWalter Erquinigo   SetPrivateState(eStateStopped);
67*8a203bb2SWalter Erquinigo 
68*8a203bb2SWalter Erquinigo   EventSP event_sp;
69*8a203bb2SWalter Erquinigo   WaitForProcessToStop(llvm::None, &event_sp, true, listener_sp);
70*8a203bb2SWalter Erquinigo 
71*8a203bb2SWalter Erquinigo   RestoreProcessEvents();
72*8a203bb2SWalter Erquinigo 
73*8a203bb2SWalter Erquinigo   Process::DidAttach(process_arch);
74*8a203bb2SWalter Erquinigo }
75*8a203bb2SWalter Erquinigo 
76*8a203bb2SWalter Erquinigo bool ProcessTrace::UpdateThreadList(ThreadList &old_thread_list,
77*8a203bb2SWalter Erquinigo                                     ThreadList &new_thread_list) {
78*8a203bb2SWalter Erquinigo   return false;
79*8a203bb2SWalter Erquinigo }
80*8a203bb2SWalter Erquinigo 
81*8a203bb2SWalter Erquinigo void ProcessTrace::RefreshStateAfterStop() {}
82*8a203bb2SWalter Erquinigo 
83*8a203bb2SWalter Erquinigo Status ProcessTrace::DoDestroy() { return Status(); }
84*8a203bb2SWalter Erquinigo 
85*8a203bb2SWalter Erquinigo bool ProcessTrace::IsAlive() { return true; }
86*8a203bb2SWalter Erquinigo 
87*8a203bb2SWalter Erquinigo size_t ProcessTrace::ReadMemory(addr_t addr, void *buf, size_t size,
88*8a203bb2SWalter Erquinigo                                 Status &error) {
89*8a203bb2SWalter Erquinigo   // Don't allow the caching that lldb_private::Process::ReadMemory does since
90*8a203bb2SWalter Erquinigo   // we have it all cached in the trace files.
91*8a203bb2SWalter Erquinigo   return DoReadMemory(addr, buf, size, error);
92*8a203bb2SWalter Erquinigo }
93*8a203bb2SWalter Erquinigo 
94*8a203bb2SWalter Erquinigo void ProcessTrace::Clear() { m_thread_list.Clear(); }
95*8a203bb2SWalter Erquinigo 
96*8a203bb2SWalter Erquinigo void ProcessTrace::Initialize() {
97*8a203bb2SWalter Erquinigo   static llvm::once_flag g_once_flag;
98*8a203bb2SWalter Erquinigo 
99*8a203bb2SWalter Erquinigo   llvm::call_once(g_once_flag, []() {
100*8a203bb2SWalter Erquinigo     PluginManager::RegisterPlugin(GetPluginNameStatic(),
101*8a203bb2SWalter Erquinigo                                   GetPluginDescriptionStatic(), CreateInstance);
102*8a203bb2SWalter Erquinigo   });
103*8a203bb2SWalter Erquinigo }
104*8a203bb2SWalter Erquinigo 
105*8a203bb2SWalter Erquinigo ArchSpec ProcessTrace::GetArchitecture() {
106*8a203bb2SWalter Erquinigo   return GetTarget().GetArchitecture();
107*8a203bb2SWalter Erquinigo }
108*8a203bb2SWalter Erquinigo 
109*8a203bb2SWalter Erquinigo bool ProcessTrace::GetProcessInfo(ProcessInstanceInfo &info) {
110*8a203bb2SWalter Erquinigo   info.Clear();
111*8a203bb2SWalter Erquinigo   info.SetProcessID(GetID());
112*8a203bb2SWalter Erquinigo   info.SetArchitecture(GetArchitecture());
113*8a203bb2SWalter Erquinigo   ModuleSP module_sp = GetTarget().GetExecutableModule();
114*8a203bb2SWalter Erquinigo   if (module_sp) {
115*8a203bb2SWalter Erquinigo     const bool add_exe_file_as_first_arg = false;
116*8a203bb2SWalter Erquinigo     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
117*8a203bb2SWalter Erquinigo                            add_exe_file_as_first_arg);
118*8a203bb2SWalter Erquinigo   }
119*8a203bb2SWalter Erquinigo   return true;
120*8a203bb2SWalter Erquinigo }
121*8a203bb2SWalter Erquinigo 
122*8a203bb2SWalter Erquinigo size_t ProcessTrace::DoReadMemory(addr_t addr, void *buf, size_t size,
123*8a203bb2SWalter Erquinigo                                   Status &error) {
124*8a203bb2SWalter Erquinigo   return 0;
125*8a203bb2SWalter Erquinigo }
126