Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- PlatformNetBSD.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 "PlatformNetBSD.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
29
// Define these constants from NetBSD mman.h for use when targeting remote
30
// netbsd systems even when host has different values.
31
0
#define MAP_PRIVATE 0x0002
32
0
#define MAP_ANON 0x1000
33
34
using namespace lldb;
35
using namespace lldb_private;
36
using namespace lldb_private::platform_netbsd;
37
38
LLDB_PLUGIN_DEFINE(PlatformNetBSD)
39
40
static uint32_t g_initialize_count = 0;
41
42
43
213
PlatformSP PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) {
44
213
  Log *log = GetLog(LLDBLog::Platform);
45
213
  LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
46
213
           arch ? arch->GetArchitectureName() : "<null>",
47
213
           arch ? arch->GetTriple().getTriple() : "<null>");
48
49
213
  bool create = force;
50
213
  if (!create && 
arch204
&&
arch->IsValid()204
) {
51
204
    const llvm::Triple &triple = arch->GetTriple();
52
204
    switch (triple.getOS()) {
53
16
    case llvm::Triple::NetBSD:
54
16
      create = true;
55
16
      break;
56
57
188
    default:
58
188
      break;
59
204
    }
60
204
  }
61
62
213
  LLDB_LOG(log, "create = {0}", create);
63
213
  if (create) {
64
25
    return PlatformSP(new PlatformNetBSD(false));
65
25
  }
66
188
  return PlatformSP();
67
213
}
68
69
3.93k
llvm::StringRef PlatformNetBSD::GetPluginDescriptionStatic(bool is_host) {
70
3.93k
  if (is_host)
71
0
    return "Local NetBSD user platform plug-in.";
72
3.93k
  return "Remote NetBSD user platform plug-in.";
73
3.93k
}
74
75
3.93k
void PlatformNetBSD::Initialize() {
76
3.93k
  PlatformPOSIX::Initialize();
77
78
3.93k
  if (g_initialize_count++ == 0) {
79
#if defined(__NetBSD__)
80
    PlatformSP default_platform_sp(new PlatformNetBSD(true));
81
    default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
82
    Platform::SetHostPlatform(default_platform_sp);
83
#endif
84
3.93k
    PluginManager::RegisterPlugin(
85
3.93k
        PlatformNetBSD::GetPluginNameStatic(false),
86
3.93k
        PlatformNetBSD::GetPluginDescriptionStatic(false),
87
3.93k
        PlatformNetBSD::CreateInstance, nullptr);
88
3.93k
  }
89
3.93k
}
90
91
3.92k
void PlatformNetBSD::Terminate() {
92
3.92k
  if (g_initialize_count > 0) {
93
3.92k
    if (--g_initialize_count == 0) {
94
3.92k
      PluginManager::UnregisterPlugin(PlatformNetBSD::CreateInstance);
95
3.92k
    }
96
3.92k
  }
97
98
3.92k
  PlatformPOSIX::Terminate();
99
3.92k
}
100
101
/// Default Constructor
102
PlatformNetBSD::PlatformNetBSD(bool is_host)
103
25
    : PlatformPOSIX(is_host) // This is the local host platform
104
25
{
105
25
  if (is_host) {
106
0
    ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
107
0
    m_supported_architectures.push_back(hostArch);
108
0
    if (hostArch.GetTriple().isArch64Bit()) {
109
0
      m_supported_architectures.push_back(
110
0
          HostInfo::GetArchitecture(HostInfo::eArchKind32));
111
0
    }
112
25
  } else {
113
25
    m_supported_architectures = CreateArchList(
114
25
        {llvm::Triple::x86_64, llvm::Triple::x86}, llvm::Triple::NetBSD);
115
25
  }
116
25
}
117
118
std::vector<ArchSpec>
119
25
PlatformNetBSD::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
120
25
  if (m_remote_platform_sp)
121
0
    return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch);
122
25
  return m_supported_architectures;
123
25
}
124
125
0
void PlatformNetBSD::GetStatus(Stream &strm) {
126
0
  Platform::GetStatus(strm);
127
128
0
#if LLDB_ENABLE_POSIX
129
  // Display local kernel information only when we are running in host mode.
130
  // Otherwise, we would end up printing non-NetBSD information (when running
131
  // on Mac OS for example).
132
0
  if (IsHost()) {
133
0
    struct utsname un;
134
135
0
    if (uname(&un))
136
0
      return;
137
138
0
    strm.Printf("    Kernel: %s\n", un.sysname);
139
0
    strm.Printf("   Release: %s\n", un.release);
140
0
    strm.Printf("   Version: %s\n", un.version);
141
0
  }
142
0
#endif
143
0
}
144
145
uint32_t
146
0
PlatformNetBSD::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
147
0
  uint32_t resume_count = 0;
