1 //===-- SBProcess.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 #include "lldb/lldb-python.h"
11 
12 #include "lldb/API/SBProcess.h"
13 
14 // C Includes
15 #include <inttypes.h>
16 
17 #include "lldb/lldb-defines.h"
18 #include "lldb/lldb-types.h"
19 
20 #include "lldb/Interpreter/Args.h"
21 #include "lldb/Core/Debugger.h"
22 #include "lldb/Core/Log.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/State.h"
25 #include "lldb/Core/Stream.h"
26 #include "lldb/Core/StreamFile.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/RegisterContext.h"
29 #include "lldb/Target/SystemRuntime.h"
30 #include "lldb/Target/Target.h"
31 #include "lldb/Target/Thread.h"
32 
33 // Project includes
34 
35 #include "lldb/API/SBBroadcaster.h"
36 #include "lldb/API/SBCommandReturnObject.h"
37 #include "lldb/API/SBDebugger.h"
38 #include "lldb/API/SBEvent.h"
39 #include "lldb/API/SBFileSpec.h"
40 #include "lldb/API/SBThread.h"
41 #include "lldb/API/SBStream.h"
42 #include "lldb/API/SBStringList.h"
43 #include "lldb/API/SBUnixSignals.h"
44 
45 using namespace lldb;
46 using namespace lldb_private;
47 
48 
49 SBProcess::SBProcess () :
50     m_opaque_wp()
51 {
52 }
53 
54 
55 //----------------------------------------------------------------------
56 // SBProcess constructor
57 //----------------------------------------------------------------------
58 
59 SBProcess::SBProcess (const SBProcess& rhs) :
60     m_opaque_wp (rhs.m_opaque_wp)
61 {
62 }
63 
64 
65 SBProcess::SBProcess (const lldb::ProcessSP &process_sp) :
66     m_opaque_wp (process_sp)
67 {
68 }
69 
70 const SBProcess&
71 SBProcess::operator = (const SBProcess& rhs)
72 {
73     if (this != &rhs)
74         m_opaque_wp = rhs.m_opaque_wp;
75     return *this;
76 }
77 
78 //----------------------------------------------------------------------
79 // Destructor
80 //----------------------------------------------------------------------
81 SBProcess::~SBProcess()
82 {
83 }
84 
85 const char *
86 SBProcess::GetBroadcasterClassName ()
87 {
88     return Process::GetStaticBroadcasterClass().AsCString();
89 }
90 
91 const char *
92 SBProcess::GetPluginName ()
93 {
94     ProcessSP process_sp(GetSP());
95     if (process_sp)
96     {
97         return process_sp->GetPluginName().GetCString();
98     }
99     return "<Unknown>";
100 }
101 
102 const char *
103 SBProcess::GetShortPluginName ()
104 {
105     ProcessSP process_sp(GetSP());
106     if (process_sp)
107     {
108         return process_sp->GetPluginName().GetCString();
109     }
110     return "<Unknown>";
111 }
112 
113 
114 lldb::ProcessSP
115 SBProcess::GetSP() const
116 {
117     return m_opaque_wp.lock();
118 }
119 
120 void
121 SBProcess::SetSP (const ProcessSP &process_sp)
122 {
123     m_opaque_wp = process_sp;
124 }
125 
126 void
127 SBProcess::Clear ()
128 {
129     m_opaque_wp.reset();
130 }
131 
132 
133 bool
134 SBProcess::IsValid() const
135 {
136     ProcessSP process_sp(m_opaque_wp.lock());
137     return ((bool) process_sp && process_sp->IsValid());
138 }
139 
140 bool
141 SBProcess::RemoteLaunch (char const **argv,
142                          char const **envp,
143                          const char *stdin_path,
144                          const char *stdout_path,
145                          const char *stderr_path,
146                          const char *working_directory,
147                          uint32_t launch_flags,
148                          bool stop_at_entry,
149                          lldb::SBError& error)
150 {
151     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
152     if (log)
153         log->Printf ("SBProcess(%p)::RemoteLaunch (argv=%p, envp=%p, stdin=%s, stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, stop_at_entry=%i, &error (%p))...",
154                      static_cast<void*>(m_opaque_wp.lock().get()),
155                      static_cast<void*>(argv), static_cast<void*>(envp),
156                      stdin_path ? stdin_path : "NULL",
157                      stdout_path ? stdout_path : "NULL",
158                      stderr_path ? stderr_path : "NULL",
159                      working_directory ? working_directory : "NULL",
160                      launch_flags, stop_at_entry,
161                      static_cast<void*>(error.get()));
162 
163     ProcessSP process_sp(GetSP());
164     if (process_sp)
165     {
166         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
167         if (process_sp->GetState() == eStateConnected)
168         {
169             if (stop_at_entry)
170                 launch_flags |= eLaunchFlagStopAtEntry;
171             ProcessLaunchInfo launch_info (stdin_path,
172                                            stdout_path,
173                                            stderr_path,
174                                            working_directory,
175                                            launch_flags);
176             Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
177             if (exe_module)
178                 launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
179             if (argv)
180                 launch_info.GetArguments().AppendArguments (argv);
181             if (envp)
182                 launch_info.GetEnvironmentEntries ().SetArguments (envp);
183             error.SetError (process_sp->Launch (launch_info));
184         }
185         else
186         {
187             error.SetErrorString ("must be in eStateConnected to call RemoteLaunch");
188         }
189     }
190     else
191     {
192         error.SetErrorString ("unable to attach pid");
193     }
194 
195     if (log) {
196         SBStream sstr;
197         error.GetDescription (sstr);
198         log->Printf ("SBProcess(%p)::RemoteLaunch (...) => SBError (%p): %s",
199                      static_cast<void*>(process_sp.get()),
200                      static_cast<void*>(error.get()), sstr.GetData());
201     }
202 
203     return error.Success();
204 }
205 
206 bool
207 SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error)
208 {
209     ProcessSP process_sp(GetSP());
210     if (process_sp)
211     {
212         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
213         if (process_sp->GetState() == eStateConnected)
214         {
215             ProcessAttachInfo attach_info;
216             attach_info.SetProcessID (pid);
217             error.SetError (process_sp->Attach (attach_info));
218         }
219         else
220         {
221             error.SetErrorString ("must be in eStateConnected to call RemoteAttachToProcessWithID");
222         }
223     }
224     else
225     {
226         error.SetErrorString ("unable to attach pid");
227     }
228 
229     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
230     if (log) {
231         SBStream sstr;
232         error.GetDescription (sstr);
233         log->Printf ("SBProcess(%p)::RemoteAttachToProcessWithID (%" PRIu64 ") => SBError (%p): %s",
234                      static_cast<void*>(process_sp.get()), pid,
235                      static_cast<void*>(error.get()), sstr.GetData());
236     }
237 
238     return error.Success();
239 }
240 
241 
242 uint32_t
243 SBProcess::GetNumThreads ()
244 {
245     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
246 
247     uint32_t num_threads = 0;
248     ProcessSP process_sp(GetSP());
249     if (process_sp)
250     {
251         Process::StopLocker stop_locker;
252 
253         const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
254         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
255         num_threads = process_sp->GetThreadList().GetSize(can_update);
256     }
257 
258     if (log)
259         log->Printf ("SBProcess(%p)::GetNumThreads () => %d",
260                      static_cast<void*>(process_sp.get()), num_threads);
261 
262     return num_threads;
263 }
264 
265 SBThread
266 SBProcess::GetSelectedThread () const
267 {
268     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
269 
270     SBThread sb_thread;
271     ThreadSP thread_sp;
272     ProcessSP process_sp(GetSP());
273     if (process_sp)
274     {
275         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
276         thread_sp = process_sp->GetThreadList().GetSelectedThread();
277         sb_thread.SetThread (thread_sp);
278     }
279 
280     if (log)
281         log->Printf ("SBProcess(%p)::GetSelectedThread () => SBThread(%p)",
282                      static_cast<void*>(process_sp.get()),
283                      static_cast<void*>(thread_sp.get()));
284 
285     return sb_thread;
286 }
287 
288 SBThread
289 SBProcess::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context)
290 {
291     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
292 
293     SBThread sb_thread;
294     ThreadSP thread_sp;
295     ProcessSP process_sp(GetSP());
296     if (process_sp)
297     {
298         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
299         thread_sp = process_sp->CreateOSPluginThread(tid, context);
300         sb_thread.SetThread (thread_sp);
301     }
302 
303     if (log)
304         log->Printf ("SBProcess(%p)::CreateOSPluginThread (tid=0x%" PRIx64 ", context=0x%" PRIx64 ") => SBThread(%p)",
305                      static_cast<void*>(process_sp.get()), tid, context,
306                      static_cast<void*>(thread_sp.get()));
307 
308     return sb_thread;
309 }
310 
311 SBTarget
312 SBProcess::GetTarget() const
313 {
314     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
315 
316     SBTarget sb_target;
317     TargetSP target_sp;
318     ProcessSP process_sp(GetSP());
319     if (process_sp)
320     {
321         target_sp = process_sp->GetTarget().shared_from_this();
322         sb_target.SetSP (target_sp);
323     }
324 
325     if (log)
326         log->Printf ("SBProcess(%p)::GetTarget () => SBTarget(%p)",
327                      static_cast<void*>(process_sp.get()),
328                      static_cast<void*>(target_sp.get()));
329 
330     return sb_target;
331 }
332 
333 
334 size_t
335 SBProcess::PutSTDIN (const char *src, size_t src_len)
336 {
337     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
338 
339     size_t ret_val = 0;
340     ProcessSP process_sp(GetSP());
341     if (process_sp)
342     {
343         Error error;
344         ret_val =  process_sp->PutSTDIN (src, src_len, error);
345     }
346 
347     if (log)
348         log->Printf("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%" PRIu64 ") => %" PRIu64,
349                      static_cast<void*>(process_sp.get()), src,
350                      static_cast<uint64_t>(src_len),
351                      static_cast<uint64_t>(ret_val));
352 
353     return ret_val;
354 }
355 
356 size_t
357 SBProcess::GetSTDOUT (char *dst, size_t dst_len) const
358 {
359     size_t bytes_read = 0;
360     ProcessSP process_sp(GetSP());
361     if (process_sp)
362     {
363         Error error;
364         bytes_read = process_sp->GetSTDOUT (dst, dst_len, error);
365     }
366 
367     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
368     if (log)
369         log->Printf ("SBProcess(%p)::GetSTDOUT (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
370                      static_cast<void*>(process_sp.get()),
371                      static_cast<int>(bytes_read), dst,
372                      static_cast<uint64_t>(dst_len),
373                      static_cast<uint64_t>(bytes_read));
374 
375     return bytes_read;
376 }
377 
378 size_t
379 SBProcess::GetSTDERR (char *dst, size_t dst_len) const
380 {
381     size_t bytes_read = 0;
382     ProcessSP process_sp(GetSP());
383     if (process_sp)
384     {
385         Error error;
386         bytes_read = process_sp->GetSTDERR (dst, dst_len, error);
387     }
388 
389     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
390     if (log)
391         log->Printf ("SBProcess(%p)::GetSTDERR (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
392                      static_cast<void*>(process_sp.get()),
393                      static_cast<int>(bytes_read), dst,
394                      static_cast<uint64_t>(dst_len),
395                      static_cast<uint64_t>(bytes_read));
396 
397     return bytes_read;
398 }
399 
400 size_t
401 SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const
402 {
403     size_t bytes_read = 0;
404     ProcessSP process_sp(GetSP());
405     if (process_sp)
406     {
407         Error error;
408         bytes_read = process_sp->GetAsyncProfileData (dst, dst_len, error);
409     }
410 
411     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
412     if (log)
413         log->Printf ("SBProcess(%p)::GetProfileData (dst=\"%.*s\", dst_len=%" PRIu64 ") => %" PRIu64,
414                      static_cast<void*>(process_sp.get()),
415                      static_cast<int>(bytes_read), dst,
416                      static_cast<uint64_t>(dst_len),
417                      static_cast<uint64_t>(bytes_read));
418 
419     return bytes_read;
420 }
421 
422 void
423 SBProcess::ReportEventState (const SBEvent &event, FILE *out) const
424 {
425     if (out == NULL)
426         return;
427 
428     ProcessSP process_sp(GetSP());
429     if (process_sp)
430     {
431         const StateType event_state = SBProcess::GetStateFromEvent (event);
432         char message[1024];
433         int message_len = ::snprintf (message,
434                                       sizeof (message),
435                                       "Process %" PRIu64 " %s\n",
436                                       process_sp->GetID(),
437                                       SBDebugger::StateAsCString (event_state));
438 
439         if (message_len > 0)
440             ::fwrite (message, 1, message_len, out);
441     }
442 }
443 
444 void
445 SBProcess::AppendEventStateReport (const SBEvent &event, SBCommandReturnObject &result)
446 {
447     ProcessSP process_sp(GetSP());
448     if (process_sp)
449     {
450         const StateType event_state = SBProcess::GetStateFromEvent (event);
451         char message[1024];
452         ::snprintf (message,
453                     sizeof (message),
454                     "Process %" PRIu64 " %s\n",
455                     process_sp->GetID(),
456                     SBDebugger::StateAsCString (event_state));
457 
458         result.AppendMessage (message);
459     }
460 }
461 
462 bool
463 SBProcess::SetSelectedThread (const SBThread &thread)
464 {
465     ProcessSP process_sp(GetSP());
466     if (process_sp)
467     {
468         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
469         return process_sp->GetThreadList().SetSelectedThreadByID (thread.GetThreadID());
470     }
471     return false;
472 }
473 
474 bool
475 SBProcess::SetSelectedThreadByID (lldb::tid_t tid)
476 {
477     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
478 
479     bool ret_val = false;
480     ProcessSP process_sp(GetSP());
481     if (process_sp)
482     {
483         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
484         ret_val = process_sp->GetThreadList().SetSelectedThreadByID (tid);
485     }
486 
487     if (log)
488         log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%4.4" PRIx64 ") => %s",
489                      static_cast<void*>(process_sp.get()), tid,
490                      (ret_val ? "true" : "false"));
491 
492     return ret_val;
493 }
494 
495 bool
496 SBProcess::SetSelectedThreadByIndexID (uint32_t index_id)
497 {
498     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
499 
500     bool ret_val = false;
501     ProcessSP process_sp(GetSP());
502     if (process_sp)
503     {
504         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
505         ret_val = process_sp->GetThreadList().SetSelectedThreadByIndexID (index_id);
506     }
507 
508     if (log)
509         log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%x) => %s",
510                      static_cast<void*>(process_sp.get()), index_id,
511                      (ret_val ? "true" : "false"));
512 
513     return ret_val;
514 }
515 
516 SBThread
517 SBProcess::GetThreadAtIndex (size_t index)
518 {
519     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
520 
521     SBThread sb_thread;
522     ThreadSP thread_sp;
523     ProcessSP process_sp(GetSP());
524     if (process_sp)
525     {
526         Process::StopLocker stop_locker;
527         const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
528         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
529         thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, can_update);
530         sb_thread.SetThread (thread_sp);
531     }
532 
533     if (log)
534         log->Printf ("SBProcess(%p)::GetThreadAtIndex (index=%d) => SBThread(%p)",
535                      static_cast<void*>(process_sp.get()),
536                      static_cast<uint32_t>(index),
537                      static_cast<void*>(thread_sp.get()));
538 
539     return sb_thread;
540 }
541 
542 uint32_t
543 SBProcess::GetNumQueues ()
544 {
545     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
546 
547     uint32_t num_queues = 0;
548     ProcessSP process_sp(GetSP());
549     if (process_sp)
550     {
551         Process::StopLocker stop_locker;
552 
553         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
554         num_queues = process_sp->GetQueueList().GetSize();
555     }
556 
557     if (log)
558         log->Printf ("SBProcess(%p)::GetNumQueues () => %d",
559                      static_cast<void*>(process_sp.get()), num_queues);
560 
561     return num_queues;
562 }
563 
564 SBQueue
565 SBProcess::GetQueueAtIndex (size_t index)
566 {
567     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
568 
569     SBQueue sb_queue;
570     QueueSP queue_sp;
571     ProcessSP process_sp(GetSP());
572     if (process_sp)
573     {
574         Process::StopLocker stop_locker;
575         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
576         queue_sp = process_sp->GetQueueList().GetQueueAtIndex(index);
577         sb_queue.SetQueue (queue_sp);
578     }
579 
580     if (log)
581         log->Printf ("SBProcess(%p)::GetQueueAtIndex (index=%d) => SBQueue(%p)",
582                      static_cast<void*>(process_sp.get()),
583                      static_cast<uint32_t>(index),
584                      static_cast<void*>(queue_sp.get()));
585 
586     return sb_queue;
587 }
588 
589 
590 uint32_t
591 SBProcess::GetStopID(bool include_expression_stops)
592 {
593     ProcessSP process_sp(GetSP());
594     if (process_sp)
595     {
596         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
597         if (include_expression_stops)
598             return process_sp->GetStopID();
599         else
600             return process_sp->GetLastNaturalStopID();
601     }
602     return 0;
603 }
604 
605 StateType
606 SBProcess::GetState ()
607 {
608 
609     StateType ret_val = eStateInvalid;
610     ProcessSP process_sp(GetSP());
611     if (process_sp)
612     {
613         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
614         ret_val = process_sp->GetState();
615     }
616 
617     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
618     if (log)
619         log->Printf ("SBProcess(%p)::GetState () => %s",
620                      static_cast<void*>(process_sp.get()),
621                      lldb_private::StateAsCString (ret_val));
622 
623     return ret_val;
624 }
625 
626 
627 int
628 SBProcess::GetExitStatus ()
629 {
630     int exit_status = 0;
631     ProcessSP process_sp(GetSP());
632     if (process_sp)
633     {
634         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
635         exit_status = process_sp->GetExitStatus ();
636     }
637     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
638     if (log)
639         log->Printf ("SBProcess(%p)::GetExitStatus () => %i (0x%8.8x)",
640                      static_cast<void*>(process_sp.get()), exit_status,
641                      exit_status);
642 
643     return exit_status;
644 }
645 
646 const char *
647 SBProcess::GetExitDescription ()
648 {
649     const char *exit_desc = NULL;
650     ProcessSP process_sp(GetSP());
651     if (process_sp)
652     {
653         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
654         exit_desc = process_sp->GetExitDescription ();
655     }
656     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
657     if (log)
658         log->Printf ("SBProcess(%p)::GetExitDescription () => %s",
659                      static_cast<void*>(process_sp.get()), exit_desc);
660     return exit_desc;
661 }
662 
663 lldb::pid_t
664 SBProcess::GetProcessID ()
665 {
666     lldb::pid_t ret_val = LLDB_INVALID_PROCESS_ID;
667     ProcessSP process_sp(GetSP());
668     if (process_sp)
669         ret_val = process_sp->GetID();
670 
671     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
672     if (log)
673         log->Printf ("SBProcess(%p)::GetProcessID () => %" PRIu64,
674                      static_cast<void*>(process_sp.get()), ret_val);
675 
676     return ret_val;
677 }
678 
679 uint32_t
680 SBProcess::GetUniqueID()
681 {
682     uint32_t ret_val = 0;
683     ProcessSP process_sp(GetSP());
684     if (process_sp)
685         ret_val = process_sp->GetUniqueID();
686     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
687     if (log)
688         log->Printf ("SBProcess(%p)::GetUniqueID () => %" PRIu32,
689                      static_cast<void*>(process_sp.get()), ret_val);
690     return ret_val;
691 }
692 
693 ByteOrder
694 SBProcess::GetByteOrder () const
695 {
696     ByteOrder byteOrder = eByteOrderInvalid;
697     ProcessSP process_sp(GetSP());
698     if (process_sp)
699         byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder();
700 
701     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
702     if (log)
703         log->Printf ("SBProcess(%p)::GetByteOrder () => %d",
704                      static_cast<void*>(process_sp.get()), byteOrder);
705 
706     return byteOrder;
707 }
708 
709 uint32_t
710 SBProcess::GetAddressByteSize () const
711 {
712     uint32_t size = 0;
713     ProcessSP process_sp(GetSP());
714     if (process_sp)
715         size =  process_sp->GetTarget().GetArchitecture().GetAddressByteSize();
716 
717     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
718     if (log)
719         log->Printf ("SBProcess(%p)::GetAddressByteSize () => %d",
720                      static_cast<void*>(process_sp.get()), size);
721 
722     return size;
723 }
724 
725 SBError
726 SBProcess::Continue ()
727 {
728     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
729 
730     SBError sb_error;
731     ProcessSP process_sp(GetSP());
732 
733     if (log)
734         log->Printf ("SBProcess(%p)::Continue ()...",
735                      static_cast<void*>(process_sp.get()));
736 
737     if (process_sp)
738     {
739         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
740 
741         Error error (process_sp->Resume());
742         if (error.Success())
743         {
744             if (process_sp->GetTarget().GetDebugger().GetAsyncExecution () == false)
745             {
746                 if (log)
747                     log->Printf ("SBProcess(%p)::Continue () waiting for process to stop...",
748                                  static_cast<void*>(process_sp.get()));
749                 process_sp->WaitForProcessToStop (NULL);
750             }
751         }
752         sb_error.SetError(error);
753     }
754     else
755         sb_error.SetErrorString ("SBProcess is invalid");
756 
757     if (log)
758     {
759         SBStream sstr;
760         sb_error.GetDescription (sstr);
761         log->Printf ("SBProcess(%p)::Continue () => SBError (%p): %s",
762                      static_cast<void*>(process_sp.get()),
763                      static_cast<void*>(sb_error.get()), sstr.GetData());
764     }
765 
766     return sb_error;
767 }
768 
769 
770 SBError
771 SBProcess::Destroy ()
772 {
773     SBError sb_error;
774     ProcessSP process_sp(GetSP());
775     if (process_sp)
776     {
777         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
778         sb_error.SetError(process_sp->Destroy());
779     }
780     else
781         sb_error.SetErrorString ("SBProcess is invalid");
782 
783     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
784     if (log)
785     {
786         SBStream sstr;
787         sb_error.GetDescription (sstr);
788         log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s",
789                      static_cast<void*>(process_sp.get()),
790                      static_cast<void*>(sb_error.get()), sstr.GetData());
791     }
792 
793     return sb_error;
794 }
795 
796 
797 SBError
798 SBProcess::Stop ()
799 {
800     SBError sb_error;
801     ProcessSP process_sp(GetSP());
802     if (process_sp)
803     {
804         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
805         sb_error.SetError (process_sp->Halt());
806     }
807     else
808         sb_error.SetErrorString ("SBProcess is invalid");
809 
810     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
811     if (log)
812     {
813         SBStream sstr;
814         sb_error.GetDescription (sstr);
815         log->Printf ("SBProcess(%p)::Stop () => SBError (%p): %s",
816                      static_cast<void*>(process_sp.get()),
817                      static_cast<void*>(sb_error.get()), sstr.GetData());
818     }
819 
820     return sb_error;
821 }
822 
823 SBError
824 SBProcess::Kill ()
825 {
826     SBError sb_error;
827     ProcessSP process_sp(GetSP());
828     if (process_sp)
829     {
830         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
831         sb_error.SetError (process_sp->Destroy());
832     }
833     else
834         sb_error.SetErrorString ("SBProcess is invalid");
835 
836     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
837     if (log)
838     {
839         SBStream sstr;
840         sb_error.GetDescription (sstr);
841         log->Printf ("SBProcess(%p)::Kill () => SBError (%p): %s",
842                      static_cast<void*>(process_sp.get()),
843                      static_cast<void*>(sb_error.get()), sstr.GetData());
844     }
845 
846     return sb_error;
847 }
848 
849 SBError
850 SBProcess::Detach ()
851 {
852     // FIXME: This should come from a process default.
853     bool keep_stopped = false;
854     return Detach (keep_stopped);
855 }
856 
857 SBError
858 SBProcess::Detach (bool keep_stopped)
859 {
860     SBError sb_error;
861     ProcessSP process_sp(GetSP());
862     if (process_sp)
863     {
864         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
865         sb_error.SetError (process_sp->Detach(keep_stopped));
866     }
867     else
868         sb_error.SetErrorString ("SBProcess is invalid");
869 
870     return sb_error;
871 }
872 
873 SBError
874 SBProcess::Signal (int signo)
875 {
876     SBError sb_error;
877     ProcessSP process_sp(GetSP());
878     if (process_sp)
879     {
880         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
881         sb_error.SetError (process_sp->Signal (signo));
882     }
883     else
884         sb_error.SetErrorString ("SBProcess is invalid");
885     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
886     if (log)
887     {
888         SBStream sstr;
889         sb_error.GetDescription (sstr);
890         log->Printf ("SBProcess(%p)::Signal (signo=%i) => SBError (%p): %s",
891                      static_cast<void*>(process_sp.get()), signo,
892                      static_cast<void*>(sb_error.get()), sstr.GetData());
893     }
894     return sb_error;
895 }
896 
897 SBUnixSignals
898 SBProcess::GetUnixSignals()
899 {
900     SBUnixSignals sb_unix_signals;
901     ProcessSP process_sp(GetSP());
902     if (process_sp)
903     {
904         sb_unix_signals.SetSP(process_sp);
905     }
906 
907     return sb_unix_signals;
908 }
909 
910 void
911 SBProcess::SendAsyncInterrupt ()
912 {
913     ProcessSP process_sp(GetSP());
914     if (process_sp)
915     {
916         process_sp->SendAsyncInterrupt ();
917     }
918 }
919 
920 SBThread
921 SBProcess::GetThreadByID (tid_t tid)
922 {
923     SBThread sb_thread;
924     ThreadSP thread_sp;
925     ProcessSP process_sp(GetSP());
926     if (process_sp)
927     {
928         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
929         Process::StopLocker stop_locker;
930         const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
931         thread_sp = process_sp->GetThreadList().FindThreadByID (tid, can_update);
932         sb_thread.SetThread (thread_sp);
933     }
934 
935     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
936     if (log)
937         log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%4.4" PRIx64 ") => SBThread (%p)",
938                      static_cast<void*>(process_sp.get()), tid,
939                      static_cast<void*>(thread_sp.get()));
940 
941     return sb_thread;
942 }
943 
944 SBThread
945 SBProcess::GetThreadByIndexID (uint32_t index_id)
946 {
947     SBThread sb_thread;
948     ThreadSP thread_sp;
949     ProcessSP process_sp(GetSP());
950     if (process_sp)
951     {
952         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
953         Process::StopLocker stop_locker;
954         const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
955         thread_sp = process_sp->GetThreadList().FindThreadByIndexID (index_id, can_update);
956         sb_thread.SetThread (thread_sp);
957     }
958 
959     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
960     if (log)
961         log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%x) => SBThread (%p)",
962                      static_cast<void*>(process_sp.get()), index_id,
963                      static_cast<void*>(thread_sp.get()));
964 
965     return sb_thread;
966 }
967 
968 StateType
969 SBProcess::GetStateFromEvent (const SBEvent &event)
970 {
971     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
972 
973     StateType ret_val = Process::ProcessEventData::GetStateFromEvent (event.get());
974 
975     if (log)
976         log->Printf ("SBProcess::GetStateFromEvent (event.sp=%p) => %s",
977                      static_cast<void*>(event.get()),
978                      lldb_private::StateAsCString (ret_val));
979 
980     return ret_val;
981 }
982 
983 bool
984 SBProcess::GetRestartedFromEvent (const SBEvent &event)
985 {
986     return Process::ProcessEventData::GetRestartedFromEvent (event.get());
987 }
988 
989 size_t
990 SBProcess::GetNumRestartedReasonsFromEvent (const lldb::SBEvent &event)
991 {
992     return Process::ProcessEventData::GetNumRestartedReasons(event.get());
993 }
994 
995 const char *
996 SBProcess::GetRestartedReasonAtIndexFromEvent (const lldb::SBEvent &event, size_t idx)
997 {
998     return Process::ProcessEventData::GetRestartedReasonAtIndex(event.get(), idx);
999 }
1000 
1001 SBProcess
1002 SBProcess::GetProcessFromEvent (const SBEvent &event)
1003 {
1004     SBProcess process(Process::ProcessEventData::GetProcessFromEvent (event.get()));
1005     return process;
1006 }
1007 
1008 bool
1009 SBProcess::EventIsProcessEvent (const SBEvent &event)
1010 {
1011     return strcmp (event.GetBroadcasterClass(), SBProcess::GetBroadcasterClass()) == 0;
1012 }
1013 
1014 SBBroadcaster
1015 SBProcess::GetBroadcaster () const
1016 {
1017     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1018 
1019     ProcessSP process_sp(GetSP());
1020 
1021     SBBroadcaster broadcaster(process_sp.get(), false);
1022 
1023     if (log)
1024         log->Printf ("SBProcess(%p)::GetBroadcaster () => SBBroadcaster (%p)",
1025                      static_cast<void*>(process_sp.get()),
1026                      static_cast<void*>(broadcaster.get()));
1027 
1028     return broadcaster;
1029 }
1030 
1031 const char *
1032 SBProcess::GetBroadcasterClass ()
1033 {
1034     return Process::GetStaticBroadcasterClass().AsCString();
1035 }
1036 
1037 size_t
1038 SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error)
1039 {
1040     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1041 
1042     size_t bytes_read = 0;
1043 
1044     ProcessSP process_sp(GetSP());
1045 
1046     if (log)
1047         log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64 ", dst=%p, dst_len=%" PRIu64 ", SBError (%p))...",
1048                      static_cast<void*>(process_sp.get()), addr,
1049                      static_cast<void*>(dst), static_cast<uint64_t>(dst_len),
1050                      static_cast<void*>(sb_error.get()));
1051 
1052     if (process_sp)
1053     {
1054         Process::StopLocker stop_locker;
1055         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1056         {
1057             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1058             bytes_read = process_sp->ReadMemory (addr, dst, dst_len, sb_error.ref());
1059         }
1060         else
1061         {
1062             if (log)
1063                 log->Printf ("SBProcess(%p)::ReadMemory() => error: process is running",
1064                              static_cast<void*>(process_sp.get()));
1065             sb_error.SetErrorString("process is running");
1066         }
1067     }
1068     else
1069     {
1070         sb_error.SetErrorString ("SBProcess is invalid");
1071     }
1072 
1073     if (log)
1074     {
1075         SBStream sstr;
1076         sb_error.GetDescription (sstr);
1077         log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64 ", dst=%p, dst_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64,
1078                      static_cast<void*>(process_sp.get()), addr,
1079                      static_cast<void*>(dst), static_cast<uint64_t>(dst_len),
1080                      static_cast<void*>(sb_error.get()), sstr.GetData(),
1081                      static_cast<uint64_t>(bytes_read));
1082     }
1083 
1084     return bytes_read;
1085 }
1086 
1087 size_t
1088 SBProcess::ReadCStringFromMemory (addr_t addr, void *buf, size_t size, lldb::SBError &sb_error)
1089 {
1090     size_t bytes_read = 0;
1091     ProcessSP process_sp(GetSP());
1092     if (process_sp)
1093     {
1094         Process::StopLocker stop_locker;
1095         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1096         {
1097             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1098             bytes_read = process_sp->ReadCStringFromMemory (addr, (char *)buf, size, sb_error.ref());
1099         }
1100         else
1101         {
1102             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1103             if (log)
1104                 log->Printf ("SBProcess(%p)::ReadCStringFromMemory() => error: process is running",
1105                              static_cast<void*>(process_sp.get()));
1106             sb_error.SetErrorString("process is running");
1107         }
1108     }
1109     else
1110     {
1111         sb_error.SetErrorString ("SBProcess is invalid");
1112     }
1113     return bytes_read;
1114 }
1115 
1116 uint64_t
1117 SBProcess::ReadUnsignedFromMemory (addr_t addr, uint32_t byte_size, lldb::SBError &sb_error)
1118 {
1119     uint64_t value = 0;
1120     ProcessSP process_sp(GetSP());
1121     if (process_sp)
1122     {
1123         Process::StopLocker stop_locker;
1124         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1125         {
1126             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1127             value = process_sp->ReadUnsignedIntegerFromMemory (addr, byte_size, 0, sb_error.ref());
1128         }
1129         else
1130         {
1131             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1132             if (log)
1133                 log->Printf ("SBProcess(%p)::ReadUnsignedFromMemory() => error: process is running",
1134                              static_cast<void*>(process_sp.get()));
1135             sb_error.SetErrorString("process is running");
1136         }
1137     }
1138     else
1139     {
1140         sb_error.SetErrorString ("SBProcess is invalid");
1141     }
1142     return value;
1143 }
1144 
1145 lldb::addr_t
1146 SBProcess::ReadPointerFromMemory (addr_t addr, lldb::SBError &sb_error)
1147 {
1148     lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
1149     ProcessSP process_sp(GetSP());
1150     if (process_sp)
1151     {
1152         Process::StopLocker stop_locker;
1153         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1154         {
1155             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1156             ptr = process_sp->ReadPointerFromMemory (addr, sb_error.ref());
1157         }
1158         else
1159         {
1160             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1161             if (log)
1162                 log->Printf ("SBProcess(%p)::ReadPointerFromMemory() => error: process is running",
1163                              static_cast<void*>(process_sp.get()));
1164             sb_error.SetErrorString("process is running");
1165         }
1166     }
1167     else
1168     {
1169         sb_error.SetErrorString ("SBProcess is invalid");
1170     }
1171     return ptr;
1172 }
1173 
1174 size_t
1175 SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &sb_error)
1176 {
1177     size_t bytes_written = 0;
1178 
1179     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1180 
1181     ProcessSP process_sp(GetSP());
1182 
1183     if (log)
1184         log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64 ", src=%p, src_len=%" PRIu64 ", SBError (%p))...",
1185                      static_cast<void*>(process_sp.get()), addr,
1186                      static_cast<const void*>(src),
1187                      static_cast<uint64_t>(src_len),
1188                      static_cast<void*>(sb_error.get()));
1189 
1190     if (process_sp)
1191     {
1192         Process::StopLocker stop_locker;
1193         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1194         {
1195             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1196             bytes_written = process_sp->WriteMemory (addr, src, src_len, sb_error.ref());
1197         }
1198         else
1199         {
1200             if (log)
1201                 log->Printf ("SBProcess(%p)::WriteMemory() => error: process is running",
1202                              static_cast<void*>(process_sp.get()));
1203             sb_error.SetErrorString("process is running");
1204         }
1205     }
1206 
1207     if (log)
1208     {
1209         SBStream sstr;
1210         sb_error.GetDescription (sstr);
1211         log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64 ", src=%p, src_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64,
1212                      static_cast<void*>(process_sp.get()), addr,
1213                      static_cast<const void*>(src),
1214                      static_cast<uint64_t>(src_len),
1215                      static_cast<void*>(sb_error.get()), sstr.GetData(),
1216                      static_cast<uint64_t>(bytes_written));
1217     }
1218 
1219     return bytes_written;
1220 }
1221 
1222 bool
1223 SBProcess::GetDescription (SBStream &description)
1224 {
1225     Stream &strm = description.ref();
1226 
1227     ProcessSP process_sp(GetSP());
1228     if (process_sp)
1229     {
1230         char path[PATH_MAX];
1231         GetTarget().GetExecutable().GetPath (path, sizeof(path));
1232         Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
1233         const char *exe_name = NULL;
1234         if (exe_module)
1235             exe_name = exe_module->GetFileSpec().GetFilename().AsCString();
1236 
1237         strm.Printf ("SBProcess: pid = %" PRIu64 ", state = %s, threads = %d%s%s",
1238                      process_sp->GetID(),
1239                      lldb_private::StateAsCString (GetState()),
1240                      GetNumThreads(),
1241                      exe_name ? ", executable = " : "",
1242                      exe_name ? exe_name : "");
1243     }
1244     else
1245         strm.PutCString ("No value");
1246 
1247     return true;
1248 }
1249 
1250 uint32_t
1251 SBProcess::GetNumSupportedHardwareWatchpoints (lldb::SBError &sb_error) const
1252 {
1253     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1254 
1255     uint32_t num = 0;
1256     ProcessSP process_sp(GetSP());
1257     if (process_sp)
1258     {
1259         Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1260         sb_error.SetError(process_sp->GetWatchpointSupportInfo (num));
1261         if (log)
1262             log->Printf ("SBProcess(%p)::GetNumSupportedHardwareWatchpoints () => %u",
1263                          static_cast<void*>(process_sp.get()), num);
1264     }
1265     else
1266     {
1267         sb_error.SetErrorString ("SBProcess is invalid");
1268     }
1269     return num;
1270 }
1271 
1272 uint32_t
1273 SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
1274 {
1275     ProcessSP process_sp(GetSP());
1276     if (process_sp)
1277     {
1278         Process::StopLocker stop_locker;
1279         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1280         {
1281             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1282             return process_sp->LoadImage (*sb_image_spec, sb_error.ref());
1283         }
1284         else
1285         {
1286             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1287             if (log)
1288                 log->Printf ("SBProcess(%p)::LoadImage() => error: process is running",
1289                              static_cast<void*>(process_sp.get()));
1290             sb_error.SetErrorString("process is running");
1291         }
1292     }
1293     return LLDB_INVALID_IMAGE_TOKEN;
1294 }
1295 
1296 lldb::SBError
1297 SBProcess::UnloadImage (uint32_t image_token)
1298 {
1299     lldb::SBError sb_error;
1300     ProcessSP process_sp(GetSP());
1301     if (process_sp)
1302     {
1303         Process::StopLocker stop_locker;
1304         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1305         {
1306             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1307             sb_error.SetError (process_sp->UnloadImage (image_token));
1308         }
1309         else
1310         {
1311             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1312             if (log)
1313                 log->Printf ("SBProcess(%p)::UnloadImage() => error: process is running",
1314                              static_cast<void*>(process_sp.get()));
1315             sb_error.SetErrorString("process is running");
1316         }
1317     }
1318     else
1319         sb_error.SetErrorString("invalid process");
1320     return sb_error;
1321 }
1322 
1323 lldb::SBError
1324 SBProcess::SendEventData (const char *event_data)
1325 {
1326     lldb::SBError sb_error;
1327     ProcessSP process_sp(GetSP());
1328     if (process_sp)
1329     {
1330         Process::StopLocker stop_locker;
1331         if (stop_locker.TryLock(&process_sp->GetRunLock()))
1332         {
1333             Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex());
1334             sb_error.SetError (process_sp->SendEventData (event_data));
1335         }
1336         else
1337         {
1338             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1339             if (log)
1340                 log->Printf ("SBProcess(%p)::SendEventData() => error: process is running",
1341                              static_cast<void*>(process_sp.get()));
1342             sb_error.SetErrorString("process is running");
1343         }
1344     }
1345     else
1346         sb_error.SetErrorString("invalid process");
1347     return sb_error;
1348 }
1349 
1350 uint32_t
1351 SBProcess::GetNumExtendedBacktraceTypes ()
1352 {
1353     ProcessSP process_sp(GetSP());
1354     if (process_sp && process_sp->GetSystemRuntime())
1355     {
1356         SystemRuntime *runtime = process_sp->GetSystemRuntime();
1357         return runtime->GetExtendedBacktraceTypes().size();
1358     }
1359     return 0;
1360 }
1361 
1362 const char *
1363 SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx)
1364 {
1365     ProcessSP process_sp(GetSP());
1366     if (process_sp && process_sp->GetSystemRuntime())
1367     {
1368         SystemRuntime *runtime = process_sp->GetSystemRuntime();
1369         const std::vector<ConstString> &names = runtime->GetExtendedBacktraceTypes();
1370         if (idx < names.size())
1371         {
1372             return names[idx].AsCString();
1373         }
1374         else
1375         {
1376             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
1377             if (log)
1378                 log->Printf("SBProcess(%p)::GetExtendedBacktraceTypeAtIndex() => error: requested extended backtrace name out of bounds",
1379                             static_cast<void*>(process_sp.get()));
1380         }
1381     }
1382     return NULL;
1383 }
1384