blob: f915888ef1864d77e2a6e3ce91d554588060f675 [file] [log] [blame]
Stephen Wilsonf6f40332010-07-24 02:19:04 +00001//===-- ProcessLinux.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// C Includes
Stephen Wilsond1fbbb42011-03-23 02:14:42 +000011#include <errno.h>
12
Stephen Wilsonf6f40332010-07-24 02:19:04 +000013// C++ Includes
14// Other libraries and framework includes
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Host/Host.h"
17#include "lldb/Symbol/ObjectFile.h"
Stephen Wilson92241ef2011-01-16 19:45:39 +000018#include "lldb/Target/DynamicLoader.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000019#include "lldb/Target/Target.h"
20
21#include "ProcessLinux.h"
22#include "ProcessMonitor.h"
23#include "LinuxThread.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28//------------------------------------------------------------------------------
29// Static functions.
30
31Process*
32ProcessLinux::CreateInstance(Target& target, Listener &listener)
33{
34 return new ProcessLinux(target, listener);
35}
36
37void
38ProcessLinux::Initialize()
39{
40 static bool g_initialized = false;
41
42 if (!g_initialized)
43 {
44 PluginManager::RegisterPlugin(GetPluginNameStatic(),
45 GetPluginDescriptionStatic(),
46 CreateInstance);
47 g_initialized = true;
48 }
49}
50
51void
52ProcessLinux::Terminate()
53{
54}
55
56const char *
57ProcessLinux::GetPluginNameStatic()
58{
59 return "plugin.process.linux";
60}
61
62const char *
63ProcessLinux::GetPluginDescriptionStatic()
64{
65 return "Process plugin for Linux";
66}
67
68
69//------------------------------------------------------------------------------
70// Constructors and destructors.
71
72ProcessLinux::ProcessLinux(Target& target, Listener &listener)
73 : Process(target, listener),
74 m_monitor(NULL),
Stephen Wilson67d9f7e2011-03-30 15:55:52 +000075 m_module(NULL),
76 m_in_limbo(false),
77 m_exit_now(false)
Stephen Wilsonf6f40332010-07-24 02:19:04 +000078{
79 // FIXME: Putting this code in the ctor and saving the byte order in a
80 // member variable is a hack to avoid const qual issues in GetByteOrder.
81 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
82 m_byte_order = obj_file->GetByteOrder();
83}
84
85ProcessLinux::~ProcessLinux()
86{
87 delete m_monitor;
88}
89
90//------------------------------------------------------------------------------
91// Process protocol.
92
93bool
94ProcessLinux::CanDebug(Target &target)
95{
96 // For now we are just making sure the file exists for a given module
97 ModuleSP exe_module_sp(target.GetExecutableModule());
98 if (exe_module_sp.get())
99 return exe_module_sp->GetFileSpec().Exists();
100 return false;
101}
102
103Error
104ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
105{
106 return Error(1, eErrorTypeGeneric);
107}
108
109Error
Stephen Wilson92241ef2011-01-16 19:45:39 +0000110ProcessLinux::WillLaunch(Module* module)
111{
112 Error error;
Stephen Wilson92241ef2011-01-16 19:45:39 +0000113 return error;
114}
115
116Error
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000117ProcessLinux::DoLaunch(Module *module,
118 char const *argv[],
119 char const *envp[],
Stephen Wilson3a804312011-01-04 21:41:31 +0000120 uint32_t launch_flags,
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000121 const char *stdin_path,
122 const char *stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000123 const char *stderr_path,
124 const char *working_directory)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000125{
126 Error error;
127 assert(m_monitor == NULL);
128
129 SetPrivateState(eStateLaunching);
130 m_monitor = new ProcessMonitor(this, module,
131 argv, envp,
132 stdin_path, stdout_path, stderr_path,
133 error);
134
135 m_module = module;
136
137 if (!error.Success())
138 return error;
139
Stephen Wilson1f004c62011-01-15 00:13:27 +0000140 SetID(m_monitor->GetPID());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000141 return error;
142}
143
Stephen Wilson92241ef2011-01-16 19:45:39 +0000144void
145ProcessLinux::DidLaunch()
146{
Stephen Wilson92241ef2011-01-16 19:45:39 +0000147}
148
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000149Error
150ProcessLinux::DoResume()
151{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000152 StateType state = GetPrivateState();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000153
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000154 assert(state == eStateStopped || state == eStateCrashed);
155
156 // We are about to resume a thread that will cause the process to exit so
157 // set our exit status now. Do not change our state if the inferior
158 // crashed.
159 if (state == eStateStopped)
160 {
161 if (m_in_limbo)
162 SetExitStatus(m_exit_status, NULL);
163 else
164 SetPrivateState(eStateRunning);
165 }
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000166
167 bool did_resume = false;
168 uint32_t thread_count = m_thread_list.GetSize(false);
169 for (uint32_t i = 0; i < thread_count; ++i)
170 {
171 LinuxThread *thread = static_cast<LinuxThread*>(
172 m_thread_list.GetThreadAtIndex(i, false).get());
173 did_resume = thread->Resume() || did_resume;
174 }
175 assert(did_resume && "Process resume failed!");
176
177 return Error();
178}
179
Stephen Wilson01316422011-01-15 00:10:37 +0000180addr_t
181ProcessLinux::GetImageInfoAddress()
182{
183 Target *target = &GetTarget();
184 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
185 Address addr = obj_file->GetImageInfoAddress();
186
187 if (addr.IsValid())
188 return addr.GetLoadAddress(target);
189 else
190 return LLDB_INVALID_ADDRESS;
191}
192
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000193Error
Stephen Wilson3a804312011-01-04 21:41:31 +0000194ProcessLinux::DoHalt(bool &caused_stop)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000195{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000196 Error error;
197
198 if (IsStopped())
199 {
200 caused_stop = false;
201 }
202 else if (kill(GetID(), SIGSTOP))
203 {
204 caused_stop = false;
205 error.SetErrorToErrno();
206 }
207 else
208 {
209 caused_stop = true;
210 }
211
212 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000213}
214
215Error
216ProcessLinux::DoDetach()
217{
218 return Error(1, eErrorTypeGeneric);
219}
220
221Error
222ProcessLinux::DoSignal(int signal)
223{
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000224 Error error;
225
226 if (kill(GetID(), signal))
227 error.SetErrorToErrno();
228
229 return error;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000230}
231
232Error
233ProcessLinux::DoDestroy()
234{
235 Error error;
236
237 if (!HasExited())
238 {
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000239 // Drive the exit event to completion (do not keep the inferior in
240 // limbo).
241 m_exit_now = true;
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000242
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000243 if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000244 {
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000245 error.SetErrorToErrno();
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000246 return error;
247 }
248
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000249 SetPrivateState(eStateExited);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000250 }
251
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000252 return error;
253}
254
255void
256ProcessLinux::SendMessage(const ProcessMessage &message)
257{
258 Mutex::Locker lock(m_message_mutex);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000259
260 switch (message.GetKind())
261 {
262 default:
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000263 assert(false && "Unexpected process message!");
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000264 break;
265
Stephen Wilson07fc7a92011-01-19 01:29:39 +0000266 case ProcessMessage::eInvalidMessage:
267 return;
268
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000269 case ProcessMessage::eLimboMessage:
270 m_in_limbo = true;
271 m_exit_status = message.GetExitStatus();
272 if (m_exit_now)
273 {
274 SetPrivateState(eStateExited);
275 m_monitor->Detach();
276 }
277 else
278 SetPrivateState(eStateStopped);
279 break;
280
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000281 case ProcessMessage::eExitMessage:
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000282 m_exit_status = message.GetExitStatus();
283 SetExitStatus(m_exit_status, NULL);
284 break;
285
286 case ProcessMessage::eTraceMessage:
287 case ProcessMessage::eBreakpointMessage:
288 SetPrivateState(eStateStopped);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000289 break;
290
291 case ProcessMessage::eSignalMessage:
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000292 case ProcessMessage::eSignalDeliveredMessage:
293 SetPrivateState(eStateStopped);
294 break;
295
296 case ProcessMessage::eCrashMessage:
297 SetPrivateState(eStateCrashed);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000298 break;
299 }
Stephen Wilson07fc7a92011-01-19 01:29:39 +0000300
301 m_message_queue.push(message);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000302}
303
304void
305ProcessLinux::RefreshStateAfterStop()
306{
307 Mutex::Locker lock(m_message_mutex);
308 if (m_message_queue.empty())
309 return;
310
311 ProcessMessage &message = m_message_queue.front();
312
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000313 // Resolve the thread this message corresponds to and pass it along.
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000314 lldb::tid_t tid = message.GetTID();
315 LinuxThread *thread = static_cast<LinuxThread*>(
316 GetThreadList().FindThreadByID(tid, false).get());
317
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000318 thread->Notify(message);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000319
320 m_message_queue.pop();
321}
322
323bool
324ProcessLinux::IsAlive()
325{
326 StateType state = GetPrivateState();
327 return state != eStateExited && state != eStateInvalid;
328}
329
330size_t
331ProcessLinux::DoReadMemory(addr_t vm_addr,
332 void *buf, size_t size, Error &error)
333{
334 return m_monitor->ReadMemory(vm_addr, buf, size, error);
335}
336
337size_t
338ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
339 Error &error)
340{
341 return m_monitor->WriteMemory(vm_addr, buf, size, error);
342}
343
344addr_t
345ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions,
346 Error &error)
347{
348 return 0;
349}
350
351addr_t
352ProcessLinux::AllocateMemory(size_t size, uint32_t permissions, Error &error)
353{
354 return 0;
355}
356
357Error
358ProcessLinux::DoDeallocateMemory(lldb::addr_t ptr)
359{
360 return Error(1, eErrorTypeGeneric);
361}
362
363size_t
364ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
365{
366 static const uint8_t g_i386_opcode[] = { 0xCC };
367
368 ArchSpec arch = GetTarget().GetArchitecture();
369 const uint8_t *opcode = NULL;
370 size_t opcode_size = 0;
371
Stephen Wilsona1f0b722011-02-24 19:17:09 +0000372 switch (arch.GetCore())
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000373 {
374 default:
375 assert(false && "CPU type not supported!");
376 break;
377
Stephen Wilsona1f0b722011-02-24 19:17:09 +0000378 case ArchSpec::eCore_x86_32_i386:
379 case ArchSpec::eCore_x86_64_x86_64:
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000380 opcode = g_i386_opcode;
381 opcode_size = sizeof(g_i386_opcode);
382 break;
383 }
384
385 bp_site->SetTrapOpcode(opcode, opcode_size);
386 return opcode_size;
387}
388
389Error
390ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site)
391{
392 return EnableSoftwareBreakpoint(bp_site);
393}
394
395Error
396ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site)
397{
398 return DisableSoftwareBreakpoint(bp_site);
399}
400
401uint32_t
402ProcessLinux::UpdateThreadListIfNeeded()
403{
404 // Do not allow recursive updates.
405 return m_thread_list.GetSize(false);
406}
407
408ByteOrder
409ProcessLinux::GetByteOrder() const
410{
411 // FIXME: We should be able to extract this value directly. See comment in
412 // ProcessLinux().
413 return m_byte_order;
414}
415
Stephen Wilsond1fbbb42011-03-23 02:14:42 +0000416size_t
417ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error)
418{
419 ssize_t status;
420 if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
421 {
422 error.SetErrorToErrno();
423 return 0;
424 }
425 return status;
426}
427
428size_t
429ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error)
430{
431 ssize_t bytes_read;
432
433 // The terminal file descriptor is always in non-block mode.
434 if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0)
435 {
436 if (errno != EAGAIN)
437 error.SetErrorToErrno();
438 return 0;
439 }
440 return bytes_read;
441}
442
443size_t
444ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error)
445{
446 return GetSTDOUT(buf, len, error);
447}
448
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000449UnixSignals &
450ProcessLinux::GetUnixSignals()
451{
452 return m_linux_signals;
453}
Stephen Wilsond1fbbb42011-03-23 02:14:42 +0000454
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000455//------------------------------------------------------------------------------
456// ProcessInterface protocol.
457
458const char *
459ProcessLinux::GetPluginName()
460{
461 return "process.linux";
462}
463
464const char *
465ProcessLinux::GetShortPluginName()
466{
467 return "process.linux";
468}
469
470uint32_t
471ProcessLinux::GetPluginVersion()
472{
473 return 1;
474}
475
476void
477ProcessLinux::GetPluginCommandHelp(const char *command, Stream *strm)
478{
479}
480
481Error
482ProcessLinux::ExecutePluginCommand(Args &command, Stream *strm)
483{
484 return Error(1, eErrorTypeGeneric);
485}
486
487Log *
488ProcessLinux::EnablePluginLogging(Stream *strm, Args &command)
489{
490 return NULL;
491}
492
493//------------------------------------------------------------------------------
494// Utility functions.
495
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000496bool
497ProcessLinux::HasExited()
498{
499 switch (GetPrivateState())
500 {
501 default:
502 break;
503
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000504 case eStateDetached:
505 case eStateExited:
506 return true;
507 }
508
509 return false;
510}
Stephen Wilson67d9f7e2011-03-30 15:55:52 +0000511
512bool
513ProcessLinux::IsStopped()
514{
515 switch (GetPrivateState())
516 {
517 default:
518 break;
519
520 case eStateStopped:
521 case eStateCrashed:
522 case eStateSuspended:
523 return true;
524 }
525
526 return false;
527}