15ffd83dbSDimitry Andric //===-- PlatformOpenBSD.cpp -----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PlatformOpenBSD.h"
100b57cec5SDimitry Andric #include "lldb/Host/Config.h"
110b57cec5SDimitry Andric 
12fe6060f1SDimitry Andric #include <cstdio>
13480093f4SDimitry Andric #if LLDB_ENABLE_POSIX
140b57cec5SDimitry Andric #include <sys/utsname.h>
150b57cec5SDimitry Andric #endif
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
180b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
190b57cec5SDimitry Andric #include "lldb/Host/HostInfo.h"
200b57cec5SDimitry Andric #include "lldb/Target/Process.h"
210b57cec5SDimitry Andric #include "lldb/Target/Target.h"
220b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
2381ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
240b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
250b57cec5SDimitry Andric #include "lldb/Utility/State.h"
260b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
270b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric // Define these constants from OpenBSD mman.h for use when targeting remote
300b57cec5SDimitry Andric // openbsd systems even when host has different values.
310b57cec5SDimitry Andric #define MAP_PRIVATE 0x0002
320b57cec5SDimitry Andric #define MAP_ANON 0x1000
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric using namespace lldb;
350b57cec5SDimitry Andric using namespace lldb_private;
360b57cec5SDimitry Andric using namespace lldb_private::platform_openbsd;
370b57cec5SDimitry Andric 
385ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(PlatformOpenBSD)
395ffd83dbSDimitry Andric 
400b57cec5SDimitry Andric static uint32_t g_initialize_count = 0;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric 
CreateInstance(bool force,const ArchSpec * arch)430b57cec5SDimitry Andric PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) {
4481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Platform);
450b57cec5SDimitry Andric   LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
460b57cec5SDimitry Andric            arch ? arch->GetArchitectureName() : "<null>",
470b57cec5SDimitry Andric            arch ? arch->GetTriple().getTriple() : "<null>");
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   bool create = force;
500b57cec5SDimitry Andric   if (!create && arch && arch->IsValid()) {
510b57cec5SDimitry Andric     const llvm::Triple &triple = arch->GetTriple();
520b57cec5SDimitry Andric     switch (triple.getOS()) {
530b57cec5SDimitry Andric     case llvm::Triple::OpenBSD:
540b57cec5SDimitry Andric       create = true;
550b57cec5SDimitry Andric       break;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric #if defined(__OpenBSD__)
580b57cec5SDimitry Andric     // Only accept "unknown" for the OS if the host is BSD and it "unknown"
590b57cec5SDimitry Andric     // wasn't specified (it was just returned because it was NOT specified)
600b57cec5SDimitry Andric     case llvm::Triple::OSType::UnknownOS:
610b57cec5SDimitry Andric       create = !arch->TripleOSWasSpecified();
620b57cec5SDimitry Andric       break;
630b57cec5SDimitry Andric #endif
640b57cec5SDimitry Andric     default:
650b57cec5SDimitry Andric       break;
660b57cec5SDimitry Andric     }
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric   LLDB_LOG(log, "create = {0}", create);
690b57cec5SDimitry Andric   if (create) {
700b57cec5SDimitry Andric     return PlatformSP(new PlatformOpenBSD(false));
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric   return PlatformSP();
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
GetPluginDescriptionStatic(bool is_host)75349cc55cSDimitry Andric llvm::StringRef PlatformOpenBSD::GetPluginDescriptionStatic(bool is_host) {
760b57cec5SDimitry Andric   if (is_host)
770b57cec5SDimitry Andric     return "Local OpenBSD user platform plug-in.";
780b57cec5SDimitry Andric   return "Remote OpenBSD user platform plug-in.";
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
Initialize()810b57cec5SDimitry Andric void PlatformOpenBSD::Initialize() {
820b57cec5SDimitry Andric   Platform::Initialize();
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   if (g_initialize_count++ == 0) {
850b57cec5SDimitry Andric #if defined(__OpenBSD__)
860b57cec5SDimitry Andric     PlatformSP default_platform_sp(new PlatformOpenBSD(true));
870b57cec5SDimitry Andric     default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
880b57cec5SDimitry Andric     Platform::SetHostPlatform(default_platform_sp);
890b57cec5SDimitry Andric #endif
900b57cec5SDimitry Andric     PluginManager::RegisterPlugin(
910b57cec5SDimitry Andric         PlatformOpenBSD::GetPluginNameStatic(false),
920b57cec5SDimitry Andric         PlatformOpenBSD::GetPluginDescriptionStatic(false),
930b57cec5SDimitry Andric         PlatformOpenBSD::CreateInstance, nullptr);
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
Terminate()970b57cec5SDimitry Andric void PlatformOpenBSD::Terminate() {
980b57cec5SDimitry Andric   if (g_initialize_count > 0) {
990b57cec5SDimitry Andric     if (--g_initialize_count == 0) {
1000b57cec5SDimitry Andric       PluginManager::UnregisterPlugin(PlatformOpenBSD::CreateInstance);
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   PlatformPOSIX::Terminate();
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric /// Default Constructor
PlatformOpenBSD(bool is_host)1080b57cec5SDimitry Andric PlatformOpenBSD::PlatformOpenBSD(bool is_host)
1090b57cec5SDimitry Andric     : PlatformPOSIX(is_host) // This is the local host platform
110349cc55cSDimitry Andric {
111349cc55cSDimitry Andric   if (is_host) {
112349cc55cSDimitry Andric     m_supported_architectures.push_back(HostInfo::GetArchitecture());
1130b57cec5SDimitry Andric   } else {
114349cc55cSDimitry Andric     m_supported_architectures =
115349cc55cSDimitry Andric         CreateArchList({llvm::Triple::x86_64, llvm::Triple::x86,
116349cc55cSDimitry Andric                         llvm::Triple::aarch64, llvm::Triple::arm},
117349cc55cSDimitry Andric                        llvm::Triple::OpenBSD);
118349cc55cSDimitry Andric   }
119349cc55cSDimitry Andric }
120349cc55cSDimitry Andric 
12181ad6265SDimitry Andric std::vector<ArchSpec>
GetSupportedArchitectures(const ArchSpec & process_host_arch)12281ad6265SDimitry Andric PlatformOpenBSD::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
1230b57cec5SDimitry Andric   if (m_remote_platform_sp)
12481ad6265SDimitry Andric     return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch);
125349cc55cSDimitry Andric   return m_supported_architectures;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
GetStatus(Stream & strm)1280b57cec5SDimitry Andric void PlatformOpenBSD::GetStatus(Stream &strm) {
1290b57cec5SDimitry Andric   Platform::GetStatus(strm);
1300b57cec5SDimitry Andric 
131480093f4SDimitry Andric #if LLDB_ENABLE_POSIX
1320b57cec5SDimitry Andric   // Display local kernel information only when we are running in host mode.
1330b57cec5SDimitry Andric   // Otherwise, we would end up printing non-OpenBSD information (when running
1340b57cec5SDimitry Andric   // on Mac OS for example).
1350b57cec5SDimitry Andric   if (IsHost()) {
1360b57cec5SDimitry Andric     struct utsname un;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric     if (uname(&un))
1390b57cec5SDimitry Andric       return;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric     strm.Printf("    Kernel: %s\n", un.sysname);
1420b57cec5SDimitry Andric     strm.Printf("   Release: %s\n", un.release);
1430b57cec5SDimitry Andric     strm.Printf("   Version: %s\n", un.version);
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric #endif
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric // OpenBSD processes cannot yet be launched by spawning and attaching.
CanDebugProcess()1490b57cec5SDimitry Andric bool PlatformOpenBSD::CanDebugProcess() {
1500b57cec5SDimitry Andric   return false;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
CalculateTrapHandlerSymbolNames()1530b57cec5SDimitry Andric void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() {
1540b57cec5SDimitry Andric   m_trap_handlers.push_back(ConstString("_sigtramp"));
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
GetMmapArgumentList(const ArchSpec & arch,addr_t addr,addr_t length,unsigned prot,unsigned flags,addr_t fd,addr_t offset)1570b57cec5SDimitry Andric MmapArgList PlatformOpenBSD::GetMmapArgumentList(const ArchSpec &arch,
1580b57cec5SDimitry Andric                                                  addr_t addr, addr_t length,
1590b57cec5SDimitry Andric                                                  unsigned prot, unsigned flags,
1600b57cec5SDimitry Andric                                                  addr_t fd, addr_t offset) {
1610b57cec5SDimitry Andric   uint64_t flags_platform = 0;
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   if (flags & eMmapFlagsPrivate)
1640b57cec5SDimitry Andric     flags_platform |= MAP_PRIVATE;
1650b57cec5SDimitry Andric   if (flags & eMmapFlagsAnon)
1660b57cec5SDimitry Andric     flags_platform |= MAP_ANON;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   MmapArgList args({addr, length, prot, flags_platform, fd, offset});
1690b57cec5SDimitry Andric   return args;
1700b57cec5SDimitry Andric }
171