1 //===-- ProcessLinux.cpp ----------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 #include <errno.h>
12
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/State.h"
17 #include "lldb/Host/Host.h"
18 #include "lldb/Symbol/ObjectFile.h"
19 #include "lldb/Target/DynamicLoader.h"
20 #include "lldb/Target/Target.h"
21
22 #include "ProcessLinux.h"
23 #include "ProcessPOSIXLog.h"
24 #include "Plugins/Process/Utility/InferiorCallPOSIX.h"
25 #include "ProcessMonitor.h"
26 #include "LinuxThread.h"
27
28 using namespace lldb;
29 using namespace lldb_private;
30
31 //------------------------------------------------------------------------------
32 // Static functions.
33
34 ProcessSP
CreateInstance(Target & target,Listener & listener,const FileSpec * core_file)35 ProcessLinux::CreateInstance(Target &target, Listener &listener, const FileSpec *core_file)
36 {
37 return ProcessSP(new ProcessLinux(target, listener, (FileSpec *)core_file));
38 }
39
40 void
Initialize()41 ProcessLinux::Initialize()
42 {
43 static bool g_initialized = false;
44
45 if (!g_initialized)
46 {
47 g_initialized = true;
48 PluginManager::RegisterPlugin(GetPluginNameStatic(),
49 GetPluginDescriptionStatic(),
50 CreateInstance);
51
52 Log::Callbacks log_callbacks = {
53 ProcessPOSIXLog::DisableLog,
54 ProcessPOSIXLog::EnableLog,
55 ProcessPOSIXLog::ListLogCategories
56 };
57
58 Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks);
59 ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic());
60 }
61 }
62
63 //------------------------------------------------------------------------------
64 // Constructors and destructors.
65
ProcessLinux(Target & target,Listener & listener,FileSpec * core_file)66 ProcessLinux::ProcessLinux(Target& target, Listener &listener, FileSpec *core_file)
67 : ProcessPOSIX(target, listener), m_core_file(core_file), m_stopping_threads(false)
68 {
69 #if 0
70 // FIXME: Putting this code in the ctor and saving the byte order in a
71 // member variable is a hack to avoid const qual issues in GetByteOrder.
72 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
73 m_byte_order = obj_file->GetByteOrder();
74 #else
75 // XXX: Will work only for local processes.
76 m_byte_order = lldb::endian::InlHostByteOrder();
77 #endif
78 }
79
80 void
Terminate()81 ProcessLinux::Terminate()
82 {
83 }
84
85 lldb_private::ConstString
GetPluginNameStatic()86 ProcessLinux::GetPluginNameStatic()
87 {
88 static ConstString g_name("linux");
89 return g_name;
90 }
91
92 const char *
GetPluginDescriptionStatic()93 ProcessLinux::GetPluginDescriptionStatic()
94 {
95 return "Process plugin for Linux";
96 }
97
98
99 bool
UpdateThreadList(ThreadList & old_thread_list,ThreadList & new_thread_list)100 ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
101 {
102 new_thread_list = old_thread_list;
103 return new_thread_list.GetSize(false) > 0;
104 }
105
106
107 //------------------------------------------------------------------------------
108 // ProcessInterface protocol.
109
110 lldb_private::ConstString
GetPluginName()111 ProcessLinux::GetPluginName()
112 {
113 return GetPluginNameStatic();
114 }
115
116 uint32_t
GetPluginVersion()117 ProcessLinux::GetPluginVersion()
118 {
119 return 1;
120 }
121
122 void
GetPluginCommandHelp(const char * command,Stream * strm)123 ProcessLinux::GetPluginCommandHelp(const char *command, Stream *strm)
124 {
125 }
126
127 Error
ExecutePluginCommand(Args & command,Stream * strm)128 ProcessLinux::ExecutePluginCommand(Args &command, Stream *strm)
129 {
130 return Error(1, eErrorTypeGeneric);
131 }
132
133 Log *
EnablePluginLogging(Stream * strm,Args & command)134 ProcessLinux::EnablePluginLogging(Stream *strm, Args &command)
135 {
136 return NULL;
137 }
138
139 // ProcessPOSIX override
140 void
StopAllThreads(lldb::tid_t stop_tid)141 ProcessLinux::StopAllThreads(lldb::tid_t stop_tid)
142 {
143 // If a breakpoint occurs while we're stopping threads, we'll get back
144 // here, but we don't want to do it again. Only the MonitorChildProcess
145 // thread calls this function, so we don't need to protect this flag.
146 if (m_stopping_threads)
147 return;
148 m_stopping_threads = true;
149
150 Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
151 if (log)
152 log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__);
153
154 // Walk the thread list and stop the other threads. The thread that caused
155 // the stop should already be marked as stopped before we get here.
156 Mutex::Locker thread_list_lock(m_thread_list.GetMutex());
157
158 uint32_t thread_count = m_thread_list.GetSize(false);
159 for (uint32_t i = 0; i < thread_count; ++i)
160 {
161 POSIXThread *thread = static_cast<POSIXThread*>(
162 m_thread_list.GetThreadAtIndex(i, false).get());
163 assert(thread);
164 lldb::tid_t tid = thread->GetID();
165 if (!StateIsStoppedState(thread->GetState(), false))
166 m_monitor->StopThread(tid);
167 }
168
169 m_stopping_threads = false;
170
171 if (log)
172 log->Printf ("ProcessLinux::%s() finished", __FUNCTION__);
173 }
174
175 // ProcessPOSIX override
176 POSIXThread *
CreateNewPOSIXThread(lldb_private::Process & process,lldb::tid_t tid)177 ProcessLinux::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
178 {
179 return new LinuxThread(process, tid);
180 }
181
182 bool
CanDebug(Target & target,bool plugin_specified_by_name)183 ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name)
184 {
185 if (plugin_specified_by_name)
186 return true;
187
188 /* If core file is specified then let elf-core plugin handle it */
189 if (m_core_file)
190 return false;
191
192 return ProcessPOSIX::CanDebug(target, plugin_specified_by_name);
193 }
194
195