1 //===-- PlatformFreeBSD.cpp ---------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/lldb-python.h"
12 #include "PlatformFreeBSD.h"
16 #include <sys/utsname.h>
19 // Other libraries and framework includes
21 #include "lldb/Core/Error.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/ModuleSpec.h"
25 #include "lldb/Core/PluginManager.h"
26 #include "lldb/Host/Host.h"
29 using namespace lldb_private;
32 PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
34 // The only time we create an instance is when we are creating a remote
36 const bool is_host = false;
39 if (create == false && arch && arch->IsValid())
41 const llvm::Triple &triple = arch->GetTriple();
42 switch (triple.getVendor())
44 case llvm::Triple::PC:
48 #if defined(__FreeBSD__) || defined(__OpenBSD__)
49 // Only accept "unknown" for the vendor if the host is BSD and
50 // it "unknown" wasn't specified (it was just returned becasue it
52 case llvm::Triple::UnknownArch:
53 create = !arch->TripleVendorWasSpecified();
62 switch (triple.getOS())
64 case llvm::Triple::FreeBSD:
65 case llvm::Triple::KFreeBSD:
68 #if defined(__FreeBSD__) || defined(__OpenBSD__)
69 // Only accept "unknown" for the OS if the host is BSD and
70 // it "unknown" wasn't specified (it was just returned becasue it
72 case llvm::Triple::UnknownOS:
73 create = arch->TripleOSWasSpecified();
83 return new PlatformFreeBSD (is_host);
88 lldb_private::ConstString
89 PlatformFreeBSD::GetPluginNameStatic (bool is_host)
93 static ConstString g_host_name(Platform::GetHostPlatformName ());
98 static ConstString g_remote_name("remote-freebsd");
104 PlatformFreeBSD::GetDescriptionStatic (bool is_host)
107 return "Local FreeBSD user platform plug-in.";
109 return "Remote FreeBSD user platform plug-in.";
112 static uint32_t g_initialize_count = 0;
115 PlatformFreeBSD::Initialize ()
117 if (g_initialize_count++ == 0)
119 #if defined (__FreeBSD__)
120 // Force a host flag to true for the default platform object.
121 PlatformSP default_platform_sp (new PlatformFreeBSD(true));
122 default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
123 Platform::SetDefaultPlatform (default_platform_sp);
125 PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
126 PlatformFreeBSD::GetDescriptionStatic(false),
127 PlatformFreeBSD::CreateInstance);
132 PlatformFreeBSD::Terminate ()
134 if (g_initialize_count > 0 && --g_initialize_count == 0)
135 PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
138 //------------------------------------------------------------------
139 /// Default Constructor
140 //------------------------------------------------------------------
141 PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
146 //------------------------------------------------------------------
149 /// The destructor is virtual since this class is designed to be
150 /// inherited from by the plug-in instance.
151 //------------------------------------------------------------------
152 PlatformFreeBSD::~PlatformFreeBSD()
158 PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
159 const ArchSpec &exe_arch,
160 lldb::ModuleSP &exe_module_sp,
161 const FileSpecList *module_search_paths_ptr)
164 // Nothing special to do here, just use the actual file and architecture
166 char exe_path[PATH_MAX];
167 FileSpec resolved_exe_file (exe_file);
171 // If we have "ls" as the exe_file, resolve the executable location based on
172 // the current path variables
173 if (!resolved_exe_file.Exists())
175 exe_file.GetPath(exe_path, sizeof(exe_path));
176 resolved_exe_file.SetFile(exe_path, true);
179 if (!resolved_exe_file.Exists())
180 resolved_exe_file.ResolveExecutableLocation ();
182 if (resolved_exe_file.Exists())
186 exe_file.GetPath(exe_path, sizeof(exe_path));
187 error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
192 if (m_remote_platform_sp)
194 error = m_remote_platform_sp->ResolveExecutable (exe_file,
197 module_search_paths_ptr);
201 // We may connect to a process and use the provided executable (Don't use local $PATH).
203 // Resolve any executable within a bundle on MacOSX
204 Host::ResolveExecutableInBundle (resolved_exe_file);
206 if (resolved_exe_file.Exists()) {
211 exe_file.GetPath(exe_path, sizeof(exe_path));
212 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
220 ModuleSpec module_spec (resolved_exe_file, exe_arch);
221 if (module_spec.GetArchitecture().IsValid())
223 error = ModuleList::GetSharedModule (module_spec,
225 module_search_paths_ptr,
229 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
231 exe_module_sp.reset();
232 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
233 exe_file.GetPath().c_str(),
234 exe_arch.GetArchitectureName());
239 // No valid architecture was specified, ask the platform for
240 // the architectures that we should be using (in the correct order)
241 // and see if we can find a match that way
242 StreamString arch_names;
243 ArchSpec platform_arch;
244 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
246 error = ModuleList::GetSharedModule (module_spec,
248 module_search_paths_ptr,
251 // Did we find an executable using one of the
254 if (exe_module_sp && exe_module_sp->GetObjectFile())
257 error.SetErrorToGenericError();
261 arch_names.PutCString (", ");
262 arch_names.PutCString (platform_arch.GetArchitectureName());
265 if (error.Fail() || !exe_module_sp)
267 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
268 exe_file.GetPath().c_str(),
269 GetPluginName().GetCString(),
270 arch_names.GetString().c_str());
276 error.SetErrorStringWithFormat ("'%s' does not exist",
277 exe_file.GetPath().c_str());
284 PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
286 ArchSpec arch = target.GetArchitecture();
287 const uint8_t *trap_opcode = NULL;
288 size_t trap_opcode_size = 0;
290 switch (arch.GetCore())
293 assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
296 case ArchSpec::eCore_x86_32_i386:
297 case ArchSpec::eCore_x86_64_x86_64:
299 static const uint8_t g_i386_opcode[] = { 0xCC };
300 trap_opcode = g_i386_opcode;
301 trap_opcode_size = sizeof(g_i386_opcode);
306 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
307 return trap_opcode_size;
313 PlatformFreeBSD::GetRemoteOSVersion ()
315 if (m_remote_platform_sp)
316 return m_remote_platform_sp->GetOSVersion (m_major_os_version,
318 m_update_os_version);
323 PlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
325 if (m_remote_platform_sp)
326 return m_remote_platform_sp->GetRemoteOSBuildString (s);
332 PlatformFreeBSD::GetRemoteOSKernelDescription (std::string &s)
334 if (m_remote_platform_sp)
335 return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
340 // Remote Platform subclasses need to override this function
342 PlatformFreeBSD::GetRemoteSystemArchitecture ()
344 if (m_remote_platform_sp)
345 return m_remote_platform_sp->GetRemoteSystemArchitecture ();
351 PlatformFreeBSD::GetHostname ()
354 return Platform::GetHostname();
356 if (m_remote_platform_sp)
357 return m_remote_platform_sp->GetHostname ();
362 PlatformFreeBSD::IsConnected () const
366 else if (m_remote_platform_sp)
367 return m_remote_platform_sp->IsConnected();
372 PlatformFreeBSD::ConnectRemote (Args& args)
377 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
381 if (!m_remote_platform_sp)
382 m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
384 if (m_remote_platform_sp)
388 if (m_remote_platform_sp)
390 error = m_remote_platform_sp->ConnectRemote (args);
394 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
399 error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
402 m_remote_platform_sp.reset();
409 PlatformFreeBSD::DisconnectRemote ()
415 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
419 if (m_remote_platform_sp)
420 error = m_remote_platform_sp->DisconnectRemote ();
422 error.SetErrorString ("the platform is not currently connected");
428 PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
430 bool success = false;
433 success = Platform::GetProcessInfo (pid, process_info);
435 else if (m_remote_platform_sp)
437 success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
445 PlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
446 ProcessInstanceInfoList &process_infos)
448 uint32_t match_count = 0;
451 // Let the base class figure out the host details
452 match_count = Platform::FindProcesses (match_info, process_infos);
456 // If we are remote, we can only return results if we are connected
457 if (m_remote_platform_sp)
458 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
464 PlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
469 error = Platform::LaunchProcess (launch_info);
473 if (m_remote_platform_sp)
474 error = m_remote_platform_sp->LaunchProcess (launch_info);
476 error.SetErrorString ("the platform is not currently connected");
482 PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
488 lldb::ProcessSP process_sp;
493 TargetSP new_target_sp;
494 ArchSpec emptyArchSpec;
496 error = debugger.GetTargetList().CreateTarget (debugger,
500 m_remote_platform_sp,
502 target = new_target_sp.get();
507 if (target && error.Success())
509 debugger.GetTargetList().SetSelectedTarget(target);
510 // The freebsd always currently uses the GDB remote debugger plug-in
511 // so even when debugging locally we are debugging remotely!
512 // Just like the darwin plugin.
513 process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
516 error = process_sp->Attach (attach_info);
521 if (m_remote_platform_sp)
522 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
524 error.SetErrorString ("the platform is not currently connected");
530 PlatformFreeBSD::GetUserName (uint32_t uid)
532 // Check the cache in Platform in case we have already looked this uid up
533 const char *user_name = Platform::GetUserName(uid);
537 if (IsRemote() && m_remote_platform_sp)
538 return m_remote_platform_sp->GetUserName(uid);
543 PlatformFreeBSD::GetGroupName (uint32_t gid)
545 const char *group_name = Platform::GetGroupName(gid);
549 if (IsRemote() && m_remote_platform_sp)
550 return m_remote_platform_sp->GetGroupName(gid);
555 // From PlatformMacOSX only
557 PlatformFreeBSD::GetFile (const FileSpec &platform_file,
558 const UUID *uuid_ptr,
559 FileSpec &local_file)
563 if (m_remote_platform_sp)
564 return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file);
567 // Default to the local case
568 local_file = platform_file;
573 PlatformFreeBSD::GetSharedModule (const ModuleSpec &module_spec,
575 const FileSpecList *module_search_paths_ptr,
576 ModuleSP *old_module_sp_ptr,
577 bool *did_create_ptr)
584 // If we have a remote platform always, let it try and locate
585 // the shared module first.
586 if (m_remote_platform_sp)
588 error = m_remote_platform_sp->GetSharedModule (module_spec,
590 module_search_paths_ptr,
598 // Fall back to the local platform and find the file locally
599 error = Platform::GetSharedModule (module_spec,
601 module_search_paths_ptr,
606 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
612 PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
614 // From macosx;s plugin code. For FreeBSD we may want to support more archs.
617 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
618 return arch.IsValid();
622 ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
623 ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
624 if (platform_arch.IsExactMatch(platform_arch64))
626 // This freebsd platform supports both 32 and 64 bit. Since we already
627 // returned the 64 bit arch for idx == 0, return the 32 bit arch
629 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
630 return arch.IsValid();
637 PlatformFreeBSD::GetStatus (Stream &strm)
646 strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
647 Platform::GetStatus(strm);