1 //===-- PlatformNetBSD.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 "PlatformNetBSD.h"
11 #include "lldb/Host/Config.h"
15 #ifndef LLDB_DISABLE_POSIX
16 #include <sys/utsname.h>
20 // Other libraries and framework includes
22 #include "lldb/Breakpoint/BreakpointLocation.h"
23 #include "lldb/Breakpoint/BreakpointSite.h"
24 #include "lldb/Core/Debugger.h"
25 #include "lldb/Core/Error.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"
31 #include "lldb/Target/Process.h"
34 using namespace lldb_private;
35 using namespace lldb_private::platform_netbsd;
37 PlatformSP PlatformNetBSD::CreateInstance(bool force, const 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()) {
44 const llvm::Triple &triple = arch->GetTriple();
45 switch (triple.getOS()) {
46 case llvm::Triple::NetBSD:
55 return PlatformSP(new PlatformNetBSD(is_host));
59 ConstString PlatformNetBSD::GetPluginNameStatic(bool is_host) {
61 static ConstString g_host_name(Platform::GetHostPlatformName());
64 static ConstString g_remote_name("remote-netbsd");
69 const char *PlatformNetBSD::GetDescriptionStatic(bool is_host) {
71 return "Local NetBSD user platform plug-in.";
73 return "Remote NetBSD user platform plug-in.";
76 static uint32_t g_initialize_count = 0;
78 void PlatformNetBSD::Initialize() {
79 Platform::Initialize();
81 if (g_initialize_count++ == 0) {
82 #if defined(__NetBSD__)
83 // Force a host flag to true for the default platform object.
84 PlatformSP default_platform_sp(new PlatformNetBSD(true));
85 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
86 Platform::SetHostPlatform(default_platform_sp);
88 PluginManager::RegisterPlugin(PlatformNetBSD::GetPluginNameStatic(false),
89 PlatformNetBSD::GetDescriptionStatic(false),
90 PlatformNetBSD::CreateInstance);
94 void PlatformNetBSD::Terminate() {
95 if (g_initialize_count > 0 && --g_initialize_count == 0)
96 PluginManager::UnregisterPlugin(PlatformNetBSD::CreateInstance);
98 Platform::Terminate();
101 bool PlatformNetBSD::GetModuleSpec(const FileSpec &module_file_spec,
102 const ArchSpec &arch,
103 ModuleSpec &module_spec) {
104 if (m_remote_platform_sp)
105 return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch,
108 return Platform::GetModuleSpec(module_file_spec, arch, module_spec);
111 Error PlatformNetBSD::RunShellCommand(const char *command,
112 const FileSpec &working_dir,
113 int *status_ptr, int *signo_ptr,
114 std::string *command_output,
115 uint32_t timeout_sec) {
117 return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
118 command_output, timeout_sec);
120 if (m_remote_platform_sp)
121 return m_remote_platform_sp->RunShellCommand(command, working_dir,
122 status_ptr, signo_ptr,
123 command_output, timeout_sec);
125 return Error("unable to run a remote command without a platform");
129 Error PlatformNetBSD::ResolveExecutable(
130 const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
131 const FileSpecList *module_search_paths_ptr) {
133 // Nothing special to do here, just use the actual file and architecture
135 char exe_path[PATH_MAX];
136 ModuleSpec resolved_module_spec(module_spec);
139 // If we have "ls" as the module_spec's file, resolve the executable
141 // the current path variables
142 if (!resolved_module_spec.GetFileSpec().Exists()) {
143 module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
144 resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
147 if (!resolved_module_spec.GetFileSpec().Exists())
148 resolved_module_spec.GetFileSpec().ResolveExecutableLocation();
150 if (resolved_module_spec.GetFileSpec().Exists())
153 error.SetErrorStringWithFormat(
154 "unable to find executable for '%s'",
155 resolved_module_spec.GetFileSpec().GetPath().c_str());
158 if (m_remote_platform_sp) {
160 GetCachedExecutable(resolved_module_spec, exe_module_sp,
161 module_search_paths_ptr, *m_remote_platform_sp);
163 // We may connect to a process and use the provided executable (Don't use
166 // Resolve any executable within a bundle on MacOSX
167 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
169 if (resolved_module_spec.GetFileSpec().Exists()) {
172 error.SetErrorStringWithFormat(
173 "the platform is not currently connected, and '%s' doesn't exist "
174 "in the system root.",
175 resolved_module_spec.GetFileSpec().GetPath().c_str());
180 if (error.Success()) {
181 if (resolved_module_spec.GetArchitecture().IsValid()) {
182 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
183 module_search_paths_ptr, NULL, NULL);
185 if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) {
186 exe_module_sp.reset();
187 error.SetErrorStringWithFormat(
188 "'%s' doesn't contain the architecture %s",
189 resolved_module_spec.GetFileSpec().GetPath().c_str(),
190 resolved_module_spec.GetArchitecture().GetArchitectureName());
193 // No valid architecture was specified, ask the platform for
194 // the architectures that we should be using (in the correct order)
195 // and see if we can find a match that way
196 StreamString arch_names;
197 for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
198 idx, resolved_module_spec.GetArchitecture());
201 ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
202 module_search_paths_ptr, NULL, NULL);
203 // Did we find an executable using one of the
204 if (error.Success()) {
205 if (exe_module_sp && exe_module_sp->GetObjectFile())
208 error.SetErrorToGenericError();
212 arch_names.PutCString(", ");
213 arch_names.PutCString(
214 resolved_module_spec.GetArchitecture().GetArchitectureName());
217 if (error.Fail() || !exe_module_sp) {
218 if (resolved_module_spec.GetFileSpec().Readable()) {
219 error.SetErrorStringWithFormat(
220 "'%s' doesn't contain any '%s' platform architectures: %s",
221 resolved_module_spec.GetFileSpec().GetPath().c_str(),
222 GetPluginName().GetCString(), arch_names.GetData());
224 error.SetErrorStringWithFormat(
225 "'%s' is not readable",
226 resolved_module_spec.GetFileSpec().GetPath().c_str());
235 // From PlatformMacOSX only
236 Error PlatformNetBSD::GetFileWithUUID(const FileSpec &platform_file,
237 const UUID *uuid_ptr,
238 FileSpec &local_file) {
240 if (m_remote_platform_sp)
241 return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr,
245 // Default to the local case
246 local_file = platform_file;
250 //------------------------------------------------------------------
251 /// Default Constructor
252 //------------------------------------------------------------------
253 PlatformNetBSD::PlatformNetBSD(bool is_host)
254 : Platform(is_host), m_remote_platform_sp() {}
256 bool PlatformNetBSD::GetRemoteOSVersion() {
257 if (m_remote_platform_sp)
258 return m_remote_platform_sp->GetOSVersion(
259 m_major_os_version, m_minor_os_version, m_update_os_version);
263 bool PlatformNetBSD::GetRemoteOSBuildString(std::string &s) {
264 if (m_remote_platform_sp)
265 return m_remote_platform_sp->GetRemoteOSBuildString(s);
270 bool PlatformNetBSD::GetRemoteOSKernelDescription(std::string &s) {
271 if (m_remote_platform_sp)
272 return m_remote_platform_sp->GetRemoteOSKernelDescription(s);
277 // Remote Platform subclasses need to override this function
278 ArchSpec PlatformNetBSD::GetRemoteSystemArchitecture() {
279 if (m_remote_platform_sp)
280 return m_remote_platform_sp->GetRemoteSystemArchitecture();
284 const char *PlatformNetBSD::GetHostname() {
286 return Platform::GetHostname();
288 if (m_remote_platform_sp)
289 return m_remote_platform_sp->GetHostname();
293 bool PlatformNetBSD::IsConnected() const {
296 else if (m_remote_platform_sp)
297 return m_remote_platform_sp->IsConnected();
301 Error PlatformNetBSD::ConnectRemote(Args &args) {
304 error.SetErrorStringWithFormat(
305 "can't connect to the host platform '%s', always connected",
306 GetPluginName().GetCString());
308 if (!m_remote_platform_sp)
309 m_remote_platform_sp =
310 Platform::Create(ConstString("remote-gdb-server"), error);
312 if (m_remote_platform_sp) {
313 if (error.Success()) {
314 if (m_remote_platform_sp) {
315 error = m_remote_platform_sp->ConnectRemote(args);
317 error.SetErrorString(
318 "\"platform connect\" takes a single argument: <connect-url>");
322 error.SetErrorString("failed to create a 'remote-gdb-server' platform");
325 m_remote_platform_sp.reset();
331 Error PlatformNetBSD::DisconnectRemote() {
335 error.SetErrorStringWithFormat(
336 "can't disconnect from the host platform '%s', always connected",
337 GetPluginName().GetCString());
339 if (m_remote_platform_sp)
340 error = m_remote_platform_sp->DisconnectRemote();
342 error.SetErrorString("the platform is not currently connected");
347 bool PlatformNetBSD::GetProcessInfo(lldb::pid_t pid,
348 ProcessInstanceInfo &process_info) {
349 bool success = false;
351 success = Platform::GetProcessInfo(pid, process_info);
352 } else if (m_remote_platform_sp) {
353 success = m_remote_platform_sp->GetProcessInfo(pid, process_info);
359 PlatformNetBSD::FindProcesses(const ProcessInstanceInfoMatch &match_info,
360 ProcessInstanceInfoList &process_infos) {
361 uint32_t match_count = 0;
363 // Let the base class figure out the host details
364 match_count = Platform::FindProcesses(match_info, process_infos);
366 // If we are remote, we can only return results if we are connected
367 if (m_remote_platform_sp)
369 m_remote_platform_sp->FindProcesses(match_info, process_infos);
374 const char *PlatformNetBSD::GetUserName(uint32_t uid) {
375 // Check the cache in Platform in case we have already looked this uid up
376 const char *user_name = Platform::GetUserName(uid);
380 if (IsRemote() && m_remote_platform_sp)
381 return m_remote_platform_sp->GetUserName(uid);
385 const char *PlatformNetBSD::GetGroupName(uint32_t gid) {
386 const char *group_name = Platform::GetGroupName(gid);
390 if (IsRemote() && m_remote_platform_sp)
391 return m_remote_platform_sp->GetGroupName(gid);
395 Error PlatformNetBSD::GetSharedModule(
396 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
397 const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
398 bool *did_create_ptr) {
403 // If we have a remote platform always, let it try and locate
404 // the shared module first.
405 if (m_remote_platform_sp) {
406 error = m_remote_platform_sp->GetSharedModule(
407 module_spec, process, module_sp, module_search_paths_ptr,
408 old_module_sp_ptr, did_create_ptr);
413 // Fall back to the local platform and find the file locally
414 error = Platform::GetSharedModule(module_spec, process, module_sp,
415 module_search_paths_ptr,
416 old_module_sp_ptr, did_create_ptr);
419 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
423 bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
426 ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
427 if (hostArch.GetTriple().isOSNetBSD()) {
430 return arch.IsValid();
431 } else if (idx == 1) {
432 // If the default host architecture is 64-bit, look for a 32-bit variant
433 if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
434 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
435 return arch.IsValid();
440 if (m_remote_platform_sp)
441 return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
444 // Set the OS to NetBSD
445 triple.setOS(llvm::Triple::NetBSD);
446 // Set the architecture
449 triple.setArchName("x86_64");
452 triple.setArchName("i386");
457 // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
459 // calling triple.SetVendorName("unknown") so that it is a "unspecified
461 // This means when someone calls triple.GetVendorName() it will return an
463 // which indicates that the vendor can be set when two architectures are
466 // Now set the triple into "arch" and return true
467 arch.SetTriple(triple);
473 void PlatformNetBSD::GetStatus(Stream &strm) {
474 #ifndef LLDB_DISABLE_POSIX
479 ::memset(&un, 0, sizeof(utsname));
480 if (::uname(&un) == -1) {
481 strm << "NetBSD" << '\n';
483 strm << un.sysname << ' ' << un.release;
484 if (un.nodename[0] != '\0')
485 strm << " (" << un.nodename << ')';
488 // Dump a common information about the platform status.
489 strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version
494 Platform::GetStatus(strm);
497 void PlatformNetBSD::CalculateTrapHandlerSymbolNames() {
498 m_trap_handlers.push_back(ConstString("_sigtramp"));
501 Error PlatformNetBSD::LaunchProcess(ProcessLaunchInfo &launch_info) {
504 error = Platform::LaunchProcess(launch_info);
506 if (m_remote_platform_sp)
507 error = m_remote_platform_sp->LaunchProcess(launch_info);
509 error.SetErrorString("the platform is not currently connected");
514 lldb::ProcessSP PlatformNetBSD::Attach(ProcessAttachInfo &attach_info,
515 Debugger &debugger, Target *target,
517 lldb::ProcessSP process_sp;
519 if (target == NULL) {
520 TargetSP new_target_sp;
521 ArchSpec emptyArchSpec;
523 error = debugger.GetTargetList().CreateTarget(debugger, "", emptyArchSpec,
524 false, m_remote_platform_sp,
526 target = new_target_sp.get();
530 if (target && error.Success()) {
531 debugger.GetTargetList().SetSelectedTarget(target);
532 // The netbsd always currently uses the GDB remote debugger plug-in
533 // so even when debugging locally we are debugging remotely!
534 // Just like the darwin plugin.
535 process_sp = target->CreateProcess(
536 attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
539 error = process_sp->Attach(attach_info);
542 if (m_remote_platform_sp)
544 m_remote_platform_sp->Attach(attach_info, debugger, target, error);
546 error.SetErrorString("the platform is not currently connected");