SBProcess.cpp revision 444e35b5fdf15a25a427285650f06f1390e62c75
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/API/SBProcess.h"
11
12#include "lldb/lldb-defines.h"
13#include "lldb/lldb-types.h"
14
15#include "lldb/Interpreter/Args.h"
16#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
18#include "lldb/Core/Debugger.h"
19#include "lldb/Core/Log.h"
20#include "lldb/Core/State.h"
21#include "lldb/Core/Stream.h"
22#include "lldb/Core/StreamFile.h"
23#include "lldb/Target/Process.h"
24#include "lldb/Target/RegisterContext.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
27
28// Project includes
29
30#include "lldb/API/SBBroadcaster.h"
31#include "lldb/API/SBDebugger.h"
32#include "lldb/API/SBCommandReturnObject.h"
33#include "lldb/API/SBEvent.h"
34#include "lldb/API/SBThread.h"
35#include "lldb/API/SBStream.h"
36#include "lldb/API/SBStringList.h"
37
38using namespace lldb;
39using namespace lldb_private;
40
41
42
43SBProcess::SBProcess () :
44    m_opaque_sp()
45{
46}
47
48
49//----------------------------------------------------------------------
50// SBProcess constructor
51//----------------------------------------------------------------------
52
53SBProcess::SBProcess (const SBProcess& rhs) :
54    m_opaque_sp (rhs.m_opaque_sp)
55{
56}
57
58
59SBProcess::SBProcess (const lldb::ProcessSP &process_sp) :
60    m_opaque_sp (process_sp)
61{
62}
63
64const SBProcess&
65SBProcess::operator = (const SBProcess& rhs)
66{
67    if (this != &rhs)
68        m_opaque_sp = rhs.m_opaque_sp;
69    return *this;
70}
71
72//----------------------------------------------------------------------
73// Destructor
74//----------------------------------------------------------------------
75SBProcess::~SBProcess()
76{
77}
78
79void
80SBProcess::SetProcess (const ProcessSP &process_sp)
81{
82    m_opaque_sp = process_sp;
83}
84
85void
86SBProcess::Clear ()
87{
88    m_opaque_sp.reset();
89}
90
91
92bool
93SBProcess::IsValid() const
94{
95    return m_opaque_sp.get() != NULL;
96}
97
98bool
99SBProcess::RemoteLaunch (char const **argv,
100                         char const **envp,
101                         const char *stdin_path,
102                         const char *stdout_path,
103                         const char *stderr_path,
104                         const char *working_directory,
105                         uint32_t launch_flags,
106                         bool stop_at_entry,
107                         lldb::SBError& error)
108{
109    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
110    if (log) {
111        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))...",
112                     m_opaque_sp.get(),
113                     argv,
114                     envp,
115                     stdin_path ? stdin_path : "NULL",
116                     stdout_path ? stdout_path : "NULL",
117                     stderr_path ? stderr_path : "NULL",
118                     working_directory ? working_directory : "NULL",
119                     launch_flags,
120                     stop_at_entry,
121                     error.get());
122    }
123
124    if (m_opaque_sp)
125    {
126        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
127        if (m_opaque_sp->GetState() == eStateConnected)
128        {
129            error.SetError (m_opaque_sp->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory));
130        }
131        else
132        {
133            error.SetErrorString ("must be in eStateConnected to call RemoteLaunch");
134        }
135    }
136    else
137    {
138        error.SetErrorString ("unable to attach pid");
139    }
140
141    if (log) {
142        SBStream sstr;
143        error.GetDescription (sstr);
144        log->Printf ("SBProcess(%p)::RemoteLaunch (...) => SBError (%p): %s", m_opaque_sp.get(), error.get(), sstr.GetData());
145    }
146
147    return error.Success();
148}
149
150bool
151SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error)
152{
153    if (m_opaque_sp)
154    {
155        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
156        if (m_opaque_sp->GetState() == eStateConnected)
157        {
158            error.SetError (m_opaque_sp->Attach (pid));
159        }
160        else
161        {
162            error.SetErrorString ("must be in eStateConnected to call RemoteAttachToProcessWithID");
163        }
164    }
165    else
166    {
167        error.SetErrorString ("unable to attach pid");
168    }
169
170    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
171    if (log) {
172        SBStream sstr;
173        error.GetDescription (sstr);
174        log->Printf ("SBProcess(%p)::RemoteAttachToProcessWithID (%d) => SBError (%p): %s", m_opaque_sp.get(), pid, error.get(), sstr.GetData());
175    }
176
177    return error.Success();
178}
179
180
181uint32_t
182SBProcess::GetNumThreads ()
183{
184    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
185
186    uint32_t num_threads = 0;
187    if (m_opaque_sp)
188    {
189        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
190        const bool can_update = true;
191        num_threads = m_opaque_sp->GetThreadList().GetSize(can_update);
192    }
193
194    if (log)
195        log->Printf ("SBProcess(%p)::GetNumThreads () => %d", m_opaque_sp.get(), num_threads);
196
197    return num_threads;
198}
199
200SBThread
201SBProcess::GetSelectedThread () const
202{
203    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
204
205    SBThread sb_thread;
206    if (m_opaque_sp)
207    {
208        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
209        sb_thread.SetThread (m_opaque_sp->GetThreadList().GetSelectedThread());
210    }
211
212    if (log)
213    {
214        log->Printf ("SBProcess(%p)::GetSelectedThread () => SBThread(%p)", m_opaque_sp.get(), sb_thread.get());
215    }
216
217    return sb_thread;
218}
219
220SBTarget
221SBProcess::GetTarget() const
222{
223    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
224
225    SBTarget sb_target;
226    if (m_opaque_sp)
227        sb_target = m_opaque_sp->GetTarget().GetSP();
228
229    if (log)
230        log->Printf ("SBProcess(%p)::GetTarget () => SBTarget(%p)", m_opaque_sp.get(), sb_target.get());
231
232    return sb_target;
233}
234
235
236size_t
237SBProcess::PutSTDIN (const char *src, size_t src_len)
238{
239    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
240
241    size_t ret_val = 0;
242    if (m_opaque_sp)
243    {
244        Error error;
245        ret_val =  m_opaque_sp->PutSTDIN (src, src_len, error);
246    }
247
248    if (log)
249        log->Printf ("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%d) => %lu",
250                     m_opaque_sp.get(),
251                     src,
252                     (uint32_t) src_len,
253                     ret_val);
254
255    return ret_val;
256}
257
258size_t
259SBProcess::GetSTDOUT (char *dst, size_t dst_len) const
260{
261    size_t bytes_read = 0;
262    if (m_opaque_sp)
263    {
264        Error error;
265        bytes_read = m_opaque_sp->GetSTDOUT (dst, dst_len, error);
266    }
267
268    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
269    if (log)
270        log->Printf ("SBProcess(%p)::GetSTDOUT (dst=\"%.*s\", dst_len=%zu) => %zu",
271                     m_opaque_sp.get(), (int) bytes_read, dst, dst_len, bytes_read);
272
273    return bytes_read;
274}
275
276size_t
277SBProcess::GetSTDERR (char *dst, size_t dst_len) const
278{
279    size_t bytes_read = 0;
280    if (m_opaque_sp)
281    {
282        Error error;
283        bytes_read = m_opaque_sp->GetSTDERR (dst, dst_len, error);
284    }
285
286    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
287    if (log)
288        log->Printf ("SBProcess(%p)::GetSTDERR (dst=\"%.*s\", dst_len=%zu) => %zu",
289                     m_opaque_sp.get(), (int) bytes_read, dst, dst_len, bytes_read);
290
291    return bytes_read;
292}
293
294void
295SBProcess::ReportEventState (const SBEvent &event, FILE *out) const
296{
297    if (out == NULL)
298        return;
299
300    if (m_opaque_sp)
301    {
302        const StateType event_state = SBProcess::GetStateFromEvent (event);
303        char message[1024];
304        int message_len = ::snprintf (message,
305                                      sizeof (message),
306                                      "Process %llu %s\n",
307                                      m_opaque_sp->GetID(),
308                                      SBDebugger::StateAsCString (event_state));
309
310        if (message_len > 0)
311            ::fwrite (message, 1, message_len, out);
312    }
313}
314
315void
316SBProcess::AppendEventStateReport (const SBEvent &event, SBCommandReturnObject &result)
317{
318    if (m_opaque_sp)
319    {
320        const StateType event_state = SBProcess::GetStateFromEvent (event);
321        char message[1024];
322        ::snprintf (message,
323                    sizeof (message),
324                    "Process %llu %s\n",
325                    m_opaque_sp->GetID(),
326                    SBDebugger::StateAsCString (event_state));
327
328        result.AppendMessage (message);
329    }
330}
331
332bool
333SBProcess::SetSelectedThread (const SBThread &thread)
334{
335    if (m_opaque_sp)
336    {
337        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
338        return m_opaque_sp->GetThreadList().SetSelectedThreadByID (thread.GetThreadID());
339    }
340    return false;
341}
342
343bool
344SBProcess::SetSelectedThreadByID (uint32_t tid)
345{
346    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
347
348    bool ret_val = false;
349    if (m_opaque_sp)
350    {
351        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
352        ret_val = m_opaque_sp->GetThreadList().SetSelectedThreadByID (tid);
353    }
354
355    if (log)
356        log->Printf ("SBProcess(%p)::SetSelectedThreadByID (tid=0x%4.4x) => %s",
357                     m_opaque_sp.get(), tid, (ret_val ? "true" : "false"));
358
359    return ret_val;
360}
361
362SBThread
363SBProcess::GetThreadAtIndex (size_t index)
364{
365    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
366
367    SBThread thread;
368    if (m_opaque_sp)
369    {
370        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
371        thread.SetThread (m_opaque_sp->GetThreadList().GetThreadAtIndex(index));
372    }
373
374    if (log)
375    {
376        log->Printf ("SBProcess(%p)::GetThreadAtIndex (index=%d) => SBThread(%p)",
377                     m_opaque_sp.get(), (uint32_t) index, thread.get());
378    }
379
380    return thread;
381}
382
383StateType
384SBProcess::GetState ()
385{
386
387    StateType ret_val = eStateInvalid;
388    if (m_opaque_sp)
389    {
390        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
391        ret_val = m_opaque_sp->GetState();
392    }
393
394    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
395    if (log)
396        log->Printf ("SBProcess(%p)::GetState () => %s",
397                     m_opaque_sp.get(),
398                     lldb_private::StateAsCString (ret_val));
399
400    return ret_val;
401}
402
403
404int
405SBProcess::GetExitStatus ()
406{
407    int exit_status = 0;
408    if (m_opaque_sp)
409    {
410        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
411        exit_status = m_opaque_sp->GetExitStatus ();
412    }
413    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
414    if (log)
415        log->Printf ("SBProcess(%p)::GetExitStatus () => %i (0x%8.8x)",
416                     m_opaque_sp.get(), exit_status, exit_status);
417
418    return exit_status;
419}
420
421const char *
422SBProcess::GetExitDescription ()
423{
424    const char *exit_desc = NULL;
425    if (m_opaque_sp)
426    {
427        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
428        exit_desc = m_opaque_sp->GetExitDescription ();
429    }
430    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
431    if (log)
432        log->Printf ("SBProcess(%p)::GetExitDescription () => %s",
433                     m_opaque_sp.get(), exit_desc);
434    return exit_desc;
435}
436
437lldb::pid_t
438SBProcess::GetProcessID ()
439{
440    lldb::pid_t ret_val = LLDB_INVALID_PROCESS_ID;
441    if (m_opaque_sp)
442        ret_val = m_opaque_sp->GetID();
443
444    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
445    if (log)
446        log->Printf ("SBProcess(%p)::GetProcessID () => %d", m_opaque_sp.get(), ret_val);
447
448    return ret_val;
449}
450
451ByteOrder
452SBProcess::GetByteOrder () const
453{
454    ByteOrder byteOrder = eByteOrderInvalid;
455    if (m_opaque_sp)
456        byteOrder = m_opaque_sp->GetTarget().GetArchitecture().GetByteOrder();
457
458    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
459    if (log)
460        log->Printf ("SBProcess(%p)::GetByteOrder () => %d", m_opaque_sp.get(), byteOrder);
461
462    return byteOrder;
463}
464
465uint32_t
466SBProcess::GetAddressByteSize () const
467{
468    uint32_t size = 0;
469    if (m_opaque_sp)
470        size =  m_opaque_sp->GetTarget().GetArchitecture().GetAddressByteSize();
471
472    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
473    if (log)
474        log->Printf ("SBProcess(%p)::GetAddressByteSize () => %d", m_opaque_sp.get(), size);
475
476    return size;
477}
478
479SBError
480SBProcess::Continue ()
481{
482    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
483    if (log)
484        log->Printf ("SBProcess(%p)::Continue ()...", m_opaque_sp.get());
485
486    SBError sb_error;
487    if (m_opaque_sp)
488    {
489        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
490
491        Error error (m_opaque_sp->Resume());
492        if (error.Success())
493        {
494            if (m_opaque_sp->GetTarget().GetDebugger().GetAsyncExecution () == false)
495            {
496                if (log)
497                    log->Printf ("SBProcess(%p)::Continue () waiting for process to stop...", m_opaque_sp.get());
498                m_opaque_sp->WaitForProcessToStop (NULL);
499            }
500        }
501        sb_error.SetError(error);
502    }
503    else
504        sb_error.SetErrorString ("SBProcess is invalid");
505
506    if (log)
507    {
508        SBStream sstr;
509        sb_error.GetDescription (sstr);
510        log->Printf ("SBProcess(%p)::Continue () => SBError (%p): %s", m_opaque_sp.get(), sb_error.get(), sstr.GetData());
511    }
512
513    return sb_error;
514}
515
516
517SBError
518SBProcess::Destroy ()
519{
520    SBError sb_error;
521    if (m_opaque_sp)
522    {
523        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
524        sb_error.SetError(m_opaque_sp->Destroy());
525    }
526    else
527        sb_error.SetErrorString ("SBProcess is invalid");
528
529    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
530    if (log)
531    {
532        SBStream sstr;
533        sb_error.GetDescription (sstr);
534        log->Printf ("SBProcess(%p)::Destroy () => SBError (%p): %s",
535                     m_opaque_sp.get(),
536                     sb_error.get(),
537                     sstr.GetData());
538    }
539
540    return sb_error;
541}
542
543
544SBError
545SBProcess::Stop ()
546{
547    SBError sb_error;
548    if (m_opaque_sp)
549    {
550        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
551        sb_error.SetError (m_opaque_sp->Halt());
552    }
553    else
554        sb_error.SetErrorString ("SBProcess is invalid");
555
556    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
557    if (log)
558    {
559        SBStream sstr;
560        sb_error.GetDescription (sstr);
561        log->Printf ("SBProcess(%p)::Stop () => SBError (%p): %s",
562                     m_opaque_sp.get(),
563                     sb_error.get(),
564                     sstr.GetData());
565    }
566
567    return sb_error;
568}
569
570SBError
571SBProcess::Kill ()
572{
573    SBError sb_error;
574    if (m_opaque_sp)
575    {
576        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
577        sb_error.SetError (m_opaque_sp->Destroy());
578    }
579    else
580        sb_error.SetErrorString ("SBProcess is invalid");
581
582    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
583    if (log)
584    {
585        SBStream sstr;
586        sb_error.GetDescription (sstr);
587        log->Printf ("SBProcess(%p)::Kill () => SBError (%p): %s",
588                     m_opaque_sp.get(),
589                     sb_error.get(),
590                     sstr.GetData());
591    }
592
593    return sb_error;
594}
595
596SBError
597SBProcess::Detach ()
598{
599    SBError sb_error;
600    if (m_opaque_sp)
601    {
602        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
603        sb_error.SetError (m_opaque_sp->Detach());
604    }
605    else
606        sb_error.SetErrorString ("SBProcess is invalid");
607
608    return sb_error;
609}
610
611SBError
612SBProcess::Signal (int signo)
613{
614    SBError sb_error;
615    if (m_opaque_sp)
616    {
617        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
618        sb_error.SetError (m_opaque_sp->Signal (signo));
619    }
620    else
621        sb_error.SetErrorString ("SBProcess is invalid");
622    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
623    if (log)
624    {
625        SBStream sstr;
626        sb_error.GetDescription (sstr);
627        log->Printf ("SBProcess(%p)::Signal (signo=%i) => SBError (%p): %s",
628                     m_opaque_sp.get(),
629                     signo,
630                     sb_error.get(),
631                     sstr.GetData());
632    }
633    return sb_error;
634}
635
636SBThread
637SBProcess::GetThreadByID (tid_t tid)
638{
639    SBThread sb_thread;
640    if (m_opaque_sp)
641    {
642        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
643        sb_thread.SetThread (m_opaque_sp->GetThreadList().FindThreadByID ((tid_t) tid));
644    }
645
646    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
647    if (log)
648    {
649        log->Printf ("SBProcess(%p)::GetThreadByID (tid=0x%4.4x) => SBThread (%p)",
650                     m_opaque_sp.get(),
651                     tid,
652                     sb_thread.get());
653    }
654
655    return sb_thread;
656}
657
658StateType
659SBProcess::GetStateFromEvent (const SBEvent &event)
660{
661    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
662
663    StateType ret_val = Process::ProcessEventData::GetStateFromEvent (event.get());
664
665    if (log)
666        log->Printf ("SBProcess::GetStateFromEvent (event.sp=%p) => %s", event.get(),
667                     lldb_private::StateAsCString (ret_val));
668
669    return ret_val;
670}
671
672bool
673SBProcess::GetRestartedFromEvent (const SBEvent &event)
674{
675    return Process::ProcessEventData::GetRestartedFromEvent (event.get());
676}
677
678SBProcess
679SBProcess::GetProcessFromEvent (const SBEvent &event)
680{
681    SBProcess process(Process::ProcessEventData::GetProcessFromEvent (event.get()));
682    return process;
683}
684
685
686SBBroadcaster
687SBProcess::GetBroadcaster () const
688{
689    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
690
691    SBBroadcaster broadcaster(m_opaque_sp.get(), false);
692
693    if (log)
694        log->Printf ("SBProcess(%p)::GetBroadcaster () => SBBroadcaster (%p)",  m_opaque_sp.get(),
695                     broadcaster.get());
696
697    return broadcaster;
698}
699
700lldb_private::Process *
701SBProcess::operator->() const
702{
703    return m_opaque_sp.get();
704}
705
706size_t
707SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error)
708{
709    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
710
711    size_t bytes_read = 0;
712
713    if (log)
714    {
715        log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%llx, dst=%p, dst_len=%zu, SBError (%p))...",
716                     m_opaque_sp.get(),
717                     addr,
718                     dst,
719                     (uint32_t) dst_len,
720                     sb_error.get());
721    }
722
723    if (m_opaque_sp)
724    {
725        Error error;
726        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
727        bytes_read = m_opaque_sp->ReadMemory (addr, dst, dst_len, error);
728        sb_error.SetError (error);
729    }
730    else
731    {
732        sb_error.SetErrorString ("SBProcess is invalid");
733    }
734
735    if (log)
736    {
737        SBStream sstr;
738        sb_error.GetDescription (sstr);
739        log->Printf ("SBProcess(%p)::ReadMemory (addr=0x%llx, dst=%p, dst_len=%zu, SBError (%p): %s) => %d",
740                     m_opaque_sp.get(),
741                     addr,
742                     dst,
743                     (uint32_t) dst_len,
744                     sb_error.get(),
745                     sstr.GetData(),
746                     (uint32_t) bytes_read);
747    }
748
749    return bytes_read;
750}
751
752size_t
753SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &sb_error)
754{
755    size_t bytes_written = 0;
756
757    LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
758    if (log)
759    {
760        log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%llx, src=%p, dst_len=%zu, SBError (%p))...",
761                     m_opaque_sp.get(),
762                     addr,
763                     src,
764                     (uint32_t) src_len,
765                     sb_error.get());
766    }
767
768    if (m_opaque_sp)
769    {
770        Error error;
771        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
772        bytes_written = m_opaque_sp->WriteMemory (addr, src, src_len, error);
773        sb_error.SetError (error);
774    }
775
776    if (log)
777    {
778        SBStream sstr;
779        sb_error.GetDescription (sstr);
780        log->Printf ("SBProcess(%p)::WriteMemory (addr=0x%llx, src=%p, dst_len=%zu, SBError (%p): %s) => %d",
781                     m_opaque_sp.get(),
782                     addr,
783                     src,
784                     (uint32_t) src_len,
785                     sb_error.get(),
786                     sstr.GetData(),
787                     (uint32_t) bytes_written);
788    }
789
790    return bytes_written;
791}
792
793// Mimic shared pointer...
794lldb_private::Process *
795SBProcess::get() const
796{
797    return m_opaque_sp.get();
798}
799
800bool
801SBProcess::GetDescription (SBStream &description)
802{
803    if (m_opaque_sp)
804    {
805        char path[PATH_MAX];
806        GetTarget().GetExecutable().GetPath (path, sizeof(path));
807        Module *exe_module = m_opaque_sp->GetTarget().GetExecutableModulePointer();
808        const char *exe_name = NULL;
809        if (exe_module)
810            exe_name = exe_module->GetFileSpec().GetFilename().AsCString();
811
812        description.Printf ("SBProcess: pid = %llu, state = %s, threads = %d%s%s",
813                            m_opaque_sp->GetID(),
814                            lldb_private::StateAsCString (GetState()),
815                            GetNumThreads(),
816                            exe_name ? ", executable = " : "",
817                            exe_name ? exe_name : "");
818    }
819    else
820        description.Printf ("No value");
821
822    return true;
823}
824
825uint32_t
826SBProcess::LoadImage (lldb::SBFileSpec &sb_image_spec, lldb::SBError &sb_error)
827{
828    if (m_opaque_sp)
829    {
830        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
831        return m_opaque_sp->LoadImage (*sb_image_spec, sb_error.ref());
832    }
833    return LLDB_INVALID_IMAGE_TOKEN;
834}
835
836lldb::SBError
837SBProcess::UnloadImage (uint32_t image_token)
838{
839    lldb::SBError sb_error;
840    if (m_opaque_sp)
841    {
842        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
843        sb_error.SetError (m_opaque_sp->UnloadImage (image_token));
844    }
845    else
846        sb_error.SetErrorString("invalid process");
847    return sb_error;
848}
849
850
851