diff options
Diffstat (limited to 'source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp')
-rw-r--r-- | source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp | 441 |
1 files changed, 78 insertions, 363 deletions
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 9ea97a5f70ba..2a150b5d452b 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -22,22 +22,34 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSite.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Host/Host.h" +#include "lldb/Core/State.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/Error.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" + +// Define these constants from FreeBSD mman.h for use when targeting +// remote FreeBSD systems even when host has different values. +#define MAP_PRIVATE 0x0002 +#define MAP_ANON 0x1000 using namespace lldb; using namespace lldb_private; using namespace lldb_private::platform_freebsd; +static uint32_t g_initialize_count = 0; + +//------------------------------------------------------------------ + PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) { - // The only time we create an instance is when we are creating a remote - // freebsd platform - const bool is_host = false; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, + arch ? arch->GetArchitectureName() : "<null>", + arch ? arch->GetTriple().getTriple() : "<null>"); bool create = force; if (create == false && arch && arch->IsValid()) { @@ -47,7 +59,7 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) { create = true; break; -#if defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__) // Only accept "unknown" for the OS if the host is BSD and // it "unknown" wasn't specified (it was just returned because it // was NOT specified) @@ -59,8 +71,10 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) { break; } } - if (create) - return PlatformSP(new PlatformFreeBSD(is_host)); + LLDB_LOG(log, "create = {0}", create); + if (create) { + return PlatformSP(new PlatformFreeBSD(false)); + } return PlatformSP(); } @@ -74,369 +88,51 @@ ConstString PlatformFreeBSD::GetPluginNameStatic(bool is_host) { } } -const char *PlatformFreeBSD::GetDescriptionStatic(bool is_host) { +const char *PlatformFreeBSD::GetPluginDescriptionStatic(bool is_host) { if (is_host) return "Local FreeBSD user platform plug-in."; else return "Remote FreeBSD user platform plug-in."; } -static uint32_t g_initialize_count = 0; +ConstString PlatformFreeBSD::GetPluginName() { + return GetPluginNameStatic(IsHost()); +} void PlatformFreeBSD::Initialize() { Platform::Initialize(); if (g_initialize_count++ == 0) { #if defined(__FreeBSD__) - // Force a host flag to true for the default platform object. PlatformSP default_platform_sp(new PlatformFreeBSD(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); Platform::SetHostPlatform(default_platform_sp); #endif - PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false), - PlatformFreeBSD::GetDescriptionStatic(false), - PlatformFreeBSD::CreateInstance); + PluginManager::RegisterPlugin( + PlatformFreeBSD::GetPluginNameStatic(false), + PlatformFreeBSD::GetPluginDescriptionStatic(false), + PlatformFreeBSD::CreateInstance, nullptr); } } void PlatformFreeBSD::Terminate() { - if (g_initialize_count > 0 && --g_initialize_count == 0) - PluginManager::UnregisterPlugin(PlatformFreeBSD::CreateInstance); - - Platform::Terminate(); -} - -bool PlatformFreeBSD::GetModuleSpec(const FileSpec &module_file_spec, - const ArchSpec &arch, - ModuleSpec &module_spec) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch, - module_spec); - - return Platform::GetModuleSpec(module_file_spec, arch, module_spec); -} - -Error PlatformFreeBSD::RunShellCommand(const char *command, - const FileSpec &working_dir, - int *status_ptr, int *signo_ptr, - std::string *command_output, - uint32_t timeout_sec) { - if (IsHost()) - return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, - command_output, timeout_sec); - else { - if (m_remote_platform_sp) - return m_remote_platform_sp->RunShellCommand(command, working_dir, - status_ptr, signo_ptr, - command_output, timeout_sec); - else - return Error("unable to run a remote command without a platform"); - } -} - -Error PlatformFreeBSD::ResolveExecutable( - const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp, - const FileSpecList *module_search_paths_ptr) { - Error error; - // Nothing special to do here, just use the actual file and architecture - - char exe_path[PATH_MAX]; - ModuleSpec resolved_module_spec(module_spec); - - if (IsHost()) { - // If we have "ls" as the module_spec's file, resolve the executable - // location based on - // the current path variables - if (!resolved_module_spec.GetFileSpec().Exists()) { - module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); - resolved_module_spec.GetFileSpec().SetFile(exe_path, true); - } - - if (!resolved_module_spec.GetFileSpec().Exists()) - resolved_module_spec.GetFileSpec().ResolveExecutableLocation(); - - if (resolved_module_spec.GetFileSpec().Exists()) - error.Clear(); - else { - error.SetErrorStringWithFormat( - "unable to find executable for '%s'", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } else { - if (m_remote_platform_sp) { - error = - GetCachedExecutable(resolved_module_spec, exe_module_sp, - module_search_paths_ptr, *m_remote_platform_sp); - } else { - // We may connect to a process and use the provided executable (Don't use - // local $PATH). - - // Resolve any executable within a bundle on MacOSX - Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); - - if (resolved_module_spec.GetFileSpec().Exists()) { - error.Clear(); - } else { - error.SetErrorStringWithFormat( - "the platform is not currently connected, and '%s' doesn't exist " - "in the system root.", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformFreeBSD::CreateInstance); } } - if (error.Success()) { - if (resolved_module_spec.GetArchitecture().IsValid()) { - error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - module_search_paths_ptr, NULL, NULL); - - if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) { - exe_module_sp.reset(); - error.SetErrorStringWithFormat( - "'%s' doesn't contain the architecture %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - resolved_module_spec.GetArchitecture().GetArchitectureName()); - } - } else { - // No valid architecture was specified, ask the platform for - // the architectures that we should be using (in the correct order) - // and see if we can find a match that way - StreamString arch_names; - for (uint32_t idx = 0; GetSupportedArchitectureAtIndex( - idx, resolved_module_spec.GetArchitecture()); - ++idx) { - error = - ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, - module_search_paths_ptr, NULL, NULL); - // Did we find an executable using one of the - if (error.Success()) { - if (exe_module_sp && exe_module_sp->GetObjectFile()) - break; - else - error.SetErrorToGenericError(); - } - - if (idx > 0) - arch_names.PutCString(", "); - arch_names.PutCString( - resolved_module_spec.GetArchitecture().GetArchitectureName()); - } - - if (error.Fail() || !exe_module_sp) { - if (resolved_module_spec.GetFileSpec().Readable()) { - error.SetErrorStringWithFormat( - "'%s' doesn't contain any '%s' platform architectures: %s", - resolved_module_spec.GetFileSpec().GetPath().c_str(), - GetPluginName().GetCString(), arch_names.GetData()); - } else { - error.SetErrorStringWithFormat( - "'%s' is not readable", - resolved_module_spec.GetFileSpec().GetPath().c_str()); - } - } - } - } - - return error; -} - -// From PlatformMacOSX only -Error PlatformFreeBSD::GetFileWithUUID(const FileSpec &platform_file, - const UUID *uuid_ptr, - FileSpec &local_file) { - if (IsRemote()) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, - local_file); - } - - // Default to the local case - local_file = platform_file; - return Error(); + PlatformPOSIX::Terminate(); } //------------------------------------------------------------------ /// Default Constructor //------------------------------------------------------------------ PlatformFreeBSD::PlatformFreeBSD(bool is_host) - : Platform(is_host), m_remote_platform_sp() {} - -//------------------------------------------------------------------ -/// Destructor. -/// -/// The destructor is virtual since this class is designed to be -/// inherited from by the plug-in instance. -//------------------------------------------------------------------ -PlatformFreeBSD::~PlatformFreeBSD() {} - -// TODO:VK: inherit PlatformPOSIX - -bool PlatformFreeBSD::GetRemoteOSVersion() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetOSVersion( - m_major_os_version, m_minor_os_version, m_update_os_version); - return false; -} - -bool PlatformFreeBSD::GetRemoteOSBuildString(std::string &s) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetRemoteOSBuildString(s); - s.clear(); - return false; -} - -bool PlatformFreeBSD::GetRemoteOSKernelDescription(std::string &s) { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetRemoteOSKernelDescription(s); - s.clear(); - return false; -} - -// Remote Platform subclasses need to override this function -ArchSpec PlatformFreeBSD::GetRemoteSystemArchitecture() { - if (m_remote_platform_sp) - return m_remote_platform_sp->GetRemoteSystemArchitecture(); - return ArchSpec(); -} - -const char *PlatformFreeBSD::GetHostname() { - if (IsHost()) - return Platform::GetHostname(); - - if (m_remote_platform_sp) - return m_remote_platform_sp->GetHostname(); - return NULL; -} - -bool PlatformFreeBSD::IsConnected() const { - if (IsHost()) - return true; - else if (m_remote_platform_sp) - return m_remote_platform_sp->IsConnected(); - return false; -} + : PlatformPOSIX(is_host) // This is the local host platform +{} -Error PlatformFreeBSD::ConnectRemote(Args &args) { - Error error; - if (IsHost()) { - error.SetErrorStringWithFormat( - "can't connect to the host platform '%s', always connected", - GetPluginName().GetCString()); - } else { - if (!m_remote_platform_sp) - m_remote_platform_sp = - Platform::Create(ConstString("remote-gdb-server"), error); - - if (m_remote_platform_sp) { - if (error.Success()) { - if (m_remote_platform_sp) { - error = m_remote_platform_sp->ConnectRemote(args); - } else { - error.SetErrorString( - "\"platform connect\" takes a single argument: <connect-url>"); - } - } - } else - error.SetErrorString("failed to create a 'remote-gdb-server' platform"); - - if (error.Fail()) - m_remote_platform_sp.reset(); - } - - return error; -} - -Error PlatformFreeBSD::DisconnectRemote() { - Error error; - - if (IsHost()) { - error.SetErrorStringWithFormat( - "can't disconnect from the host platform '%s', always connected", - GetPluginName().GetCString()); - } else { - if (m_remote_platform_sp) - error = m_remote_platform_sp->DisconnectRemote(); - else - error.SetErrorString("the platform is not currently connected"); - } - return error; -} - -bool PlatformFreeBSD::GetProcessInfo(lldb::pid_t pid, - ProcessInstanceInfo &process_info) { - bool success = false; - if (IsHost()) { - success = Platform::GetProcessInfo(pid, process_info); - } else if (m_remote_platform_sp) { - success = m_remote_platform_sp->GetProcessInfo(pid, process_info); - } - return success; -} - -uint32_t -PlatformFreeBSD::FindProcesses(const ProcessInstanceInfoMatch &match_info, - ProcessInstanceInfoList &process_infos) { - uint32_t match_count = 0; - if (IsHost()) { - // Let the base class figure out the host details - match_count = Platform::FindProcesses(match_info, process_infos); - } else { - // If we are remote, we can only return results if we are connected - if (m_remote_platform_sp) - match_count = - m_remote_platform_sp->FindProcesses(match_info, process_infos); - } - return match_count; -} - -const char *PlatformFreeBSD::GetUserName(uint32_t uid) { - // Check the cache in Platform in case we have already looked this uid up - const char *user_name = Platform::GetUserName(uid); - if (user_name) - return user_name; - - if (IsRemote() && m_remote_platform_sp) - return m_remote_platform_sp->GetUserName(uid); - return NULL; -} - -const char *PlatformFreeBSD::GetGroupName(uint32_t gid) { - const char *group_name = Platform::GetGroupName(gid); - if (group_name) - return group_name; - - if (IsRemote() && m_remote_platform_sp) - return m_remote_platform_sp->GetGroupName(gid); - return NULL; -} - -Error PlatformFreeBSD::GetSharedModule( - const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, - bool *did_create_ptr) { - Error error; - module_sp.reset(); - - if (IsRemote()) { - // If we have a remote platform always, let it try and locate - // the shared module first. - if (m_remote_platform_sp) { - error = m_remote_platform_sp->GetSharedModule( - module_spec, process, module_sp, module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - } - } - - if (!module_sp) { - // Fall back to the local platform and find the file locally - error = Platform::GetSharedModule(module_spec, process, module_sp, - module_search_paths_ptr, - old_module_sp_ptr, did_create_ptr); - } - if (module_sp) - module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); - return error; -} +PlatformFreeBSD::~PlatformFreeBSD() = default; bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { @@ -507,26 +203,23 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx, } void PlatformFreeBSD::GetStatus(Stream &strm) { -#ifndef LLDB_DISABLE_POSIX - struct utsname un; - - strm << " Host: "; + Platform::GetStatus(strm); - ::memset(&un, 0, sizeof(utsname)); - if (uname(&un) == -1) - strm << "FreeBSD" << '\n'; +#ifndef LLDB_DISABLE_POSIX + // Display local kernel information only when we are running in host mode. + // Otherwise, we would end up printing non-FreeBSD information (when running + // on Mac OS for example). + if (IsHost()) { + struct utsname un; - strm << un.sysname << ' ' << un.release; - if (un.nodename[0] != '\0') - strm << " (" << un.nodename << ')'; - strm << '\n'; + if (uname(&un)) + return; - // Dump a common information about the platform status. - strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version - << '\n'; + strm.Printf(" Kernel: %s\n", un.sysname); + strm.Printf(" Release: %s\n", un.release); + strm.Printf(" Version: %s\n", un.version); + } #endif - - Platform::GetStatus(strm); } size_t @@ -549,6 +242,12 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target, // FreeBSD kernel as of 10.x, does not support thumb breakpoints return 0; } + + static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7}; + size_t trap_opcode_size = sizeof(g_arm_breakpoint_opcode); + assert(bp_site); + if (bp_site->SetTrapOpcode(g_arm_breakpoint_opcode, trap_opcode_size)) + return trap_opcode_size; } LLVM_FALLTHROUGH; default: @@ -556,10 +255,6 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target, } } -void PlatformFreeBSD::CalculateTrapHandlerSymbolNames() { - m_trap_handlers.push_back(ConstString("_sigtramp")); -} - Error PlatformFreeBSD::LaunchProcess(ProcessLaunchInfo &launch_info) { Error error; if (IsHost()) { @@ -609,3 +304,23 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, } return process_sp; } + +// FreeBSD processes cannot yet be launched by spawning and attaching. +bool PlatformFreeBSD::CanDebugProcess() { + return false; +} + +void PlatformFreeBSD::CalculateTrapHandlerSymbolNames() { + m_trap_handlers.push_back(ConstString("_sigtramp")); +} + +uint64_t PlatformFreeBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch, + unsigned flags) { + uint64_t flags_platform = 0; + + if (flags & eMmapFlagsPrivate) + flags_platform |= MAP_PRIVATE; + if (flags & eMmapFlagsAnon) + flags_platform |= MAP_ANON; + return flags_platform; +} |