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) :
146 m_remote_platform_sp()
150 //------------------------------------------------------------------
153 /// The destructor is virtual since this class is designed to be
154 /// inherited from by the plug-in instance.
155 //------------------------------------------------------------------
156 PlatformFreeBSD::~PlatformFreeBSD()
160 //TODO:VK: inherit PlatformPOSIX
162 PlatformFreeBSD::RunShellCommand (const char *command,
163 const char *working_dir,
166 std::string *command_output,
167 uint32_t timeout_sec)
170 return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
173 if (m_remote_platform_sp)
174 return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
176 return Error("unable to run a remote command without a platform");
182 PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
183 const ArchSpec &exe_arch,
184 lldb::ModuleSP &exe_module_sp,
185 const FileSpecList *module_search_paths_ptr)
188 // Nothing special to do here, just use the actual file and architecture
190 char exe_path[PATH_MAX];
191 FileSpec resolved_exe_file (exe_file);
195 // If we have "ls" as the exe_file, resolve the executable location based on
196 // the current path variables
197 if (!resolved_exe_file.Exists())
199 exe_file.GetPath(exe_path, sizeof(exe_path));
200 resolved_exe_file.SetFile(exe_path, true);
203 if (!resolved_exe_file.Exists())
204 resolved_exe_file.ResolveExecutableLocation ();
206 if (resolved_exe_file.Exists())
210 exe_file.GetPath(exe_path, sizeof(exe_path));
211 error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
216 if (m_remote_platform_sp)
218 error = m_remote_platform_sp->ResolveExecutable (exe_file,
221 module_search_paths_ptr);
225 // We may connect to a process and use the provided executable (Don't use local $PATH).
227 // Resolve any executable within a bundle on MacOSX
228 Host::ResolveExecutableInBundle (resolved_exe_file);
230 if (resolved_exe_file.Exists()) {
235 exe_file.GetPath(exe_path, sizeof(exe_path));
236 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
243 ModuleSpec module_spec (resolved_exe_file, exe_arch);
244 if (module_spec.GetArchitecture().IsValid())
246 error = ModuleList::GetSharedModule (module_spec,
248 module_search_paths_ptr,
252 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
254 exe_module_sp.reset();
255 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
256 exe_file.GetPath().c_str(),
257 exe_arch.GetArchitectureName());
262 // No valid architecture was specified, ask the platform for
263 // the architectures that we should be using (in the correct order)
264 // and see if we can find a match that way
265 StreamString arch_names;
266 ArchSpec platform_arch;
267 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
269 error = ModuleList::GetSharedModule (module_spec,
271 module_search_paths_ptr,
274 // Did we find an executable using one of the
277 if (exe_module_sp && exe_module_sp->GetObjectFile())
280 error.SetErrorToGenericError();
284 arch_names.PutCString (", ");
285 arch_names.PutCString (platform_arch.GetArchitectureName());
288 if (error.Fail() || !exe_module_sp)
290 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
291 exe_file.GetPath().c_str(),
292 GetPluginName().GetCString(),
293 arch_names.GetString().c_str());
302 PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
304 ArchSpec arch = target.GetArchitecture();
305 const uint8_t *trap_opcode = NULL;
306 size_t trap_opcode_size = 0;
308 switch (arch.GetCore())
311 assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
314 case ArchSpec::eCore_x86_32_i386:
315 case ArchSpec::eCore_x86_64_x86_64:
316 case ArchSpec::eCore_x86_64_x86_64h:
318 static const uint8_t g_i386_opcode[] = { 0xCC };
319 trap_opcode = g_i386_opcode;
320 trap_opcode_size = sizeof(g_i386_opcode);
325 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
326 return trap_opcode_size;
332 PlatformFreeBSD::GetRemoteOSVersion ()
334 if (m_remote_platform_sp)
335 return m_remote_platform_sp->GetOSVersion (m_major_os_version,
337 m_update_os_version);
342 PlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
344 if (m_remote_platform_sp)
345 return m_remote_platform_sp->GetRemoteOSBuildString (s);
351 PlatformFreeBSD::GetRemoteOSKernelDescription (std::string &s)
353 if (m_remote_platform_sp)
354 return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
359 // Remote Platform subclasses need to override this function
361 PlatformFreeBSD::GetRemoteSystemArchitecture ()
363 if (m_remote_platform_sp)
364 return m_remote_platform_sp->GetRemoteSystemArchitecture ();
370 PlatformFreeBSD::GetHostname ()
373 return Platform::GetHostname();
375 if (m_remote_platform_sp)
376 return m_remote_platform_sp->GetHostname ();
381 PlatformFreeBSD::IsConnected () const
385 else if (m_remote_platform_sp)
386 return m_remote_platform_sp->IsConnected();
391 PlatformFreeBSD::ConnectRemote (Args& args)
396 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
400 if (!m_remote_platform_sp)
401 m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
403 if (m_remote_platform_sp)
407 if (m_remote_platform_sp)
409 error = m_remote_platform_sp->ConnectRemote (args);
413 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
418 error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
421 m_remote_platform_sp.reset();
428 PlatformFreeBSD::DisconnectRemote ()
434 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
438 if (m_remote_platform_sp)
439 error = m_remote_platform_sp->DisconnectRemote ();
441 error.SetErrorString ("the platform is not currently connected");
447 PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
449 bool success = false;
452 success = Platform::GetProcessInfo (pid, process_info);
454 else if (m_remote_platform_sp)
456 success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
464 PlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
465 ProcessInstanceInfoList &process_infos)
467 uint32_t match_count = 0;
470 // Let the base class figure out the host details
471 match_count = Platform::FindProcesses (match_info, process_infos);
475 // If we are remote, we can only return results if we are connected
476 if (m_remote_platform_sp)
477 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
483 PlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
488 error = Platform::LaunchProcess (launch_info);
492 if (m_remote_platform_sp)
493 error = m_remote_platform_sp->LaunchProcess (launch_info);
495 error.SetErrorString ("the platform is not currently connected");
501 PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
507 lldb::ProcessSP process_sp;
512 TargetSP new_target_sp;
513 ArchSpec emptyArchSpec;
515 error = debugger.GetTargetList().CreateTarget (debugger,
519 m_remote_platform_sp,
521 target = new_target_sp.get();
526 if (target && error.Success())
528 debugger.GetTargetList().SetSelectedTarget(target);
529 // The freebsd always currently uses the GDB remote debugger plug-in
530 // so even when debugging locally we are debugging remotely!
531 // Just like the darwin plugin.
532 process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
535 error = process_sp->Attach (attach_info);
540 if (m_remote_platform_sp)
541 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
543 error.SetErrorString ("the platform is not currently connected");
549 PlatformFreeBSD::GetUserName (uint32_t uid)
551 // Check the cache in Platform in case we have already looked this uid up
552 const char *user_name = Platform::GetUserName(uid);
556 if (IsRemote() && m_remote_platform_sp)
557 return m_remote_platform_sp->GetUserName(uid);
562 PlatformFreeBSD::GetGroupName (uint32_t gid)
564 const char *group_name = Platform::GetGroupName(gid);
568 if (IsRemote() && m_remote_platform_sp)
569 return m_remote_platform_sp->GetGroupName(gid);
574 // From PlatformMacOSX only
576 PlatformFreeBSD::GetFileWithUUID (const FileSpec &platform_file,
577 const UUID *uuid_ptr,
578 FileSpec &local_file)
582 if (m_remote_platform_sp)
583 return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
586 // Default to the local case
587 local_file = platform_file;
592 PlatformFreeBSD::GetSharedModule (const ModuleSpec &module_spec,
594 const FileSpecList *module_search_paths_ptr,
595 ModuleSP *old_module_sp_ptr,
596 bool *did_create_ptr)
603 // If we have a remote platform always, let it try and locate
604 // the shared module first.
605 if (m_remote_platform_sp)
607 error = m_remote_platform_sp->GetSharedModule (module_spec,
609 module_search_paths_ptr,
617 // Fall back to the local platform and find the file locally
618 error = Platform::GetSharedModule (module_spec,
620 module_search_paths_ptr,
625 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
631 PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
633 // From macosx;s plugin code. For FreeBSD we may want to support more archs.
636 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
637 return arch.IsValid();
641 ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
642 ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
643 if (platform_arch.IsExactMatch(platform_arch64))
645 // This freebsd platform supports both 32 and 64 bit. Since we already
646 // returned the 64 bit arch for idx == 0, return the 32 bit arch
648 arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
649 return arch.IsValid();
656 PlatformFreeBSD::GetStatus (Stream &strm)
658 #ifndef LLDB_DISABLE_POSIX
663 ::memset(&un, 0, sizeof(utsname));
664 if (uname(&un) == -1)
665 strm << "FreeBSD" << '\n';
667 strm << un.sysname << ' ' << un.release;
668 if (un.nodename[0] != '\0')
669 strm << " (" << un.nodename << ')';
672 // Dump a common information about the platform status.
673 strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
676 Platform::GetStatus(strm);
680 PlatformFreeBSD::CalculateTrapHandlerSymbolNames ()
682 m_trap_handlers.push_back (ConstString ("_sigtramp"));