PlatformOpenBSD.cpp revision 360784
1//===-- PlatformOpenBSD.cpp -------------------------------------*- C++ -*-===//
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 <stdio.h>
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/Log.h"
24#include "lldb/Utility/State.h"
25#include "lldb/Utility/Status.h"
26#include "lldb/Utility/StreamString.h"
27
28// Define these constants from OpenBSD mman.h for use when targeting remote
29// openbsd systems even when host has different values.
30#define MAP_PRIVATE 0x0002
31#define MAP_ANON 0x1000
32
33using namespace lldb;
34using namespace lldb_private;
35using namespace lldb_private::platform_openbsd;
36
37static uint32_t g_initialize_count = 0;
38
39
40PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) {
41  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
42  LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
43           arch ? arch->GetArchitectureName() : "<null>",
44           arch ? arch->GetTriple().getTriple() : "<null>");
45
46  bool create = force;
47  if (!create && arch && arch->IsValid()) {
48    const llvm::Triple &triple = arch->GetTriple();
49    switch (triple.getOS()) {
50    case llvm::Triple::OpenBSD:
51      create = true;
52      break;
53
54#if defined(__OpenBSD__)
55    // Only accept "unknown" for the OS if the host is BSD and it "unknown"
56    // wasn't specified (it was just returned because it was NOT specified)
57    case llvm::Triple::OSType::UnknownOS:
58      create = !arch->TripleOSWasSpecified();
59      break;
60#endif
61    default:
62      break;
63    }
64  }
65  LLDB_LOG(log, "create = {0}", create);
66  if (create) {
67    return PlatformSP(new PlatformOpenBSD(false));
68  }
69  return PlatformSP();
70}
71
72ConstString PlatformOpenBSD::GetPluginNameStatic(bool is_host) {
73  if (is_host) {
74    static ConstString g_host_name(Platform::GetHostPlatformName());
75    return g_host_name;
76  } else {
77    static ConstString g_remote_name("remote-openbsd");
78    return g_remote_name;
79  }
80}
81
82const char *PlatformOpenBSD::GetPluginDescriptionStatic(bool is_host) {
83  if (is_host)
84    return "Local OpenBSD user platform plug-in.";
85  else
86    return "Remote OpenBSD user platform plug-in.";
87}
88
89ConstString PlatformOpenBSD::GetPluginName() {
90  return GetPluginNameStatic(IsHost());
91}
92
93void PlatformOpenBSD::Initialize() {
94  Platform::Initialize();
95
96  if (g_initialize_count++ == 0) {
97#if defined(__OpenBSD__)
98    PlatformSP default_platform_sp(new PlatformOpenBSD(true));
99    default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
100    Platform::SetHostPlatform(default_platform_sp);
101#endif
102    PluginManager::RegisterPlugin(
103        PlatformOpenBSD::GetPluginNameStatic(false),
104        PlatformOpenBSD::GetPluginDescriptionStatic(false),
105        PlatformOpenBSD::CreateInstance, nullptr);
106  }
107}
108
109void PlatformOpenBSD::Terminate() {
110  if (g_initialize_count > 0) {
111    if (--g_initialize_count == 0) {
112      PluginManager::UnregisterPlugin(PlatformOpenBSD::CreateInstance);
113    }
114  }
115
116  PlatformPOSIX::Terminate();
117}
118
119/// Default Constructor
120PlatformOpenBSD::PlatformOpenBSD(bool is_host)
121    : PlatformPOSIX(is_host) // This is the local host platform
122{}
123
124PlatformOpenBSD::~PlatformOpenBSD() = default;
125
126bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
127                                                      ArchSpec &arch) {
128  if (IsHost()) {
129    ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
130    if (hostArch.GetTriple().isOSOpenBSD()) {
131      if (idx == 0) {
132        arch = hostArch;
133        return arch.IsValid();
134      }
135    }
136  } else {
137    if (m_remote_platform_sp)
138      return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
139
140    llvm::Triple triple;
141    // Set the OS to OpenBSD
142    triple.setOS(llvm::Triple::OpenBSD);
143    // Set the architecture
144    switch (idx) {
145    case 0:
146      triple.setArchName("x86_64");
147      break;
148    case 1:
149      triple.setArchName("i386");
150      break;
151    case 2:
152      triple.setArchName("aarch64");
153      break;
154    case 3:
155      triple.setArchName("arm");
156      break;
157    default:
158      return false;
159    }
160    // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
161    // vendor by calling triple.SetVendorName("unknown") so that it is a
162    // "unspecified unknown". This means when someone calls
163    // triple.GetVendorName() it will return an empty string which indicates
164    // that the vendor can be set when two architectures are merged
165
166    // Now set the triple into "arch" and return true
167    arch.SetTriple(triple);
168    return true;
169  }
170  return false;
171}
172
173void PlatformOpenBSD::GetStatus(Stream &strm) {
174  Platform::GetStatus(strm);
175
176#if LLDB_ENABLE_POSIX
177  // Display local kernel information only when we are running in host mode.
178  // Otherwise, we would end up printing non-OpenBSD information (when running
179  // on Mac OS for example).
180  if (IsHost()) {
181    struct utsname un;
182
183    if (uname(&un))
184      return;
185
186    strm.Printf("    Kernel: %s\n", un.sysname);
187    strm.Printf("   Release: %s\n", un.release);
188    strm.Printf("   Version: %s\n", un.version);
189  }
190#endif
191}
192
193// OpenBSD processes cannot yet be launched by spawning and attaching.
194bool PlatformOpenBSD::CanDebugProcess() {
195  return false;
196}
197
198void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() {
199  m_trap_handlers.push_back(ConstString("_sigtramp"));
200}
201
202MmapArgList PlatformOpenBSD::GetMmapArgumentList(const ArchSpec &arch,
203                                                 addr_t addr, addr_t length,
204                                                 unsigned prot, unsigned flags,
205                                                 addr_t fd, addr_t offset) {
206  uint64_t flags_platform = 0;
207
208  if (flags & eMmapFlagsPrivate)
209    flags_platform |= MAP_PRIVATE;
210  if (flags & eMmapFlagsAnon)
211    flags_platform |= MAP_ANON;
212
213  MmapArgList args({addr, length, prot, flags_platform, fd, offset});
214  return args;
215}
216