148
149
  // Always resume past the initial stop when we use eLaunchFlagDebug
150
0
  if (launch_info.GetFlags().Test(eLaunchFlagDebug)) {
151
    // Resume past the stop for the final exec into the true inferior.
152
0
    ++resume_count;
153
0
  }
154
155
  // If we're not launching a shell, we're done.
156
0
  const FileSpec &shell = launch_info.GetShell();
157
0
  if (!shell)
158
0
    return resume_count;
159
160
0
  std::string shell_string = shell.GetPath();
161
  // We're in a shell, so for sure we have to resume past the shell exec.
162
0
  ++resume_count;
163
164
  // Figure out what shell we're planning on using.
165
0
  const char *shell_name = strrchr(shell_string.c_str(), '/');
166
0
  if (shell_name == nullptr)
167
0
    shell_name = shell_string.c_str();
168
0
  else
169
0
    shell_name++;
170
171
0
  if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 ||
172
0
      strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) {
173
    // These shells seem to re-exec themselves.  Add another resume.
174
0
    ++resume_count;
175
0
  }
176
177
0
  return resume_count;
178
0
}
179
180
0
bool PlatformNetBSD::CanDebugProcess() {
181
0
  if (IsHost()) {
182
0
    return true;
183
0
  } else {
184
    // If we're connected, we can debug.
185
0
    return IsConnected();
186
0
  }
187
0
}
188
189
3
void PlatformNetBSD::CalculateTrapHandlerSymbolNames() {
190
3
  m_trap_handlers.push_back(ConstString("_sigtramp"));
191
3
}
192
193
MmapArgList PlatformNetBSD::GetMmapArgumentList(const ArchSpec &arch,
194
                                                addr_t addr, addr_t length,
195
                                                unsigned prot, unsigned flags,
196
0
                                                addr_t fd, addr_t offset) {
197
0
  uint64_t flags_platform = 0;
198
199
0
  if (flags & eMmapFlagsPrivate)
200
0
    flags_platform |= MAP_PRIVATE;
201
0
  if (flags & eMmapFlagsAnon)
202
0
    flags_platform |= MAP_ANON;
203
204
0
  MmapArgList args({addr, length, prot, flags_platform, fd, offset});
205
0
  return args;
206
0
}
207
208
2
CompilerType PlatformNetBSD::GetSiginfoType(const llvm::Triple &triple) {
209
2
  {
210
2
    std::lock_guard<std::mutex> guard(m_mutex);
211
2
    if (!m_type_system)
212
2
      m_type_system = std::make_shared<TypeSystemClang>("siginfo", triple);
213
2
  }
214
2
  TypeSystemClang *ast = m_type_system.get();
215
216
  // generic types
217
2
  CompilerType int_type = ast->GetBasicType(eBasicTypeInt);
218
2
  CompilerType uint_type = ast->GetBasicType(eBasicTypeUnsignedInt);
219
2
  CompilerType long_type = ast->GetBasicType(eBasicTypeLong);
220
2
  CompilerType long_long_type = ast->GetBasicType(eBasicTypeLongLong);
221
2
  CompilerType voidp_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
222
223
  // platform-specific types
224
2
  CompilerType &pid_type = int_type;
225
2
  CompilerType &uid_type = uint_type;
226
2
  CompilerType &clock_type = uint_type;
227
2
  CompilerType &lwpid_type = int_type;
228
229
2
  CompilerType sigval_type = ast->CreateRecordType(
230
2
      nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t",
231
2
      clang::TTK_Union, lldb::eLanguageTypeC);
232
2
  ast->StartTagDeclarationDefinition(sigval_type);
233
2
  ast->AddFieldToRecordType(sigval_type, "sival_int", int_type,
234
2
                            lldb::eAccessPublic, 0);
235
2
  ast->AddFieldToRecordType(sigval_type, "sival_ptr", voidp_type,
236
2
                            lldb::eAccessPublic, 0);
237
2
  ast->CompleteTagDeclarationDefinition(sigval_type);
238
239
2
  CompilerType ptrace_option_type = ast->CreateRecordType(
240
2
      nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "",
241
2
      clang::TTK_Union, lldb::eLanguageTypeC);
242
2
  ast->StartTagDeclarationDefinition(ptrace_option_type);
243
2
  ast->AddFieldToRecordType(ptrace_option_type, "_pe_other_pid", pid_type,
244
2
                            lldb::eAccessPublic, 0);
245
2
  ast->AddFieldToRecordType(ptrace_option_type, "_pe_lwp", lwpid_type,
246
2
                            lldb::eAccessPublic, 0);
247
2
  ast->CompleteTagDeclarationDefinition(ptrace_option_type);
248
249
  // siginfo_t
250
2
  CompilerType siginfo_type = ast->CreateRecordType(
251
2
      nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t",
252
2
      clang::TTK_Union, lldb::eLanguageTypeC);
253
2
  ast->StartTagDeclarationDefinition(siginfo_type);
254
255
  // struct _ksiginfo
256
2
  CompilerType ksiginfo_type = ast->CreateRecordType(
257
2
      nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "",
258
2
      clang::TTK_Struct, lldb::eLanguageTypeC);
259
2
  ast->StartTagDeclarationDefinition(ksiginfo_type);
260
2
  ast->AddFieldToRecordType(ksiginfo_type, "_signo", int_type,
261
2
                            lldb::eAccessPublic, 0);
262
2
  ast->AddFieldToRecordType(ksiginfo_type, "_code", int_type,
263
2
                            lldb::eAccessPublic, 0);
264
2
  ast->AddFieldToRecordType(ksiginfo_type, "_errno", int_type,
265
2
                            lldb::eAccessPublic, 0);
266
267
  // the structure is padded on 64-bit arches to fix alignment
268
2
  if (triple.isArch64Bit())
269
1
    ast->AddFieldToRecordType(ksiginfo_type, "__pad0", int_type,
270
1
                              lldb::eAccessPublic, 0);
271
272
  // union used to hold the signal data
273
2
  CompilerType union_type = ast->CreateRecordType(
274
2
      nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "",
275
2
      clang::TTK_Union, lldb::eLanguageTypeC);
276
2
  ast->StartTagDeclarationDefinition(union_type);
277
278
2
  ast->AddFieldToRecordType(
279
2
      union_type, "_rt",
280
2
      ast->CreateStructForIdentifier(llvm::StringRef(),
281
2
                                     {
282
2
                                         {"_pid", pid_type},
283
2
                                         {"_uid", uid_type},
284
2
                                         {"_value", sigval_type},
285
2
                                     }),
286
2
      lldb::eAccessPublic, 0);
287
288
2
  ast->AddFieldToRecordType(
289
2
      union_type, "_child",
290
2
      ast->CreateStructForIdentifier(llvm::StringRef(),
291
2
                                     {
292
2
                                         {"_pid", pid_type},
293
2
                                         {"_uid", uid_type},
294
2
                                         {"_status", int_type},
295
2
                                         {"_utime", clock_type},
296
2
                                         {"_stime", clock_type},
297
2
                                     }),
298
2
      lldb::eAccessPublic, 0);
299
300
2
  ast->AddFieldToRecordType(
301
2
      union_type, "_fault",
302
2
      ast->CreateStructForIdentifier(llvm::StringRef(),
303
2
                                     {
304
2
                                         {"_addr", voidp_type},
305
2
                                         {"_trap", int_type},
306
2
                                         {"_trap2", int_type},
307
2
                                         {"_trap3", int_type},
308
2
                                     }),
309
2
      lldb::eAccessPublic, 0);
310
311
2
  ast->AddFieldToRecordType(
312
2
      union_type, "_poll",
313
2
      ast->CreateStructForIdentifier(llvm::StringRef(),
314
2
                                     {
315
2
                                         {"_band", long_type},
316
2
                                         {"_fd", int_type},
317
2
                                     }),
318
2
      lldb::eAccessPublic, 0);
319
320
2
  ast->AddFieldToRecordType(union_type, "_syscall",
321
2
                            ast->CreateStructForIdentifier(
322
2
                                llvm::StringRef(),
323
2
                                {
324
2
                                    {"_sysnum", int_type},
325
2
                                    {"_retval", int_type.GetArrayType(2)},
326
2
                                    {"_error", int_type},
327
2
                                    {"_args", long_long_type.GetArrayType(8)},
328
2
                                }),
329
2
                            lldb::eAccessPublic, 0);
330
331
2
  ast->AddFieldToRecordType(
332
2
      union_type, "_ptrace_state",
333
2
      ast->CreateStructForIdentifier(llvm::StringRef(),
334
2
                                     {
335
2
                                         {"_pe_report_event", int_type},
336
2
                                         {"_option", ptrace_option_type},
337
2
                                     }),
338
2
      lldb::eAccessPublic, 0);
339
340
2
  ast->CompleteTagDeclarationDefinition(union_type);
341
2
  ast->AddFieldToRecordType(ksiginfo_type, "_reason", union_type,
342
2
                            lldb::eAccessPublic, 0);
343
344
2
  ast->CompleteTagDeclarationDefinition(ksiginfo_type);
345
2
  ast->AddFieldToRecordType(siginfo_type, "_info", ksiginfo_type,
346
2
                            lldb::eAccessPublic, 0);
347
348
2
  ast->CompleteTagDeclarationDefinition(siginfo_type);
349
2
  return siginfo_type;
350
2
}