1 //===-- OperatingSystemPython.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 #ifndef LLDB_DISABLE_PYTHON
11
12 #include "OperatingSystemPython.h"
13 #include "Plugins/Process/Utility/DynamicRegisterInfo.h"
14 #include "Plugins/Process/Utility/RegisterContextDummy.h"
15 #include "Plugins/Process/Utility/RegisterContextMemory.h"
16 #include "Plugins/Process/Utility/ThreadMemory.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/PluginManager.h"
20 #include "lldb/Core/ValueObjectVariable.h"
21 #include "lldb/Interpreter/CommandInterpreter.h"
22 #include "lldb/Interpreter/ScriptInterpreter.h"
23 #include "lldb/Symbol/ObjectFile.h"
24 #include "lldb/Symbol/VariableList.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/StopInfo.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/Thread.h"
29 #include "lldb/Target/ThreadList.h"
30 #include "lldb/Utility/DataBufferHeap.h"
31 #include "lldb/Utility/RegisterValue.h"
32 #include "lldb/Utility/StreamString.h"
33 #include "lldb/Utility/StructuredData.h"
34
35 using namespace lldb;
36 using namespace lldb_private;
37
Initialize()38 void OperatingSystemPython::Initialize() {
39 PluginManager::RegisterPlugin(GetPluginNameStatic(),
40 GetPluginDescriptionStatic(), CreateInstance,
41 nullptr);
42 }
43
Terminate()44 void OperatingSystemPython::Terminate() {
45 PluginManager::UnregisterPlugin(CreateInstance);
46 }
47
CreateInstance(Process * process,bool force)48 OperatingSystem *OperatingSystemPython::CreateInstance(Process *process,
49 bool force) {
50 // Python OperatingSystem plug-ins must be requested by name, so force must
51 // be true
52 FileSpec python_os_plugin_spec(process->GetPythonOSPluginPath());
53 if (python_os_plugin_spec &&
54 FileSystem::Instance().Exists(python_os_plugin_spec)) {
55 std::unique_ptr<OperatingSystemPython> os_ap(
56 new OperatingSystemPython(process, python_os_plugin_spec));
57 if (os_ap.get() && os_ap->IsValid())
58 return os_ap.release();
59 }
60 return NULL;
61 }
62
GetPluginNameStatic()63 ConstString OperatingSystemPython::GetPluginNameStatic() {
64 static ConstString g_name("python");
65 return g_name;
66 }
67
GetPluginDescriptionStatic()68 const char *OperatingSystemPython::GetPluginDescriptionStatic() {
69 return "Operating system plug-in that gathers OS information from a python "
70 "class that implements the necessary OperatingSystem functionality.";
71 }
72
OperatingSystemPython(lldb_private::Process * process,const FileSpec & python_module_path)73 OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
74 const FileSpec &python_module_path)
75 : OperatingSystem(process), m_thread_list_valobj_sp(), m_register_info_ap(),
76 m_interpreter(NULL), m_python_object_sp() {
77 if (!process)
78 return;
79 TargetSP target_sp = process->CalculateTarget();
80 if (!target_sp)
81 return;
82 m_interpreter =
83 target_sp->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
84 if (m_interpreter) {
85
86 std::string os_plugin_class_name(
87 python_module_path.GetFilename().AsCString(""));
88 if (!os_plugin_class_name.empty()) {
89 const bool init_session = false;
90 const bool allow_reload = true;
91 char python_module_path_cstr[PATH_MAX];
92 python_module_path.GetPath(python_module_path_cstr,
93 sizeof(python_module_path_cstr));
94 Status error;
95 if (m_interpreter->LoadScriptingModule(
96 python_module_path_cstr, allow_reload, init_session, error)) {
97 // Strip the ".py" extension if there is one
98 size_t py_extension_pos = os_plugin_class_name.rfind(".py");
99 if (py_extension_pos != std::string::npos)
100 os_plugin_class_name.erase(py_extension_pos);
101 // Add ".OperatingSystemPlugIn" to the module name to get a string like
102 // "modulename.OperatingSystemPlugIn"
103 os_plugin_class_name += ".OperatingSystemPlugIn";
104 StructuredData::ObjectSP object_sp =
105 m_interpreter->OSPlugin_CreatePluginObject(
106 os_plugin_class_name.c_str(), process->CalculateProcess());
107 if (object_sp && object_sp->IsValid())
108 m_python_object_sp = object_sp;
109 }
110 }
111 }
112 }
113
~OperatingSystemPython()114 OperatingSystemPython::~OperatingSystemPython() {}
115
GetDynamicRegisterInfo()116 DynamicRegisterInfo *OperatingSystemPython::GetDynamicRegisterInfo() {
117 if (m_register_info_ap.get() == NULL) {
118 if (!m_interpreter || !m_python_object_sp)
119 return NULL;
120 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
121
122 if (log)
123 log->Printf("OperatingSystemPython::GetDynamicRegisterInfo() fetching "
124 "thread register definitions from python for pid %" PRIu64,
125 m_process->GetID());
126
127 StructuredData::DictionarySP dictionary =
128 m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp);
129 if (!dictionary)
130 return NULL;
131
132 m_register_info_ap.reset(new DynamicRegisterInfo(
133 *dictionary, m_process->GetTarget().GetArchitecture()));
134 assert(m_register_info_ap->GetNumRegisters() > 0);
135 assert(m_register_info_ap->GetNumRegisterSets() > 0);
136 }
137 return m_register_info_ap.get();
138 }
139
140 //------------------------------------------------------------------
141 // PluginInterface protocol
142 //------------------------------------------------------------------
GetPluginName()143 ConstString OperatingSystemPython::GetPluginName() {
144 return GetPluginNameStatic();
145 }
146
GetPluginVersion()147 uint32_t OperatingSystemPython::GetPluginVersion() { return 1; }
148
UpdateThreadList(ThreadList & old_thread_list,ThreadList & core_thread_list,ThreadList & new_thread_list)149 bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
150 ThreadList &core_thread_list,
151 ThreadList &new_thread_list) {
152 if (!m_interpreter || !m_python_object_sp)
153 return false;
154
155 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
156
157 // First thing we have to do is to try to get the API lock, and the
158 // interpreter lock. We're going to change the thread content of the process,
159 // and we're going to use python, which requires the API lock to do it. We
160 // need the interpreter lock to make sure thread_info_dict stays alive.
161 //
162 // If someone already has the API lock, that is ok, we just want to avoid
163 // external code from making new API calls while this call is happening.
164 //
165 // This is a recursive lock so we can grant it to any Python code called on
166 // the stack below us.
167 Target &target = m_process->GetTarget();
168 std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
169 std::defer_lock);
170 api_lock.try_lock();
171 auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
172
173 if (log)
174 log->Printf("OperatingSystemPython::UpdateThreadList() fetching thread "
175 "data from python for pid %" PRIu64,
176 m_process->GetID());
177
178 // The threads that are in "new_thread_list" upon entry are the threads from
179 // the lldb_private::Process subclass, no memory threads will be in this
180 // list.
181 StructuredData::ArraySP threads_list =
182 m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp);
183
184 const uint32_t num_cores = core_thread_list.GetSize(false);
185
186 // Make a map so we can keep track of which cores were used from the
187 // core_thread list. Any real threads/cores that weren't used should later be
188 // put back into the "new_thread_list".
189 std::vector<bool> core_used_map(num_cores, false);
190 if (threads_list) {
191 if (log) {
192 StreamString strm;
193 threads_list->Dump(strm);
194 log->Printf("threads_list = %s", strm.GetData());
195 }
196
197 const uint32_t num_threads = threads_list->GetSize();
198 for (uint32_t i = 0; i < num_threads; ++i) {
199 StructuredData::ObjectSP thread_dict_obj =
200 threads_list->GetItemAtIndex(i);
201 if (auto thread_dict = thread_dict_obj->GetAsDictionary()) {
202 ThreadSP thread_sp(
203 CreateThreadFromThreadInfo(*thread_dict, core_thread_list,
204 old_thread_list, core_used_map, NULL));
205 if (thread_sp)
206 new_thread_list.AddThread(thread_sp);
207 }
208 }
209 }
210
211 // Any real core threads that didn't end up backing a memory thread should
212 // still be in the main thread list, and they should be inserted at the
213 // beginning of the list
214 uint32_t insert_idx = 0;
215 for (uint32_t core_idx = 0; core_idx < num_cores; ++core_idx) {
216 if (!core_used_map[core_idx]) {
217 new_thread_list.InsertThread(
218 core_thread_list.GetThreadAtIndex(core_idx, false), insert_idx);
219 ++insert_idx;
220 }
221 }
222
223 return new_thread_list.GetSize(false) > 0;
224 }
225
CreateThreadFromThreadInfo(StructuredData::Dictionary & thread_dict,ThreadList & core_thread_list,ThreadList & old_thread_list,std::vector<bool> & core_used_map,bool * did_create_ptr)226 ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo(
227 StructuredData::Dictionary &thread_dict, ThreadList &core_thread_list,
228 ThreadList &old_thread_list, std::vector<bool> &core_used_map,
229 bool *did_create_ptr) {
230 ThreadSP thread_sp;
231 tid_t tid = LLDB_INVALID_THREAD_ID;
232 if (!thread_dict.GetValueForKeyAsInteger("tid", tid))
233 return ThreadSP();
234
235 uint32_t core_number;
236 addr_t reg_data_addr;
237 llvm::StringRef name;
238 llvm::StringRef queue;
239
240 thread_dict.GetValueForKeyAsInteger("core", core_number, UINT32_MAX);
241 thread_dict.GetValueForKeyAsInteger("register_data_addr", reg_data_addr,
242 LLDB_INVALID_ADDRESS);
243 thread_dict.GetValueForKeyAsString("name", name);
244 thread_dict.GetValueForKeyAsString("queue", queue);
245
246 // See if a thread already exists for "tid"
247 thread_sp = old_thread_list.FindThreadByID(tid, false);
248 if (thread_sp) {
249 // A thread already does exist for "tid", make sure it was an operating
250 // system
251 // plug-in generated thread.
252 if (!IsOperatingSystemPluginThread(thread_sp)) {
253 // We have thread ID overlap between the protocol threads and the
254 // operating system threads, clear the thread so we create an operating
255 // system thread for this.
256 thread_sp.reset();
257 }
258 }
259
260 if (!thread_sp) {
261 if (did_create_ptr)
262 *did_create_ptr = true;
263 thread_sp.reset(
264 new ThreadMemory(*m_process, tid, name, queue, reg_data_addr));
265 }
266
267 if (core_number < core_thread_list.GetSize(false)) {
268 ThreadSP core_thread_sp(
269 core_thread_list.GetThreadAtIndex(core_number, false));
270 if (core_thread_sp) {
271 // Keep track of which cores were set as the backing thread for memory
272 // threads...
273 if (core_number < core_used_map.size())
274 core_used_map[core_number] = true;
275
276 ThreadSP backing_core_thread_sp(core_thread_sp->GetBackingThread());
277 if (backing_core_thread_sp) {
278 thread_sp->SetBackingThread(backing_core_thread_sp);
279 } else {
280 thread_sp->SetBackingThread(core_thread_sp);
281 }
282 }
283 }
284 return thread_sp;
285 }
286
ThreadWasSelected(Thread * thread)287 void OperatingSystemPython::ThreadWasSelected(Thread *thread) {}
288
289 RegisterContextSP
CreateRegisterContextForThread(Thread * thread,addr_t reg_data_addr)290 OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
291 addr_t reg_data_addr) {
292 RegisterContextSP reg_ctx_sp;
293 if (!m_interpreter || !m_python_object_sp || !thread)
294 return reg_ctx_sp;
295
296 if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
297 return reg_ctx_sp;
298
299 // First thing we have to do is to try to get the API lock, and the
300 // interpreter lock. We're going to change the thread content of the process,
301 // and we're going to use python, which requires the API lock to do it. We
302 // need the interpreter lock to make sure thread_info_dict stays alive.
303 //
304 // If someone already has the API lock, that is ok, we just want to avoid
305 // external code from making new API calls while this call is happening.
306 //
307 // This is a recursive lock so we can grant it to any Python code called on
308 // the stack below us.
309 Target &target = m_process->GetTarget();
310 std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
311 std::defer_lock);
312 api_lock.try_lock();
313 auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
314
315 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
316
317 if (reg_data_addr != LLDB_INVALID_ADDRESS) {
318 // The registers data is in contiguous memory, just create the register
319 // context using the address provided
320 if (log)
321 log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid "
322 "= 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64
323 ") creating memory register context",
324 thread->GetID(), thread->GetProtocolID(), reg_data_addr);
325 reg_ctx_sp.reset(new RegisterContextMemory(
326 *thread, 0, *GetDynamicRegisterInfo(), reg_data_addr));
327 } else {
328 // No register data address is provided, query the python plug-in to let it
329 // make up the data as it sees fit
330 if (log)
331 log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid "
332 "= 0x%" PRIx64 ", 0x%" PRIx64
333 ") fetching register data from python",
334 thread->GetID(), thread->GetProtocolID());
335
336 StructuredData::StringSP reg_context_data =
337 m_interpreter->OSPlugin_RegisterContextData(m_python_object_sp,
338 thread->GetID());
339 if (reg_context_data) {
340 std::string value = reg_context_data->GetValue();
341 DataBufferSP data_sp(new DataBufferHeap(value.c_str(), value.length()));
342 if (data_sp->GetByteSize()) {
343 RegisterContextMemory *reg_ctx_memory = new RegisterContextMemory(
344 *thread, 0, *GetDynamicRegisterInfo(), LLDB_INVALID_ADDRESS);
345 if (reg_ctx_memory) {
346 reg_ctx_sp.reset(reg_ctx_memory);
347 reg_ctx_memory->SetAllRegisterData(data_sp);
348 }
349 }
350 }
351 }
352 // if we still have no register data, fallback on a dummy context to avoid
353 // crashing
354 if (!reg_ctx_sp) {
355 if (log)
356 log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid "
357 "= 0x%" PRIx64 ") forcing a dummy register context",
358 thread->GetID());
359 reg_ctx_sp.reset(new RegisterContextDummy(
360 *thread, 0, target.GetArchitecture().GetAddressByteSize()));
361 }
362 return reg_ctx_sp;
363 }
364
365 StopInfoSP
CreateThreadStopReason(lldb_private::Thread * thread)366 OperatingSystemPython::CreateThreadStopReason(lldb_private::Thread *thread) {
367 // We should have gotten the thread stop info from the dictionary of data for
368 // the thread in the initial call to get_thread_info(), this should have been
369 // cached so we can return it here
370 StopInfoSP
371 stop_info_sp; //(StopInfo::CreateStopReasonWithSignal (*thread, SIGSTOP));
372 return stop_info_sp;
373 }
374
CreateThread(lldb::tid_t tid,addr_t context)375 lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
376 addr_t context) {
377 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
378
379 if (log)
380 log->Printf("OperatingSystemPython::CreateThread (tid = 0x%" PRIx64
381 ", context = 0x%" PRIx64 ") fetching register data from python",
382 tid, context);
383
384 if (m_interpreter && m_python_object_sp) {
385 // First thing we have to do is to try to get the API lock, and the
386 // interpreter lock. We're going to change the thread content of the
387 // process, and we're going to use python, which requires the API lock to
388 // do it. We need the interpreter lock to make sure thread_info_dict stays
389 // alive.
390 //
391 // If someone already has the API lock, that is ok, we just want to avoid
392 // external code from making new API calls while this call is happening.
393 //
394 // This is a recursive lock so we can grant it to any Python code called on
395 // the stack below us.
396 Target &target = m_process->GetTarget();
397 std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
398 std::defer_lock);
399 api_lock.try_lock();
400 auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
401
402 StructuredData::DictionarySP thread_info_dict =
403 m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context);
404 std::vector<bool> core_used_map;
405 if (thread_info_dict) {
406 ThreadList core_threads(m_process);
407 ThreadList &thread_list = m_process->GetThreadList();
408 bool did_create = false;
409 ThreadSP thread_sp(
410 CreateThreadFromThreadInfo(*thread_info_dict, core_threads,
411 thread_list, core_used_map, &did_create));
412 if (did_create)
413 thread_list.AddThread(thread_sp);
414 return thread_sp;
415 }
416 }
417 return ThreadSP();
418 }
419
420 #endif // #ifndef LLDB_DISABLE_PYTHON
421