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"
30 #include "lldb/Host/HostInfo.h"
33 using namespace lldb_private;
36 PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
38 // The only time we create an instance is when we are creating a remote
40 const bool is_host = false;
43 if (create == false && arch && arch->IsValid())
45 const llvm::Triple &triple = arch->GetTriple();
46 switch (triple.getVendor())
48 case llvm::Triple::PC:
52 #if defined(__FreeBSD__) || defined(__OpenBSD__)
53 // Only accept "unknown" for the vendor if the host is BSD and
54 // it "unknown" wasn't specified (it was just returned because it
56 case llvm::Triple::UnknownArch:
57 create = !arch->TripleVendorWasSpecified();
66 switch (triple.getOS())
68 case llvm::Triple::FreeBSD:
69 case llvm::Triple::KFreeBSD:
72 #if defined(__FreeBSD__) || defined(__OpenBSD__)
73 // Only accept "unknown" for the OS if the host is BSD and
74 // it "unknown" wasn't specified (it was just returned because it
76 case llvm::Triple::UnknownOS:
77 create = arch->TripleOSWasSpecified();
87 return PlatformSP(new PlatformFreeBSD (is_host));
92 lldb_private::ConstString
93 PlatformFreeBSD::GetPluginNameStatic (bool is_host)
97 static ConstString g_host_name(Platform::GetHostPlatformName ());
102 static ConstString g_remote_name("remote-freebsd");
103 return g_remote_name;
108 PlatformFreeBSD::GetDescriptionStatic (bool is_host)
111 return "Local FreeBSD user platform plug-in.";
113 return "Remote FreeBSD user platform plug-in.";
116 static uint32_t g_initialize_count = 0;
119 PlatformFreeBSD::Initialize ()
121 if (g_initialize_count++ == 0)
123 #if defined (__FreeBSD__)
124 // Force a host flag to true for the default platform object.
125 PlatformSP default_platform_sp (new PlatformFreeBSD(true));
126 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
127 Platform::SetHostPlatform (default_platform_sp);
129 PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
130 PlatformFreeBSD::GetDescriptionStatic(false),
131 PlatformFreeBSD::CreateInstance);
136 PlatformFreeBSD::Terminate ()
138 if (g_initialize_count > 0 && --g_initialize_count == 0)
139 PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
142 //------------------------------------------------------------------
143 /// Default Constructor
144 //------------------------------------------------------------------
145 PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
147 m_remote_platform_sp()
151 //------------------------------------------------------------------
154 /// The destructor is virtual since this class is designed to be
155 /// inherited from by the plug-in instance.
156 //------------------------------------------------------------------
157 PlatformFreeBSD::~PlatformFreeBSD()
161 //TODO:VK: inherit PlatformPOSIX
163 PlatformFreeBSD::RunShellCommand (const char *command,
164 const char *working_dir,
167 std::string *command_output,
168 uint32_t timeout_sec)
171 return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
174 if (m_remote_platform_sp)
175 return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
177 return Error("unable to run a remote command without a platform");
183 PlatformFreeBSD::ResolveExecutable (const ModuleSpec &module_spec,
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 ModuleSpec resolved_module_spec(module_spec);
195 // If we have "ls" as the module_spec's file, resolve the executable location based on
196 // the current path variables
197 if (!resolved_module_spec.GetFileSpec().Exists())
199 module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
200 resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
203 if (!resolved_module_spec.GetFileSpec().Exists())
204 resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
206 if (resolved_module_spec.GetFileSpec().Exists())
210 error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
215 if (m_remote_platform_sp)
217 error = m_remote_platform_sp->ResolveExecutable (module_spec,
219 module_search_paths_ptr);
223 // We may connect to a process and use the provided executable (Don't use local $PATH).
225 // Resolve any executable within a bundle on MacOSX
226 Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
228 if (resolved_module_spec.GetFileSpec().Exists())
234 error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str());
241 if (resolved_module_spec.GetArchitecture().IsValid())
243 error = ModuleList::GetSharedModule (resolved_module_spec,
245 module_search_paths_ptr,
249 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
251 exe_module_sp.reset();
252 error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
253 resolved_module_spec.GetFileSpec().GetPath().c_str(),
254 resolved_module_spec.GetArchitecture().GetArchitectureName());
259 // No valid architecture was specified, ask the platform for
260 // the architectures that we should be using (in the correct order)
261 // and see if we can find a match that way
262 StreamString arch_names;
263 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
265 error = ModuleList::GetSharedModule (resolved_module_spec,
267 module_search_paths_ptr,
270 // Did we find an executable using one of the
273 if (exe_module_sp && exe_module_sp->GetObjectFile())
276 error.SetErrorToGenericError();
280 arch_names.PutCString (", ");
281 arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
284 if (error.Fail() || !exe_module_sp)
286 if (resolved_module_spec.GetFileSpec().Readable())
288 error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
289 resolved_module_spec.GetFileSpec().GetPath().c_str(),
290 GetPluginName().GetCString(),
291 arch_names.GetString().c_str());
295 error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
305 PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
307 ArchSpec arch = target.GetArchitecture();
308 const uint8_t *trap_opcode = NULL;
309 size_t trap_opcode_size = 0;
311 switch (arch.GetMachine())
314 assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
316 case llvm::Triple::x86:
317 case llvm::Triple::x86_64:
319 static const uint8_t g_i386_opcode[] = { 0xCC };
320 trap_opcode = g_i386_opcode;
321 trap_opcode_size = sizeof(g_i386_opcode);
324 case llvm::Triple::ppc:
325 case llvm::Triple::ppc64:
327 static const uint8_t g_ppc_opcode[] = { 0x7f, 0xe0, 0x00, 0x08 };
328 trap_opcode = g_ppc_opcode;
329 trap_opcode_size = sizeof(g_ppc_opcode);
333 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
334 return trap_opcode_size;
340 PlatformFreeBSD::GetRemoteOSVersion ()
342 if (m_remote_platform_sp)
343 return m_remote_platform_sp->GetOSVersion (m_major_os_version,
345 m_update_os_version);
350 PlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
352 if (m_remote_platform_sp)
353 return m_remote_platform_sp->GetRemoteOSBuildString (s);
359 PlatformFreeBSD::GetRemoteOSKernelDescription (std::string &s)
361 if (m_remote_platform_sp)
362 return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
367 // Remote Platform subclasses need to override this function
369 PlatformFreeBSD::GetRemoteSystemArchitecture ()
371 if (m_remote_platform_sp)
372 return m_remote_platform_sp->GetRemoteSystemArchitecture ();
378 PlatformFreeBSD::GetHostname ()
381 return Platform::GetHostname();
383 if (m_remote_platform_sp)
384 return m_remote_platform_sp->GetHostname ();
389 PlatformFreeBSD::IsConnected () const
393 else if (m_remote_platform_sp)
394 return m_remote_platform_sp->IsConnected();
399 PlatformFreeBSD::ConnectRemote (Args& args)
404 error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
408 if (!m_remote_platform_sp)
409 m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
411 if (m_remote_platform_sp)
415 if (m_remote_platform_sp)
417 error = m_remote_platform_sp->ConnectRemote (args);
421 error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
426 error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
429 m_remote_platform_sp.reset();
436 PlatformFreeBSD::DisconnectRemote ()
442 error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
446 if (m_remote_platform_sp)
447 error = m_remote_platform_sp->DisconnectRemote ();
449 error.SetErrorString ("the platform is not currently connected");
455 PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
457 bool success = false;
460 success = Platform::GetProcessInfo (pid, process_info);
462 else if (m_remote_platform_sp)
464 success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
472 PlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
473 ProcessInstanceInfoList &process_infos)
475 uint32_t match_count = 0;
478 // Let the base class figure out the host details
479 match_count = Platform::FindProcesses (match_info, process_infos);
483 // If we are remote, we can only return results if we are connected
484 if (m_remote_platform_sp)
485 match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
491 PlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
496 error = Platform::LaunchProcess (launch_info);
500 if (m_remote_platform_sp)
501 error = m_remote_platform_sp->LaunchProcess (launch_info);
503 error.SetErrorString ("the platform is not currently connected");
509 PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
514 lldb::ProcessSP process_sp;
519 TargetSP new_target_sp;
520 ArchSpec emptyArchSpec;
522 error = debugger.GetTargetList().CreateTarget (debugger,
526 m_remote_platform_sp,
528 target = new_target_sp.get();
533 if (target && error.Success())
535 debugger.GetTargetList().SetSelectedTarget(target);
536 // The freebsd always currently uses the GDB remote debugger plug-in
537 // so even when debugging locally we are debugging remotely!
538 // Just like the darwin plugin.
539 process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
542 error = process_sp->Attach (attach_info);
547 if (m_remote_platform_sp)
548 process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
550 error.SetErrorString ("the platform is not currently connected");
556 PlatformFreeBSD::GetUserName (uint32_t uid)
558 // Check the cache in Platform in case we have already looked this uid up
559 const char *user_name = Platform::GetUserName(uid);
563 if (IsRemote() && m_remote_platform_sp)
564 return m_remote_platform_sp->GetUserName(uid);
569 PlatformFreeBSD::GetGroupName (uint32_t gid)
571 const char *group_name = Platform::GetGroupName(gid);
575 if (IsRemote() && m_remote_platform_sp)
576 return m_remote_platform_sp->GetGroupName(gid);
581 // From PlatformMacOSX only
583 PlatformFreeBSD::GetFileWithUUID (const FileSpec &platform_file,
584 const UUID *uuid_ptr,
585 FileSpec &local_file)
589 if (m_remote_platform_sp)
590 return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
593 // Default to the local case
594 local_file = platform_file;
599 PlatformFreeBSD::GetSharedModule (const ModuleSpec &module_spec,
601 const FileSpecList *module_search_paths_ptr,
602 ModuleSP *old_module_sp_ptr,
603 bool *did_create_ptr)
610 // If we have a remote platform always, let it try and locate
611 // the shared module first.
612 if (m_remote_platform_sp)
614 error = m_remote_platform_sp->GetSharedModule (module_spec,
616 module_search_paths_ptr,
624 // Fall back to the local platform and find the file locally
625 error = Platform::GetSharedModule (module_spec,
627 module_search_paths_ptr,
632 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
638 PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
640 // From macosx;s plugin code. For FreeBSD we may want to support more archs.
643 arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
644 return arch.IsValid();
648 ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
649 ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64));
650 if (platform_arch.IsExactMatch(platform_arch64))
652 // This freebsd platform supports both 32 and 64 bit. Since we already
653 // returned the 64 bit arch for idx == 0, return the 32 bit arch
655 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
656 return arch.IsValid();
663 PlatformFreeBSD::GetStatus (Stream &strm)
665 #ifndef LLDB_DISABLE_POSIX
670 ::memset(&un, 0, sizeof(utsname));
671 if (uname(&un) == -1)
672 strm << "FreeBSD" << '\n';
674 strm << un.sysname << ' ' << un.release;
675 if (un.nodename[0] != '\0')
676 strm << " (" << un.nodename << ')';
679 // Dump a common information about the platform status.
680 strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
683 Platform::GetStatus(strm);
687 PlatformFreeBSD::CalculateTrapHandlerSymbolNames ()
689 m_trap_handlers.push_back (ConstString ("_sigtramp"));