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/State.h"
19 #include "lldb/Core/Stream.h"
20 #include "lldb/Core/StreamFile.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/RegisterContext.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 
26 // Project includes
27 
28 #include "lldb/API/SBBroadcaster.h"
29 #include "lldb/API/SBDebugger.h"
30 #include "lldb/API/SBCommandReturnObject.h"
31 #include "lldb/API/SBEvent.h"
32 #include "lldb/API/SBThread.h"
33 #include "lldb/API/SBStream.h"
34 #include "lldb/API/SBStringList.h"
35 
36 using namespace lldb;
37 using namespace lldb_private;
38 
39 
40 
41 SBProcess::SBProcess () :
42     m_opaque_sp()
43 {
44 }
45 
46 
47 //----------------------------------------------------------------------
48 // SBProcess constructor
49 //----------------------------------------------------------------------
50 
51 SBProcess::SBProcess (const SBProcess& rhs) :
52     m_opaque_sp (rhs.m_opaque_sp)
53 {
54 }
55 
56 
57 SBProcess::SBProcess (const lldb::ProcessSP &process_sp) :
58     m_opaque_sp (process_sp)
59 {
60 }
61 
62 //----------------------------------------------------------------------
63 // Destructor
64 //----------------------------------------------------------------------
65 SBProcess::~SBProcess()
66 {
67 }
68 
69 void
70 SBProcess::SetProcess (const ProcessSP &process_sp)
71 {
72     m_opaque_sp = process_sp;
73 }
74 
75 void
76 SBProcess::Clear ()
77 {
78     m_opaque_sp.reset();
79 }
80 
81 
82 bool
83 SBProcess::IsValid() const
84 {
85     return m_opaque_sp.get() != NULL;
86 }
87 
88 
89 uint32_t
90 SBProcess::GetNumThreads ()
91 {
92     if (m_opaque_sp)
93     {
94         const bool can_update = true;
95         return m_opaque_sp->GetThreadList().GetSize(can_update);
96     }
97     return 0;
98 }
99 
100 SBThread
101 SBProcess::GetSelectedThread () const
102 {
103     SBThread sb_thread;
104     if (m_opaque_sp)
105         sb_thread.SetThread (m_opaque_sp->GetThreadList().GetSelectedThread());
106     return sb_thread;
107 }
108 
109 SBTarget
110 SBProcess::GetTarget() const
111 {
112     SBTarget sb_target;
113     if (m_opaque_sp)
114         sb_target = m_opaque_sp->GetTarget().GetSP();
115     return sb_target;
116 }
117 
118 
119 size_t
120 SBProcess::PutSTDIN (const char *src, size_t src_len)
121 {
122     if (m_opaque_sp != NULL)
123     {
124         Error error;
125         return m_opaque_sp->PutSTDIN (src, src_len, error);
126     }
127     else
128         return 0;
129 }
130 
131 size_t
132 SBProcess::GetSTDOUT (char *dst, size_t dst_len) const
133 {
134     if (m_opaque_sp != NULL)
135     {
136         Error error;
137         return m_opaque_sp->GetSTDOUT (dst, dst_len, error);
138     }
139     else
140         return 0;
141 }
142 
143 size_t
144 SBProcess::GetSTDERR (char *dst, size_t dst_len) const
145 {
146     if (m_opaque_sp != NULL)
147     {
148         Error error;
149         return m_opaque_sp->GetSTDERR (dst, dst_len, error);
150     }
151     else
152         return 0;
153 }
154 
155 void
156 SBProcess::ReportEventState (const SBEvent &event, FILE *out) const
157 {
158     if (out == NULL)
159         return;
160 
161     if (m_opaque_sp != NULL)
162     {
163         const StateType event_state = SBProcess::GetStateFromEvent (event);
164         char message[1024];
165         int message_len = ::snprintf (message,
166                                       sizeof (message),
167                                       "Process %d %s\n",
168                                       m_opaque_sp->GetID(),
169                                       SBDebugger::StateAsCString (event_state));
170 
171         if (message_len > 0)
172             ::fwrite (message, 1, message_len, out);
173     }
174 }
175 
176 void
177 SBProcess::AppendEventStateReport (const SBEvent &event, SBCommandReturnObject &result)
178 {
179     if (m_opaque_sp != NULL)
180     {
181         const StateType event_state = SBProcess::GetStateFromEvent (event);
182         char message[1024];
183         ::snprintf (message,
184                     sizeof (message),
185                     "Process %d %s\n",
186                     m_opaque_sp->GetID(),
187                     SBDebugger::StateAsCString (event_state));
188 
189         result.AppendMessage (message);
190     }
191 }
192 
193 bool
194 SBProcess::SetSelectedThread (const SBThread &thread)
195 {
196     if (m_opaque_sp != NULL)
197         return m_opaque_sp->GetThreadList().SetSelectedThreadByID (thread.GetThreadID());
198     return false;
199 }
200 
201 bool
202 SBProcess::SetSelectedThreadByID (uint32_t tid)
203 {
204     if (m_opaque_sp != NULL)
205         return m_opaque_sp->GetThreadList().SetSelectedThreadByID (tid);
206     return false;
207 }
208 
209 SBThread
210 SBProcess::GetThreadAtIndex (size_t index)
211 {
212     SBThread thread;
213     if (m_opaque_sp)
214         thread.SetThread (m_opaque_sp->GetThreadList().GetThreadAtIndex(index));
215     return thread;
216 }
217 
218 StateType
219 SBProcess::GetState ()
220 {
221     if (m_opaque_sp != NULL)
222         return m_opaque_sp->GetState();
223     else
224         return eStateInvalid;
225 }
226 
227 
228 int
229 SBProcess::GetExitStatus ()
230 {
231     if (m_opaque_sp != NULL)
232         return m_opaque_sp->GetExitStatus ();
233     else
234         return 0;
235 }
236 
237 const char *
238 SBProcess::GetExitDescription ()
239 {
240     if (m_opaque_sp != NULL)
241         return m_opaque_sp->GetExitDescription ();
242     else
243         return NULL;
244 }
245 
246 lldb::pid_t
247 SBProcess::GetProcessID ()
248 {
249     if (m_opaque_sp)
250         return m_opaque_sp->GetID();
251     else
252         return LLDB_INVALID_PROCESS_ID;
253 }
254 
255 uint32_t
256 SBProcess::GetAddressByteSize () const
257 {
258     if (m_opaque_sp)
259         return m_opaque_sp->GetAddressByteSize();
260     else
261         return 0;
262 }
263 
264 bool
265 SBProcess::WaitUntilProcessHasStopped (SBCommandReturnObject &result)
266 {
267     bool state_changed = false;
268 
269     if (IsValid())
270     {
271         EventSP event_sp;
272         StateType state = m_opaque_sp->WaitForStateChangedEvents (NULL, event_sp);
273 
274         while (StateIsStoppedState (state))
275         {
276             state = m_opaque_sp->WaitForStateChangedEvents (NULL, event_sp);
277             SBEvent event (event_sp);
278             AppendEventStateReport (event, result);
279             state_changed = true;
280         }
281     }
282     return state_changed;
283 }
284 
285 SBError
286 SBProcess::Continue ()
287 {
288     SBError sb_error;
289     if (IsValid())
290         sb_error.SetError(m_opaque_sp->Resume());
291     else
292         sb_error.SetErrorString ("SBProcess is invalid");
293 
294     return sb_error;
295 }
296 
297 
298 SBError
299 SBProcess::Destroy ()
300 {
301     SBError sb_error;
302     if (m_opaque_sp)
303         sb_error.SetError(m_opaque_sp->Destroy());
304     else
305         sb_error.SetErrorString ("SBProcess is invalid");
306 
307     return sb_error;
308 }
309 
310 
311 SBError
312 SBProcess::Stop ()
313 {
314     SBError sb_error;
315     if (IsValid())
316         sb_error.SetError (m_opaque_sp->Halt());
317     else
318         sb_error.SetErrorString ("SBProcess is invalid");
319     return sb_error;
320 }
321 
322 SBError
323 SBProcess::Kill ()
324 {
325     SBError sb_error;
326     if (m_opaque_sp)
327         sb_error.SetError (m_opaque_sp->Destroy());
328     else
329         sb_error.SetErrorString ("SBProcess is invalid");
330     return sb_error;
331 }
332 
333 
334 SBError
335 SBProcess::AttachByName (const char *name, bool wait_for_launch)
336 {
337     SBError sb_error;
338     if (m_opaque_sp)
339         sb_error.SetError (m_opaque_sp->Attach (name, wait_for_launch));
340     else
341         sb_error.SetErrorString ("SBProcess is invalid");
342     return sb_error;
343 }
344 
345 lldb::pid_t
346 SBProcess::AttachByPID (lldb::pid_t attach_pid) // DEPRECATED: will be removed in a few builds in favor of SBError AttachByPID(pid_t)
347 {
348     Attach (attach_pid);
349     return GetProcessID();
350 }
351 
352 
353 SBError
354 SBProcess::Attach (lldb::pid_t attach_pid)
355 {
356     SBError sb_error;
357     if (m_opaque_sp)
358         sb_error.SetError  (m_opaque_sp->Attach (attach_pid));
359     else
360         sb_error.SetErrorString ("SBProcess is invalid");
361     return sb_error;
362 }
363 
364 SBError
365 SBProcess::Detach ()
366 {
367     SBError sb_error;
368     if (m_opaque_sp)
369         sb_error.SetError (m_opaque_sp->Detach());
370     else
371         sb_error.SetErrorString ("SBProcess is invalid");
372 
373     return sb_error;
374 }
375 
376 SBError
377 SBProcess::Signal (int signal)
378 {
379     SBError sb_error;
380     if (m_opaque_sp)
381         sb_error.SetError (m_opaque_sp->Signal (signal));
382     else
383         sb_error.SetErrorString ("SBProcess is invalid");
384     return sb_error;
385 }
386 
387 SBThread
388 SBProcess::GetThreadByID (tid_t sb_thread_id)
389 {
390     SBThread thread;
391     if (m_opaque_sp)
392         thread.SetThread (m_opaque_sp->GetThreadList().FindThreadByID ((tid_t) sb_thread_id));
393     return thread;
394 }
395 
396 StateType
397 SBProcess::GetStateFromEvent (const SBEvent &event)
398 {
399     return Process::ProcessEventData::GetStateFromEvent (event.get());
400 }
401 
402 bool
403 SBProcess::GetRestartedFromEvent (const SBEvent &event)
404 {
405     return Process::ProcessEventData::GetRestartedFromEvent (event.get());
406 }
407 
408 SBProcess
409 SBProcess::GetProcessFromEvent (const SBEvent &event)
410 {
411     SBProcess process(Process::ProcessEventData::GetProcessFromEvent (event.get()));
412     return process;
413 }
414 
415 
416 SBBroadcaster
417 SBProcess::GetBroadcaster () const
418 {
419     SBBroadcaster broadcaster(m_opaque_sp.get(), false);
420     return broadcaster;
421 }
422 
423 lldb_private::Process *
424 SBProcess::operator->() const
425 {
426     return m_opaque_sp.get();
427 }
428 
429 size_t
430 SBProcess::ReadMemory (addr_t addr, void *dst, size_t dst_len, SBError &sb_error)
431 {
432     size_t bytes_read = 0;
433 
434     if (IsValid())
435     {
436         Error error;
437         bytes_read = m_opaque_sp->ReadMemory (addr, dst, dst_len, error);
438         sb_error.SetError (error);
439     }
440     else
441     {
442         sb_error.SetErrorString ("SBProcess is invalid");
443     }
444 
445     return bytes_read;
446 }
447 
448 size_t
449 SBProcess::WriteMemory (addr_t addr, const void *src, size_t src_len, SBError &sb_error)
450 {
451     size_t bytes_written = 0;
452 
453     if (IsValid())
454     {
455         Error error;
456         bytes_written = m_opaque_sp->WriteMemory (addr, src, src_len, error);
457         sb_error.SetError (error);
458     }
459 
460     return bytes_written;
461 }
462 
463 // Mimic shared pointer...
464 lldb_private::Process *
465 SBProcess::get() const
466 {
467     return m_opaque_sp.get();
468 }
469 
470 bool
471 SBProcess::GetDescription (SBStream &description)
472 {
473     if (m_opaque_sp)
474     {
475         char path[PATH_MAX];
476         GetTarget().GetExecutable().GetPath (path, sizeof(path));
477         description.Printf ("Process {pid: %d, executable %s\n", (int) GetProcessID(), path);
478         description.Printf ("         instance name: %s, state: %s, thread cnt: %d}",
479                             m_opaque_sp->GetInstanceName().AsCString(),
480                             SBDebugger::StateAsCString (GetState()),
481                             GetNumThreads());
482     }
483     else
484         description.Printf ("No value");
485 
486     return true;
487 }
488