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"
13 #include "lldb/Host/Config.h"
17 #ifndef LLDB_DISABLE_POSIX
18 #include <sys/utsname.h>
22 // Other libraries and framework includes
24 #include "lldb/Core/Error.h"
25 #include "lldb/Core/Debugger.h"
26 #include "lldb/Core/Module.h"
27 #include "lldb/Core/ModuleSpec.h"
28 #include "lldb/Core/PluginManager.h"
29 #include "lldb/Host/Host.h"
32 using namespace lldb_private;
35 PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
37 // The only time we create an instance is when we are creating a remote
39 const bool is_host = false;
42 if (create == false && arch && arch->IsValid())
44 const llvm::Triple &triple = arch->GetTriple();
45 switch (triple.getVendor())
47 case llvm::Triple::PC:
51 #if defined(__FreeBSD__) || defined(__OpenBSD__)
52 // Only accept "unknown" for the vendor if the host is BSD and
53 // it "unknown" wasn't specified (it was just returned becasue it
55 case llvm::Triple::UnknownArch:
56 create = !arch->TripleVendorWasSpecified();
65 switch (triple.getOS())
67 case llvm::Triple::FreeBSD:
68 case llvm::Triple::KFreeBSD:
71 #if defined(__FreeBSD__) || defined(__OpenBSD__)
72 // Only accept "unknown" for the OS if the host is BSD and
73 // it "unknown" wasn't specified (it was just returned becasue it
75 case llvm::Triple::UnknownOS:
76 create = arch->TripleOSWasSpecified();
86 return new PlatformFreeBSD (is_host);
91 lldb_private::ConstString
92 PlatformFreeBSD::GetPluginNameStatic (bool is_host)
96 static ConstString g_host_name(Platform::GetHostPlatformName ());
101 static ConstString g_remote_name("remote-freebsd");
102 return g_remote_name;
107 PlatformFreeBSD::GetDescriptionStatic (bool is_host)
110 return "Local FreeBSD user platform plug-in.";
112 return "Remote FreeBSD user platform plug-in.";
115 static uint32_t g_initialize_count = 0;
118 PlatformFreeBSD::Initialize ()
120 if (g_initialize_count++ == 0)
122 #if defined (__FreeBSD__)
123 // Force a host flag to true for the default platform object.
124 PlatformSP default_platform_sp (new PlatformFreeBSD(true));
125 default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
126 Platform::SetDefaultPlatform (default_platform_sp);
128 PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
129 PlatformFreeBSD::GetDescriptionStatic(false),
130 PlatformFreeBSD::CreateInstance);
135 PlatformFreeBSD::Terminate ()
137 if (g_initialize_count > 0 && --g_initialize_count == 0)
138 PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
141 //------------------------------------------------------------------
142 /// Default Constructor
143 //------------------------------------------------------------------
144 PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
149 //------------------------------------------------------------------
152 /// The destructor is virtual since this class is designed to be
153 /// inherited from by the plug-in instance.
154 //------------------------------------------------------------------
155 PlatformFreeBSD::~PlatformFreeBSD()
159 //TODO:VK: inherit PlatformPOSIX
161 PlatformFreeBSD::RunShellCommand (const char *command,
162 const char *working_dir,
165 std::string *command_output,
166 uint32_t timeout_sec)
169 return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
172 if (m_remote_platform_sp)
173 return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
175 return Error("unable to run a remote command without a platform");
181 PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
182 const ArchSpec &exe_arch,
183 lldb::ModuleSP &exe_module_sp,
184 const FileSpecList *module_search_paths_ptr)
187 // Nothing special to do here, just use the actual file and architecture
189 char exe_path[PATH_MAX];
190 FileSpec resolved_exe_file (exe_file);
194 // If we have "ls" as the exe_file, resolve the executable location based on
195 // the current path variables
196 if (!resolved_exe_file.Exists())
198 exe_file.GetPath(exe_path, sizeof(exe_path));
199 resolved_exe_file.SetFile(exe_path, true);
202 if (!resolved_exe_file.Exists())
203 resolved_exe_file.ResolveExecutableLocation ();
205 if (resolved_exe_file.Exists())
209 exe_file.GetPath(exe_path, sizeof(exe_path));
210 error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
215 if (m_remote_platform_sp)
217 error = m_remote_platform_sp->ResolveExecutable (exe_file,
220 module_search_paths_ptr);
224 // We may connect to a process and use the provided executable (Don't use local $PATH).
226 // Resolve any executable within a bundle on MacOSX
227 Host::ResolveExecutableInBundle (resolved_exe_file);
229 if (resolved_exe_file.Exists()) {
234 exe_file.GetPath(exe_path, sizeof(exe_path));
235 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
242 ModuleSpec module_spec (resolved_exe_file, exe_arch);
243 if (module_spec.GetArchitecture().IsValid())
245 error = ModuleList::GetSharedModule (module_spec,
247 module_search_paths_ptr,
251 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
253 exe_module_sp.reset();
254 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
255 exe_file.GetPath().c_str(),
256 exe_arch.GetArchitectureName());
261 // No valid architecture was specified, ask the platform for
262 // the architectures that we should be using (in the correct order)
263 // and see if we can find a match that way
264 StreamString arch_names;
265 ArchSpec platform_arch;
266 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
268 error = ModuleList::GetSharedModule (module_spec,
270 module_search_paths_ptr,
273 // Did we find an executable using one of the
276 if (exe_module_sp && exe_module_sp->GetObjectFile())
279 error.SetErrorToGenericError();
283 arch_names.PutCString (", ");
284 arch_names.PutCString (platform_arch.GetArchitectureName());
287 if (error.Fail() || !exe_module_sp)
289 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
290 exe_file.GetPath().c_str(),
291 GetPluginName().GetCString(),
292 arch_names.GetString().c_str());
301 PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
303 ArchSpec arch = target.GetArchitecture();
304 const uint8_t *trap_opcode = NULL;
305 size_t trap_opcode_size = 0;
307 switch (arch.GetCore())
310 assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
313 case ArchSpec::eCore_x86_32_i386:
314 case ArchSpec::eCore_x86_64_x86_64:
316 static const uint8_t g_i386_opcode[] = { 0xCC };
317 trap_opcode = g_i386_opcode;
318 trap_opcode_size = sizeof(g_i386_opcode);
323 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
324 return trap_opcode_size;
330 PlatformFreeBSD::GetRemoteOSVersion ()
332 if (m_remote_platform_sp)
333 return m_remote_platform_sp->GetOSVersion (m_major_os_version,
335 m_update_os_version);
340 PlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
342 if (m_remote_platform_sp)
343 return m_remote_platform_sp->GetRemoteOSBuildString (s);
349 PlatformFreeBSD::GetRemoteOSKernelDescription (std::string &s)
351 if (m_remote_platform_sp)
352 return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
357 // Remote Platform subclasses need to override this function
359 PlatformFreeBSD::GetRemoteSystemArchitecture ()
361 if (m_remote_platform_sp)
362 return m_remote_platform_sp->GetRemoteSystemArchitecture ();
368 PlatformFreeBSD::GetHostname ()
371 return Platform::GetHostname();
373 if (m_remote_platform_sp)
374 return m_remote_platform_sp->GetHostname ();
379 PlatformFreeBSD::IsConnected () const
383 else if (m_remote_platform_sp)
384 return m_remote_platform_sp->IsConnected();
389 PlatformFreeBSD::ConnectRemote (Args& args)
394 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
398 if (!m_remote_platform_sp)
399 m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
401 if (m_remote_platform_sp)
405 if (m_remote_platform_sp)
407 error = m_remote_platform_sp->ConnectRemote (args);
411 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
416 error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
419 m_remote_platform_sp.reset();
426 PlatformFreeBSD::DisconnectRemote ()
432 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
436 if (m_remote_platform_sp)
437 error = m_remote_platform_sp->DisconnectRemote ();
439 error.SetErrorString ("the platform is not currently connected");
445 PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
447 bool success = false;
450 success = Platform::GetProcessInfo (pid, process_info);
452 else if (m_remote_platform_sp)
454 success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
462 PlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
463 ProcessInstanceInfoList &process_infos)
465 uint32_t match_count = 0;
468 // Let the base class figure out the host details
469 match_count = Platform::FindProcesses (match_info, process_infos);
473 // If we are remote, we can only return results if we are connected
474 if (m_remote_platform_sp)
475 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
481 PlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
486 error = Platform::LaunchProcess (launch_info);
490 if (m_remote_platform_sp)
491 error = m_remote_platform_sp->LaunchProcess (launch_info);
493 error.SetErrorString ("the platform is not currently connected");
499 PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
505 lldb::ProcessSP process_sp;
510 TargetSP new_target_sp;
511 ArchSpec emptyArchSpec;
513 error = debugger.GetTargetList().CreateTarget (debugger,
517 m_remote_platform_sp,
519 target = new_target_sp.get();
524 if (target && error.Success())
526 debugger.GetTargetList().SetSelectedTarget(target);
527 // The freebsd always currently uses the GDB remote debugger plug-in
528 // so even when debugging locally we are debugging remotely!
529 // Just like the darwin plugin.
530 process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
533 error = process_sp->Attach (attach_info);
538 if (m_remote_platform_sp)
539 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
541 error.SetErrorString ("the platform is not currently connected");
547 PlatformFreeBSD::GetUserName (uint32_t uid)
549 // Check the cache in Platform in case we have already looked this uid up
550 const char *user_name = Platform::GetUserName(uid);
554 if (IsRemote() && m_remote_platform_sp)
555 return m_remote_platform_sp->GetUserName(uid);
560 PlatformFreeBSD::GetGroupName (uint32_t gid)
562 const char *group_name = Platform::GetGroupName(gid);
566 if (IsRemote() && m_remote_platform_sp)
567 return m_remote_platform_sp->GetGroupName(gid);
572 // From PlatformMacOSX only
574 PlatformFreeBSD::GetFile (const FileSpec &platform_file,
575 const UUID *uuid_ptr,
576 FileSpec &local_file)
580 if (m_remote_platform_sp)
581 return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file);
584 // Default to the local case
585 local_file = platform_file;
590 PlatformFreeBSD::GetSharedModule (const ModuleSpec &module_spec,
592 const FileSpecList *module_search_paths_ptr,
593 ModuleSP *old_module_sp_ptr,
594 bool *did_create_ptr)
601 // If we have a remote platform always, let it try and locate
602 // the shared module first.
603 if (m_remote_platform_sp)
605 error = m_remote_platform_sp->GetSharedModule (module_spec,
607 module_search_paths_ptr,
615 // Fall back to the local platform and find the file locally
616 error = Platform::GetSharedModule (module_spec,
618 module_search_paths_ptr,
623 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
629 PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
631 // From macosx;s plugin code. For FreeBSD we may want to support more archs.
634 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
635 return arch.IsValid();
639 ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
640 ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
641 if (platform_arch.IsExactMatch(platform_arch64))
643 // This freebsd platform supports both 32 and 64 bit. Since we already
644 // returned the 64 bit arch for idx == 0, return the 32 bit arch
646 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
647 return arch.IsValid();
654 PlatformFreeBSD::GetStatus (Stream &strm)
656 #ifndef LLDB_DISABLE_POSIX
661 ::memset(&un, 0, sizeof(utsname));
662 if (uname(&un) == -1)
663 strm << "FreeBSD" << '\n';
665 strm << un.sysname << ' ' << un.release;
666 if (un.nodename[0] != '\0')
667 strm << " (" << un.nodename << ')';
670 // Dump a common information about the platform status.
671 strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
674 Platform::GetStatus(strm);