1 //===-- PlatformOpenBSD.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "PlatformOpenBSD.h" 10 #include "lldb/Host/Config.h" 11 12 #include <cstdio> 13 #if LLDB_ENABLE_POSIX 14 #include <sys/utsname.h> 15 #endif 16 17 #include "lldb/Core/Debugger.h" 18 #include "lldb/Core/PluginManager.h" 19 #include "lldb/Host/HostInfo.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Utility/FileSpec.h" 23 #include "lldb/Utility/LLDBLog.h" 24 #include "lldb/Utility/Log.h" 25 #include "lldb/Utility/State.h" 26 #include "lldb/Utility/Status.h" 27 #include "lldb/Utility/StreamString.h" 28 #include "Plugins/Process/OpenBSDKernel/ProcessOpenBSDKernel.h" 29 30 // Define these constants from OpenBSD mman.h for use when targeting remote 31 // openbsd systems even when host has different values. 32 #define MAP_PRIVATE 0x0002 33 #define MAP_ANON 0x1000 34 35 using namespace lldb; 36 using namespace lldb_private; 37 using namespace lldb_private::platform_openbsd; 38 39 LLDB_PLUGIN_DEFINE(PlatformOpenBSD) 40 41 static uint32_t g_initialize_count = 0; 42 43 44 PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) { 45 Log *log = GetLog(LLDBLog::Platform); 46 LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force, 47 arch ? arch->GetArchitectureName() : "<null>", 48 arch ? arch->GetTriple().getTriple() : "<null>"); 49 50 bool create = force; 51 if (!create && arch && arch->IsValid()) { 52 const llvm::Triple &triple = arch->GetTriple(); 53 switch (triple.getOS()) { 54 case llvm::Triple::OpenBSD: 55 create = true; 56 break; 57 58 #if defined(__OpenBSD__) 59 // Only accept "unknown" for the OS if the host is BSD and it "unknown" 60 // wasn't specified (it was just returned because it was NOT specified) 61 case llvm::Triple::OSType::UnknownOS: 62 create = !arch->TripleOSWasSpecified(); 63 break; 64 #endif 65 default: 66 break; 67 } 68 } 69 LLDB_LOG(log, "create = {0}", create); 70 if (create) { 71 return PlatformSP(new PlatformOpenBSD(false)); 72 } 73 return PlatformSP(); 74 } 75 76 llvm::StringRef PlatformOpenBSD::GetPluginDescriptionStatic(bool is_host) { 77 if (is_host) 78 return "Local OpenBSD user platform plug-in."; 79 return "Remote OpenBSD user platform plug-in."; 80 } 81 82 void PlatformOpenBSD::Initialize() { 83 PlatformPOSIX::Initialize(); 84 85 if (g_initialize_count++ == 0) { 86 #if defined(__OpenBSD__) 87 PlatformSP default_platform_sp(new PlatformOpenBSD(true)); 88 default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 89 Platform::SetHostPlatform(default_platform_sp); 90 #endif 91 PluginManager::RegisterPlugin( 92 PlatformOpenBSD::GetPluginNameStatic(false), 93 PlatformOpenBSD::GetPluginDescriptionStatic(false), 94 PlatformOpenBSD::CreateInstance, nullptr); 95 ProcessOpenBSDKernel::Initialize(); 96 } 97 } 98 99 void PlatformOpenBSD::Terminate() { 100 if (g_initialize_count > 0) { 101 if (--g_initialize_count == 0) { 102 PluginManager::UnregisterPlugin(PlatformOpenBSD::CreateInstance); 103 ProcessOpenBSDKernel::Terminate(); 104 } 105 } 106 107 PlatformPOSIX::Terminate(); 108 } 109 110 /// Default Constructor 111 PlatformOpenBSD::PlatformOpenBSD(bool is_host) 112 : PlatformPOSIX(is_host) // This is the local host platform 113 { 114 if (is_host) { 115 m_supported_architectures.push_back(HostInfo::GetArchitecture()); 116 } else { 117 m_supported_architectures = 118 CreateArchList({llvm::Triple::x86_64, llvm::Triple::x86, 119 llvm::Triple::aarch64, llvm::Triple::arm}, 120 llvm::Triple::OpenBSD); 121 } 122 } 123 124 std::vector<ArchSpec> 125 PlatformOpenBSD::GetSupportedArchitectures(const ArchSpec &process_host_arch) { 126 if (m_remote_platform_sp) 127 return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch); 128 return m_supported_architectures; 129 } 130 131 void PlatformOpenBSD::GetStatus(Stream &strm) { 132 Platform::GetStatus(strm); 133 134 #if LLDB_ENABLE_POSIX 135 // Display local kernel information only when we are running in host mode. 136 // Otherwise, we would end up printing non-OpenBSD information (when running 137 // on Mac OS for example). 138 if (IsHost()) { 139 struct utsname un; 140 141 if (uname(&un)) 142 return; 143 144 strm.Printf(" Kernel: %s\n", un.sysname); 145 strm.Printf(" Release: %s\n", un.release); 146 strm.Printf(" Version: %s\n", un.version); 147 } 148 #endif 149 } 150 151 bool PlatformOpenBSD::CanDebugProcess() { 152 if (IsHost()) { 153 return true; 154 } else { 155 // If we're connected, we can debug. 156 return IsConnected(); 157 } 158 } 159 160 void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() { 161 m_trap_handlers.push_back(ConstString("_sigtramp")); 162 } 163 164 MmapArgList PlatformOpenBSD::GetMmapArgumentList(const ArchSpec &arch, 165 addr_t addr, addr_t length, 166 unsigned prot, unsigned flags, 167 addr_t fd, addr_t offset) { 168 uint64_t flags_platform = 0; 169 170 if (flags & eMmapFlagsPrivate) 171 flags_platform |= MAP_PRIVATE; 172 if (flags & eMmapFlagsAnon) 173 flags_platform |= MAP_ANON; 174 175 MmapArgList args({addr, length, prot, flags_platform, fd, offset}); 176 return args; 177 } 178 179 FileSpec PlatformOpenBSD::LocateExecutable(const char *basename) { 180 181 std::string check = std::string("/usr/bin/") + basename; 182 if (access(check.c_str(), X_OK) == 0) { 183 return FileSpec(check); 184 } 185 186 return FileSpec(); 187 } 188