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