blob: ecf8479ddde683bd8686a58ca993dab84d4a86d9 [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
11// C++ Includes
12// Other libraries and framework includes
13#include "lldb/Core/PluginManager.h"
14#include "lldb/Host/Host.h"
15#include "lldb/Symbol/ObjectFile.h"
Stephen Wilson92241ef2011-01-16 19:45:39 +000016#include "lldb/Target/DynamicLoader.h"
Stephen Wilsonf6f40332010-07-24 02:19:04 +000017#include "lldb/Target/Target.h"
18
19#include "ProcessLinux.h"
20#include "ProcessMonitor.h"
21#include "LinuxThread.h"
22
23using namespace lldb;
24using namespace lldb_private;
25
26//------------------------------------------------------------------------------
27// Static functions.
28
29Process*
30ProcessLinux::CreateInstance(Target& target, Listener &listener)
31{
32 return new ProcessLinux(target, listener);
33}
34
35void
36ProcessLinux::Initialize()
37{
38 static bool g_initialized = false;
39
40 if (!g_initialized)
41 {
42 PluginManager::RegisterPlugin(GetPluginNameStatic(),
43 GetPluginDescriptionStatic(),
44 CreateInstance);
45 g_initialized = true;
46 }
47}
48
49void
50ProcessLinux::Terminate()
51{
52}
53
54const char *
55ProcessLinux::GetPluginNameStatic()
56{
57 return "plugin.process.linux";
58}
59
60const char *
61ProcessLinux::GetPluginDescriptionStatic()
62{
63 return "Process plugin for Linux";
64}
65
66
67//------------------------------------------------------------------------------
68// Constructors and destructors.
69
70ProcessLinux::ProcessLinux(Target& target, Listener &listener)
71 : Process(target, listener),
72 m_monitor(NULL),
73 m_module(NULL)
74{
75 // FIXME: Putting this code in the ctor and saving the byte order in a
76 // member variable is a hack to avoid const qual issues in GetByteOrder.
77 ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
78 m_byte_order = obj_file->GetByteOrder();
79}
80
81ProcessLinux::~ProcessLinux()
82{
83 delete m_monitor;
84}
85
86//------------------------------------------------------------------------------
87// Process protocol.
88
89bool
90ProcessLinux::CanDebug(Target &target)
91{
92 // For now we are just making sure the file exists for a given module
93 ModuleSP exe_module_sp(target.GetExecutableModule());
94 if (exe_module_sp.get())
95 return exe_module_sp->GetFileSpec().Exists();
96 return false;
97}
98
99Error
100ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid)
101{
102 return Error(1, eErrorTypeGeneric);
103}
104
105Error
Stephen Wilson92241ef2011-01-16 19:45:39 +0000106ProcessLinux::WillLaunch(Module* module)
107{
108 Error error;
109
110 m_dyld_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.linux-dyld"));
111 if (m_dyld_ap.get() == NULL)
112 error.SetErrorString("unable to find the dynamic loader named "
113 "'dynamic-loader.linux-dyld'");
114
115 return error;
116}
117
118Error
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000119ProcessLinux::DoLaunch(Module *module,
120 char const *argv[],
121 char const *envp[],
Stephen Wilson3a804312011-01-04 21:41:31 +0000122 uint32_t launch_flags,
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000123 const char *stdin_path,
124 const char *stdout_path,
125 const char *stderr_path)
126{
127 Error error;
128 assert(m_monitor == NULL);
129
130 SetPrivateState(eStateLaunching);
131 m_monitor = new ProcessMonitor(this, module,
132 argv, envp,
133 stdin_path, stdout_path, stderr_path,
134 error);
135
136 m_module = module;
137
138 if (!error.Success())
139 return error;
140
Stephen Wilson1f004c62011-01-15 00:13:27 +0000141 SetID(m_monitor->GetPID());
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000142 return error;
143}
144
Stephen Wilson92241ef2011-01-16 19:45:39 +0000145void
146ProcessLinux::DidLaunch()
147{
148 if (m_dyld_ap.get() != NULL)
149 m_dyld_ap->DidLaunch();
150}
151
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000152Error
153ProcessLinux::DoResume()
154{
155 assert(GetPrivateState() == eStateStopped && "Bad state for DoResume!");
156
157 // Set our state to running. This ensures inferior threads do not post a
158 // state change first.
159 SetPrivateState(eStateRunning);
160
161 bool did_resume = false;
162 uint32_t thread_count = m_thread_list.GetSize(false);
163 for (uint32_t i = 0; i < thread_count; ++i)
164 {
165 LinuxThread *thread = static_cast<LinuxThread*>(
166 m_thread_list.GetThreadAtIndex(i, false).get());
167 did_resume = thread->Resume() || did_resume;
168 }
169 assert(did_resume && "Process resume failed!");
170
171 return Error();
172}
173
Stephen Wilson01316422011-01-15 00:10:37 +0000174addr_t
175ProcessLinux::GetImageInfoAddress()
176{
177 Target *target = &GetTarget();
178 ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
179 Address addr = obj_file->GetImageInfoAddress();
180
181 if (addr.IsValid())
182 return addr.GetLoadAddress(target);
183 else
184 return LLDB_INVALID_ADDRESS;
185}
186
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000187Error
Stephen Wilson3a804312011-01-04 21:41:31 +0000188ProcessLinux::DoHalt(bool &caused_stop)
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000189{
190 return Error(1, eErrorTypeGeneric);
191}
192
193Error
194ProcessLinux::DoDetach()
195{
196 return Error(1, eErrorTypeGeneric);
197}
198
199Error
200ProcessLinux::DoSignal(int signal)
201{
202 return Error(1, eErrorTypeGeneric);
203}
204
205Error
206ProcessLinux::DoDestroy()
207{
208 Error error;
209
210 if (!HasExited())
211 {
Greg Clayton5d187e52011-01-08 20:28:42 +0000212 // Shut down the private state thread as we will synchronize with events
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000213 // ourselves. Discard all current thread plans.
214 PausePrivateStateThread();
215 GetThreadList().DiscardThreadPlans();
216
217 // Bringing the inferior into limbo will be caught by our monitor
218 // thread, in turn updating the process state.
219 if (!m_monitor->BringProcessIntoLimbo())
220 {
221 error.SetErrorToGenericError();
222 error.SetErrorString("Process termination failed.");
223 return error;
224 }
225
Stephen Wilson83047fc2011-01-19 01:30:44 +0000226 // Wait for the event to arrive. This is guaranteed to be an exit event.
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000227 StateType state;
228 EventSP event;
229 do {
Stephen Wilson83047fc2011-01-19 01:30:44 +0000230 TimeValue timeout_time;
231 timeout_time = TimeValue::Now();
232 timeout_time.OffsetWithSeconds(2);
233 state = WaitForStateChangedEventsPrivate(&timeout_time, event);
234 } while (state != eStateExited && state != eStateInvalid);
235
236 // Check if we timed out waiting for the exit event to arrive.
237 if (state == eStateInvalid)
238 error.SetErrorString("ProcessLinux::DoDestroy timed out.");
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000239
240 // Restart standard event handling and send the process the final kill,
241 // driving it out of limbo.
242 ResumePrivateStateThread();
243 }
244
Stephen Wilson83047fc2011-01-19 01:30:44 +0000245 if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000246 error.SetErrorToErrno();
Stephen Wilson83047fc2011-01-19 01:30:44 +0000247
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000248 return error;
249}
250
251void
252ProcessLinux::SendMessage(const ProcessMessage &message)
253{
254 Mutex::Locker lock(m_message_mutex);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000255
256 switch (message.GetKind())
257 {
258 default:
259 SetPrivateState(eStateStopped);
260 break;
261
Stephen Wilson07fc7a92011-01-19 01:29:39 +0000262 case ProcessMessage::eInvalidMessage:
263 return;
264
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000265 case ProcessMessage::eExitMessage:
266 SetExitStatus(message.GetExitStatus(), NULL);
267 break;
268
269 case ProcessMessage::eSignalMessage:
270 SetExitStatus(-1, NULL);
271 break;
272 }
Stephen Wilson07fc7a92011-01-19 01:29:39 +0000273
274 m_message_queue.push(message);
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000275}
276
277void
278ProcessLinux::RefreshStateAfterStop()
279{
280 Mutex::Locker lock(m_message_mutex);
281 if (m_message_queue.empty())
282 return;
283
284 ProcessMessage &message = m_message_queue.front();
285
286 // Resolve the thread this message corresponds to.
287 lldb::tid_t tid = message.GetTID();
288 LinuxThread *thread = static_cast<LinuxThread*>(
289 GetThreadList().FindThreadByID(tid, false).get());
290
291 switch (message.GetKind())
292 {
293 default:
294 assert(false && "Unexpected message kind!");
295 break;
296
297 case ProcessMessage::eExitMessage:
298 case ProcessMessage::eSignalMessage:
299 thread->ExitNotify();
300 break;
301
302 case ProcessMessage::eTraceMessage:
303 thread->TraceNotify();
304 break;
305
306 case ProcessMessage::eBreakpointMessage:
307 thread->BreakNotify();
308 break;
309 }
310
311 m_message_queue.pop();
312}
313
314bool
315ProcessLinux::IsAlive()
316{
317 StateType state = GetPrivateState();
318 return state != eStateExited && state != eStateInvalid;
319}
320
321size_t
322ProcessLinux::DoReadMemory(addr_t vm_addr,
323 void *buf, size_t size, Error &error)
324{
325 return m_monitor->ReadMemory(vm_addr, buf, size, error);
326}
327
328size_t
329ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
330 Error &error)
331{
332 return m_monitor->WriteMemory(vm_addr, buf, size, error);
333}
334
335addr_t
336ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions,
337 Error &error)
338{
339 return 0;
340}
341
342addr_t
343ProcessLinux::AllocateMemory(size_t size, uint32_t permissions, Error &error)
344{
345 return 0;
346}
347
348Error
349ProcessLinux::DoDeallocateMemory(lldb::addr_t ptr)
350{
351 return Error(1, eErrorTypeGeneric);
352}
353
354size_t
355ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
356{
357 static const uint8_t g_i386_opcode[] = { 0xCC };
358
359 ArchSpec arch = GetTarget().GetArchitecture();
360 const uint8_t *opcode = NULL;
361 size_t opcode_size = 0;
362
363 switch (arch.GetGenericCPUType())
364 {
365 default:
366 assert(false && "CPU type not supported!");
367 break;
368
369 case ArchSpec::eCPU_i386:
370 case ArchSpec::eCPU_x86_64:
371 opcode = g_i386_opcode;
372 opcode_size = sizeof(g_i386_opcode);
373 break;
374 }
375
376 bp_site->SetTrapOpcode(opcode, opcode_size);
377 return opcode_size;
378}
379
380Error
381ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site)
382{
383 return EnableSoftwareBreakpoint(bp_site);
384}
385
386Error
387ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site)
388{
389 return DisableSoftwareBreakpoint(bp_site);
390}
391
392uint32_t
393ProcessLinux::UpdateThreadListIfNeeded()
394{
395 // Do not allow recursive updates.
396 return m_thread_list.GetSize(false);
397}
398
399ByteOrder
400ProcessLinux::GetByteOrder() const
401{
402 // FIXME: We should be able to extract this value directly. See comment in
403 // ProcessLinux().
404 return m_byte_order;
405}
406
Stephen Wilson92241ef2011-01-16 19:45:39 +0000407DynamicLoader *
408ProcessLinux::GetDynamicLoader()
409{
410 return m_dyld_ap.get();
411}
412
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000413//------------------------------------------------------------------------------
414// ProcessInterface protocol.
415
416const char *
417ProcessLinux::GetPluginName()
418{
419 return "process.linux";
420}
421
422const char *
423ProcessLinux::GetShortPluginName()
424{
425 return "process.linux";
426}
427
428uint32_t
429ProcessLinux::GetPluginVersion()
430{
431 return 1;
432}
433
434void
435ProcessLinux::GetPluginCommandHelp(const char *command, Stream *strm)
436{
437}
438
439Error
440ProcessLinux::ExecutePluginCommand(Args &command, Stream *strm)
441{
442 return Error(1, eErrorTypeGeneric);
443}
444
445Log *
446ProcessLinux::EnablePluginLogging(Stream *strm, Args &command)
447{
448 return NULL;
449}
450
451//------------------------------------------------------------------------------
452// Utility functions.
453
Stephen Wilsonf6f40332010-07-24 02:19:04 +0000454bool
455ProcessLinux::HasExited()
456{
457 switch (GetPrivateState())
458 {
459 default:
460 break;
461
462 case eStateUnloaded:
463 case eStateCrashed:
464 case eStateDetached:
465 case eStateExited:
466 return true;
467 }
468
469 return false;
470}