1dda28197Spatrick //===-- PlatformFreeBSD.cpp -----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "PlatformFreeBSD.h"
10061da546Spatrick #include "lldb/Host/Config.h"
11061da546Spatrick
12be691f3bSpatrick #include <cstdio>
13061da546Spatrick #if LLDB_ENABLE_POSIX
14061da546Spatrick #include <sys/utsname.h>
15061da546Spatrick #endif
16061da546Spatrick
17061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
18061da546Spatrick #include "lldb/Breakpoint/BreakpointSite.h"
19061da546Spatrick #include "lldb/Core/Debugger.h"
20061da546Spatrick #include "lldb/Core/PluginManager.h"
21061da546Spatrick #include "lldb/Host/HostInfo.h"
22061da546Spatrick #include "lldb/Target/Process.h"
23061da546Spatrick #include "lldb/Target/Target.h"
24061da546Spatrick #include "lldb/Utility/FileSpec.h"
25*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
26061da546Spatrick #include "lldb/Utility/Log.h"
27061da546Spatrick #include "lldb/Utility/State.h"
28061da546Spatrick #include "lldb/Utility/Status.h"
29061da546Spatrick #include "lldb/Utility/StreamString.h"
30061da546Spatrick
31be691f3bSpatrick #include "llvm/ADT/Triple.h"
32be691f3bSpatrick #include "llvm/Support/Host.h"
33be691f3bSpatrick
34061da546Spatrick // Define these constants from FreeBSD mman.h for use when targeting remote
35061da546Spatrick // FreeBSD systems even when host has different values.
36061da546Spatrick #define MAP_PRIVATE 0x0002
37061da546Spatrick #define MAP_ANON 0x1000
38061da546Spatrick
39061da546Spatrick using namespace lldb;
40061da546Spatrick using namespace lldb_private;
41061da546Spatrick using namespace lldb_private::platform_freebsd;
42061da546Spatrick
43dda28197Spatrick LLDB_PLUGIN_DEFINE(PlatformFreeBSD)
44dda28197Spatrick
45061da546Spatrick static uint32_t g_initialize_count = 0;
46061da546Spatrick
47061da546Spatrick
CreateInstance(bool force,const ArchSpec * arch)48061da546Spatrick PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) {
49*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Platform);
50061da546Spatrick LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
51061da546Spatrick arch ? arch->GetArchitectureName() : "<null>",
52061da546Spatrick arch ? arch->GetTriple().getTriple() : "<null>");
53061da546Spatrick
54061da546Spatrick bool create = force;
55061da546Spatrick if (!create && arch && arch->IsValid()) {
56061da546Spatrick const llvm::Triple &triple = arch->GetTriple();
57061da546Spatrick switch (triple.getOS()) {
58061da546Spatrick case llvm::Triple::FreeBSD:
59061da546Spatrick create = true;
60061da546Spatrick break;
61061da546Spatrick
62061da546Spatrick #if defined(__FreeBSD__)
63061da546Spatrick // Only accept "unknown" for the OS if the host is BSD and it "unknown"
64061da546Spatrick // wasn't specified (it was just returned because it was NOT specified)
65061da546Spatrick case llvm::Triple::OSType::UnknownOS:
66061da546Spatrick create = !arch->TripleOSWasSpecified();
67061da546Spatrick break;
68061da546Spatrick #endif
69061da546Spatrick default:
70061da546Spatrick break;
71061da546Spatrick }
72061da546Spatrick }
73061da546Spatrick LLDB_LOG(log, "create = {0}", create);
74061da546Spatrick if (create) {
75061da546Spatrick return PlatformSP(new PlatformFreeBSD(false));
76061da546Spatrick }
77061da546Spatrick return PlatformSP();
78061da546Spatrick }
79061da546Spatrick
GetPluginDescriptionStatic(bool is_host)80*f6aab3d8Srobert llvm::StringRef PlatformFreeBSD::GetPluginDescriptionStatic(bool is_host) {
81061da546Spatrick if (is_host)
82061da546Spatrick return "Local FreeBSD user platform plug-in.";
83061da546Spatrick return "Remote FreeBSD user platform plug-in.";
84061da546Spatrick }
85061da546Spatrick
Initialize()86061da546Spatrick void PlatformFreeBSD::Initialize() {
87061da546Spatrick Platform::Initialize();
88061da546Spatrick
89061da546Spatrick if (g_initialize_count++ == 0) {
90061da546Spatrick #if defined(__FreeBSD__)
91061da546Spatrick PlatformSP default_platform_sp(new PlatformFreeBSD(true));
92061da546Spatrick default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
93061da546Spatrick Platform::SetHostPlatform(default_platform_sp);
94061da546Spatrick #endif
95061da546Spatrick PluginManager::RegisterPlugin(
96061da546Spatrick PlatformFreeBSD::GetPluginNameStatic(false),
97061da546Spatrick PlatformFreeBSD::GetPluginDescriptionStatic(false),
98061da546Spatrick PlatformFreeBSD::CreateInstance, nullptr);
99061da546Spatrick }
100061da546Spatrick }
101061da546Spatrick
Terminate()102061da546Spatrick void PlatformFreeBSD::Terminate() {
103061da546Spatrick if (g_initialize_count > 0) {
104061da546Spatrick if (--g_initialize_count == 0) {
105061da546Spatrick PluginManager::UnregisterPlugin(PlatformFreeBSD::CreateInstance);
106061da546Spatrick }
107061da546Spatrick }
108061da546Spatrick
109061da546Spatrick PlatformPOSIX::Terminate();
110061da546Spatrick }
111061da546Spatrick
112061da546Spatrick /// Default Constructor
PlatformFreeBSD(bool is_host)113061da546Spatrick PlatformFreeBSD::PlatformFreeBSD(bool is_host)
114061da546Spatrick : PlatformPOSIX(is_host) // This is the local host platform
115*f6aab3d8Srobert {
116*f6aab3d8Srobert if (is_host) {
117061da546Spatrick ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
118*f6aab3d8Srobert m_supported_architectures.push_back(hostArch);
119*f6aab3d8Srobert if (hostArch.GetTriple().isArch64Bit()) {
120*f6aab3d8Srobert m_supported_architectures.push_back(
121*f6aab3d8Srobert HostInfo::GetArchitecture(HostInfo::eArchKind32));
122061da546Spatrick }
123061da546Spatrick } else {
124*f6aab3d8Srobert m_supported_architectures = CreateArchList(
125*f6aab3d8Srobert {llvm::Triple::x86_64, llvm::Triple::x86, llvm::Triple::aarch64,
126*f6aab3d8Srobert llvm::Triple::arm, llvm::Triple::mips64, llvm::Triple::ppc64,
127*f6aab3d8Srobert llvm::Triple::ppc},
128*f6aab3d8Srobert llvm::Triple::FreeBSD);
129*f6aab3d8Srobert }
130*f6aab3d8Srobert }
131*f6aab3d8Srobert
132*f6aab3d8Srobert std::vector<ArchSpec>
GetSupportedArchitectures(const ArchSpec & process_host_arch)133*f6aab3d8Srobert PlatformFreeBSD::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
134061da546Spatrick if (m_remote_platform_sp)
135*f6aab3d8Srobert return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch);
136*f6aab3d8Srobert return m_supported_architectures;
137061da546Spatrick }
138061da546Spatrick
GetStatus(Stream & strm)139061da546Spatrick void PlatformFreeBSD::GetStatus(Stream &strm) {
140061da546Spatrick Platform::GetStatus(strm);
141061da546Spatrick
142061da546Spatrick #if LLDB_ENABLE_POSIX
143061da546Spatrick // Display local kernel information only when we are running in host mode.
144061da546Spatrick // Otherwise, we would end up printing non-FreeBSD information (when running
145061da546Spatrick // on Mac OS for example).
146061da546Spatrick if (IsHost()) {
147061da546Spatrick struct utsname un;
148061da546Spatrick
149061da546Spatrick if (uname(&un))
150061da546Spatrick return;
151061da546Spatrick
152061da546Spatrick strm.Printf(" Kernel: %s\n", un.sysname);
153061da546Spatrick strm.Printf(" Release: %s\n", un.release);
154061da546Spatrick strm.Printf(" Version: %s\n", un.version);
155061da546Spatrick }
156061da546Spatrick #endif
157061da546Spatrick }
158061da546Spatrick
CanDebugProcess()159061da546Spatrick bool PlatformFreeBSD::CanDebugProcess() {
160be691f3bSpatrick if (IsHost()) {
161be691f3bSpatrick return true;
162be691f3bSpatrick } else {
163be691f3bSpatrick // If we're connected, we can debug.
164be691f3bSpatrick return IsConnected();
165be691f3bSpatrick }
166061da546Spatrick }
167061da546Spatrick
CalculateTrapHandlerSymbolNames()168061da546Spatrick void PlatformFreeBSD::CalculateTrapHandlerSymbolNames() {
169061da546Spatrick m_trap_handlers.push_back(ConstString("_sigtramp"));
170061da546Spatrick }
171061da546Spatrick
GetMmapArgumentList(const ArchSpec & arch,addr_t addr,addr_t length,unsigned prot,unsigned flags,addr_t fd,addr_t offset)172061da546Spatrick MmapArgList PlatformFreeBSD::GetMmapArgumentList(const ArchSpec &arch,
173061da546Spatrick addr_t addr, addr_t length,
174061da546Spatrick unsigned prot, unsigned flags,
175061da546Spatrick addr_t fd, addr_t offset) {
176061da546Spatrick uint64_t flags_platform = 0;
177061da546Spatrick
178061da546Spatrick if (flags & eMmapFlagsPrivate)
179061da546Spatrick flags_platform |= MAP_PRIVATE;
180061da546Spatrick if (flags & eMmapFlagsAnon)
181061da546Spatrick flags_platform |= MAP_ANON;
182061da546Spatrick
183061da546Spatrick MmapArgList args({addr, length, prot, flags_platform, fd, offset});
184061da546Spatrick if (arch.GetTriple().getArch() == llvm::Triple::x86)
185061da546Spatrick args.push_back(0);
186061da546Spatrick return args;
187061da546Spatrick }
188*f6aab3d8Srobert
GetSiginfoType(const llvm::Triple & triple)189*f6aab3d8Srobert CompilerType PlatformFreeBSD::GetSiginfoType(const llvm::Triple &triple) {
190*f6aab3d8Srobert {
191*f6aab3d8Srobert std::lock_guard<std::mutex> guard(m_mutex);
192*f6aab3d8Srobert if (!m_type_system)
193*f6aab3d8Srobert m_type_system = std::make_shared<TypeSystemClang>("siginfo", triple);
194*f6aab3d8Srobert }
195*f6aab3d8Srobert TypeSystemClang *ast = m_type_system.get();
196*f6aab3d8Srobert
197*f6aab3d8Srobert // generic types
198*f6aab3d8Srobert CompilerType int_type = ast->GetBasicType(eBasicTypeInt);
199*f6aab3d8Srobert CompilerType uint_type = ast->GetBasicType(eBasicTypeUnsignedInt);
200*f6aab3d8Srobert CompilerType long_type = ast->GetBasicType(eBasicTypeLong);
201*f6aab3d8Srobert CompilerType voidp_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
202*f6aab3d8Srobert
203*f6aab3d8Srobert // platform-specific types
204*f6aab3d8Srobert CompilerType &pid_type = int_type;
205*f6aab3d8Srobert CompilerType &uid_type = uint_type;
206*f6aab3d8Srobert
207*f6aab3d8Srobert CompilerType sigval_type = ast->CreateRecordType(
208*f6aab3d8Srobert nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t",
209*f6aab3d8Srobert clang::TTK_Union, lldb::eLanguageTypeC);
210*f6aab3d8Srobert ast->StartTagDeclarationDefinition(sigval_type);
211*f6aab3d8Srobert ast->AddFieldToRecordType(sigval_type, "sival_int", int_type,
212*f6aab3d8Srobert lldb::eAccessPublic, 0);
213*f6aab3d8Srobert ast->AddFieldToRecordType(sigval_type, "sival_ptr", voidp_type,
214*f6aab3d8Srobert lldb::eAccessPublic, 0);
215*f6aab3d8Srobert ast->CompleteTagDeclarationDefinition(sigval_type);
216*f6aab3d8Srobert
217*f6aab3d8Srobert // siginfo_t
218*f6aab3d8Srobert CompilerType siginfo_type = ast->CreateRecordType(
219*f6aab3d8Srobert nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t",
220*f6aab3d8Srobert clang::TTK_Struct, lldb::eLanguageTypeC);
221*f6aab3d8Srobert ast->StartTagDeclarationDefinition(siginfo_type);
222*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_signo", int_type,
223*f6aab3d8Srobert lldb::eAccessPublic, 0);
224*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_errno", int_type,
225*f6aab3d8Srobert lldb::eAccessPublic, 0);
226*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_code", int_type,
227*f6aab3d8Srobert lldb::eAccessPublic, 0);
228*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_pid", pid_type,
229*f6aab3d8Srobert lldb::eAccessPublic, 0);
230*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_uid", uid_type,
231*f6aab3d8Srobert lldb::eAccessPublic, 0);
232*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_status", int_type,
233*f6aab3d8Srobert lldb::eAccessPublic, 0);
234*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_addr", voidp_type,
235*f6aab3d8Srobert lldb::eAccessPublic, 0);
236*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "si_value", sigval_type,
237*f6aab3d8Srobert lldb::eAccessPublic, 0);
238*f6aab3d8Srobert
239*f6aab3d8Srobert // union used to hold the signal data
240*f6aab3d8Srobert CompilerType union_type = ast->CreateRecordType(
241*f6aab3d8Srobert nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "",
242*f6aab3d8Srobert clang::TTK_Union, lldb::eLanguageTypeC);
243*f6aab3d8Srobert ast->StartTagDeclarationDefinition(union_type);
244*f6aab3d8Srobert
245*f6aab3d8Srobert ast->AddFieldToRecordType(
246*f6aab3d8Srobert union_type, "_fault",
247*f6aab3d8Srobert ast->CreateStructForIdentifier(ConstString(),
248*f6aab3d8Srobert {
249*f6aab3d8Srobert {"_trapno", int_type},
250*f6aab3d8Srobert }),
251*f6aab3d8Srobert lldb::eAccessPublic, 0);
252*f6aab3d8Srobert
253*f6aab3d8Srobert ast->AddFieldToRecordType(
254*f6aab3d8Srobert union_type, "_timer",
255*f6aab3d8Srobert ast->CreateStructForIdentifier(ConstString(),
256*f6aab3d8Srobert {
257*f6aab3d8Srobert {"_timerid", int_type},
258*f6aab3d8Srobert {"_overrun", int_type},
259*f6aab3d8Srobert }),
260*f6aab3d8Srobert lldb::eAccessPublic, 0);
261*f6aab3d8Srobert
262*f6aab3d8Srobert ast->AddFieldToRecordType(
263*f6aab3d8Srobert union_type, "_mesgq",
264*f6aab3d8Srobert ast->CreateStructForIdentifier(ConstString(),
265*f6aab3d8Srobert {
266*f6aab3d8Srobert {"_mqd", int_type},
267*f6aab3d8Srobert }),
268*f6aab3d8Srobert lldb::eAccessPublic, 0);
269*f6aab3d8Srobert
270*f6aab3d8Srobert ast->AddFieldToRecordType(
271*f6aab3d8Srobert union_type, "_poll",
272*f6aab3d8Srobert ast->CreateStructForIdentifier(ConstString(),
273*f6aab3d8Srobert {
274*f6aab3d8Srobert {"_band", long_type},
275*f6aab3d8Srobert }),
276*f6aab3d8Srobert lldb::eAccessPublic, 0);
277*f6aab3d8Srobert
278*f6aab3d8Srobert ast->CompleteTagDeclarationDefinition(union_type);
279*f6aab3d8Srobert ast->AddFieldToRecordType(siginfo_type, "_reason", union_type,
280*f6aab3d8Srobert lldb::eAccessPublic, 0);
281*f6aab3d8Srobert
282*f6aab3d8Srobert ast->CompleteTagDeclarationDefinition(siginfo_type);
283*f6aab3d8Srobert return siginfo_type;
284*f6aab3d8Srobert }
285