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