xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- PlatformLinux.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 "PlatformLinux.h"
10061da546Spatrick #include "lldb/Host/Config.h"
11061da546Spatrick 
12be691f3bSpatrick #include <cstdio>
13061da546Spatrick #if LLDB_ENABLE_POSIX
14061da546Spatrick #include <sys/utsname.h>
15061da546Spatrick #endif
16061da546Spatrick 
17*f6aab3d8Srobert #include "Utility/ARM64_DWARF_Registers.h"
18061da546Spatrick #include "lldb/Core/Debugger.h"
19061da546Spatrick #include "lldb/Core/PluginManager.h"
20061da546Spatrick #include "lldb/Host/HostInfo.h"
21*f6aab3d8Srobert #include "lldb/Symbol/UnwindPlan.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 
31061da546Spatrick // Define these constants from Linux mman.h for use when targeting remote linux
32061da546Spatrick // systems even when host has different values.
33061da546Spatrick #define MAP_PRIVATE 2
34061da546Spatrick #define MAP_ANON 0x20
35061da546Spatrick 
36061da546Spatrick using namespace lldb;
37061da546Spatrick using namespace lldb_private;
38061da546Spatrick using namespace lldb_private::platform_linux;
39061da546Spatrick 
40dda28197Spatrick LLDB_PLUGIN_DEFINE(PlatformLinux)
41dda28197Spatrick 
42061da546Spatrick static uint32_t g_initialize_count = 0;
43061da546Spatrick 
44061da546Spatrick 
CreateInstance(bool force,const ArchSpec * arch)45061da546Spatrick PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) {
46*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Platform);
47061da546Spatrick   LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
48061da546Spatrick            arch ? arch->GetArchitectureName() : "<null>",
49061da546Spatrick            arch ? arch->GetTriple().getTriple() : "<null>");
50061da546Spatrick 
51061da546Spatrick   bool create = force;
52061da546Spatrick   if (!create && arch && arch->IsValid()) {
53061da546Spatrick     const llvm::Triple &triple = arch->GetTriple();
54061da546Spatrick     switch (triple.getOS()) {
55061da546Spatrick     case llvm::Triple::Linux:
56061da546Spatrick       create = true;
57061da546Spatrick       break;
58061da546Spatrick 
59061da546Spatrick #if defined(__linux__)
60061da546Spatrick     // Only accept "unknown" for the OS if the host is linux and it "unknown"
61061da546Spatrick     // wasn't specified (it was just returned because it was NOT specified)
62061da546Spatrick     case llvm::Triple::OSType::UnknownOS:
63061da546Spatrick       create = !arch->TripleOSWasSpecified();
64061da546Spatrick       break;
65061da546Spatrick #endif
66061da546Spatrick     default:
67061da546Spatrick       break;
68061da546Spatrick     }
69061da546Spatrick   }
70061da546Spatrick 
71061da546Spatrick   LLDB_LOG(log, "create = {0}", create);
72061da546Spatrick   if (create) {
73061da546Spatrick     return PlatformSP(new PlatformLinux(false));
74061da546Spatrick   }
75061da546Spatrick   return PlatformSP();
76061da546Spatrick }
77061da546Spatrick 
GetPluginDescriptionStatic(bool is_host)78*f6aab3d8Srobert llvm::StringRef PlatformLinux::GetPluginDescriptionStatic(bool is_host) {
79061da546Spatrick   if (is_host)
80061da546Spatrick     return "Local Linux user platform plug-in.";
81061da546Spatrick   return "Remote Linux user platform plug-in.";
82061da546Spatrick }
83061da546Spatrick 
Initialize()84061da546Spatrick void PlatformLinux::Initialize() {
85061da546Spatrick   PlatformPOSIX::Initialize();
86061da546Spatrick 
87061da546Spatrick   if (g_initialize_count++ == 0) {
88061da546Spatrick #if defined(__linux__) && !defined(__ANDROID__)
89061da546Spatrick     PlatformSP default_platform_sp(new PlatformLinux(true));
90061da546Spatrick     default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
91061da546Spatrick     Platform::SetHostPlatform(default_platform_sp);
92061da546Spatrick #endif
93061da546Spatrick     PluginManager::RegisterPlugin(
94061da546Spatrick         PlatformLinux::GetPluginNameStatic(false),
95061da546Spatrick         PlatformLinux::GetPluginDescriptionStatic(false),
96061da546Spatrick         PlatformLinux::CreateInstance, nullptr);
97061da546Spatrick   }
98061da546Spatrick }
99061da546Spatrick 
Terminate()100061da546Spatrick void PlatformLinux::Terminate() {
101061da546Spatrick   if (g_initialize_count > 0) {
102061da546Spatrick     if (--g_initialize_count == 0) {
103061da546Spatrick       PluginManager::UnregisterPlugin(PlatformLinux::CreateInstance);
104061da546Spatrick     }
105061da546Spatrick   }
106061da546Spatrick 
107061da546Spatrick   PlatformPOSIX::Terminate();
108061da546Spatrick }
109061da546Spatrick 
110061da546Spatrick /// Default Constructor
PlatformLinux(bool is_host)111061da546Spatrick PlatformLinux::PlatformLinux(bool is_host)
112061da546Spatrick     : PlatformPOSIX(is_host) // This is the local host platform
113*f6aab3d8Srobert {
114*f6aab3d8Srobert   if (is_host) {
115061da546Spatrick     ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
116*f6aab3d8Srobert     m_supported_architectures.push_back(hostArch);
117*f6aab3d8Srobert     if (hostArch.GetTriple().isArch64Bit()) {
118*f6aab3d8Srobert       m_supported_architectures.push_back(
119*f6aab3d8Srobert           HostInfo::GetArchitecture(HostInfo::eArchKind32));
120061da546Spatrick     }
121061da546Spatrick   } else {
122*f6aab3d8Srobert     m_supported_architectures = CreateArchList(
123*f6aab3d8Srobert         {llvm::Triple::x86_64, llvm::Triple::x86, llvm::Triple::arm,
124*f6aab3d8Srobert          llvm::Triple::aarch64, llvm::Triple::mips64, llvm::Triple::mips64,
125*f6aab3d8Srobert          llvm::Triple::hexagon, llvm::Triple::mips, llvm::Triple::mips64el,
126*f6aab3d8Srobert          llvm::Triple::mipsel, llvm::Triple::systemz},
127*f6aab3d8Srobert         llvm::Triple::Linux);
128*f6aab3d8Srobert   }
129*f6aab3d8Srobert }
130*f6aab3d8Srobert 
131*f6aab3d8Srobert std::vector<ArchSpec>
GetSupportedArchitectures(const ArchSpec & process_host_arch)132*f6aab3d8Srobert PlatformLinux::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
133061da546Spatrick   if (m_remote_platform_sp)
134*f6aab3d8Srobert     return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch);
135*f6aab3d8Srobert   return m_supported_architectures;
136061da546Spatrick }
137061da546Spatrick 
GetStatus(Stream & strm)138061da546Spatrick void PlatformLinux::GetStatus(Stream &strm) {
139061da546Spatrick   Platform::GetStatus(strm);
140061da546Spatrick 
141061da546Spatrick #if LLDB_ENABLE_POSIX
142061da546Spatrick   // Display local kernel information only when we are running in host mode.
143061da546Spatrick   // Otherwise, we would end up printing non-Linux information (when running on
144061da546Spatrick   // Mac OS for example).
145061da546Spatrick   if (IsHost()) {
146061da546Spatrick     struct utsname un;
147061da546Spatrick 
148061da546Spatrick     if (uname(&un))
149061da546Spatrick       return;
150061da546Spatrick 
151061da546Spatrick     strm.Printf("    Kernel: %s\n", un.sysname);
152061da546Spatrick     strm.Printf("   Release: %s\n", un.release);
153061da546Spatrick     strm.Printf("   Version: %s\n", un.version);
154061da546Spatrick   }
155061da546Spatrick #endif
156061da546Spatrick }
157061da546Spatrick 
158be691f3bSpatrick uint32_t
GetResumeCountForLaunchInfo(ProcessLaunchInfo & launch_info)159061da546Spatrick PlatformLinux::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
160be691f3bSpatrick   uint32_t resume_count = 0;
161061da546Spatrick 
162061da546Spatrick   // Always resume past the initial stop when we use eLaunchFlagDebug
163061da546Spatrick   if (launch_info.GetFlags().Test(eLaunchFlagDebug)) {
164061da546Spatrick     // Resume past the stop for the final exec into the true inferior.
165061da546Spatrick     ++resume_count;
166061da546Spatrick   }
167061da546Spatrick 
168061da546Spatrick   // If we're not launching a shell, we're done.
169061da546Spatrick   const FileSpec &shell = launch_info.GetShell();
170061da546Spatrick   if (!shell)
171061da546Spatrick     return resume_count;
172061da546Spatrick 
173061da546Spatrick   std::string shell_string = shell.GetPath();
174061da546Spatrick   // We're in a shell, so for sure we have to resume past the shell exec.
175061da546Spatrick   ++resume_count;
176061da546Spatrick 
177061da546Spatrick   // Figure out what shell we're planning on using.
178061da546Spatrick   const char *shell_name = strrchr(shell_string.c_str(), '/');
179061da546Spatrick   if (shell_name == nullptr)
180061da546Spatrick     shell_name = shell_string.c_str();
181061da546Spatrick   else
182061da546Spatrick     shell_name++;
183061da546Spatrick 
184061da546Spatrick   if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 ||
185061da546Spatrick       strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) {
186061da546Spatrick     // These shells seem to re-exec themselves.  Add another resume.
187061da546Spatrick     ++resume_count;
188061da546Spatrick   }
189061da546Spatrick 
190061da546Spatrick   return resume_count;
191061da546Spatrick }
192061da546Spatrick 
CanDebugProcess()193061da546Spatrick bool PlatformLinux::CanDebugProcess() {
194061da546Spatrick   if (IsHost()) {
195061da546Spatrick     return true;
196061da546Spatrick   } else {
197061da546Spatrick     // If we're connected, we can debug.
198061da546Spatrick     return IsConnected();
199061da546Spatrick   }
200061da546Spatrick }
201061da546Spatrick 
CalculateTrapHandlerSymbolNames()202061da546Spatrick void PlatformLinux::CalculateTrapHandlerSymbolNames() {
203061da546Spatrick   m_trap_handlers.push_back(ConstString("_sigtramp"));
204061da546Spatrick   m_trap_handlers.push_back(ConstString("__kernel_rt_sigreturn"));
205061da546Spatrick   m_trap_handlers.push_back(ConstString("__restore_rt"));
206061da546Spatrick }
207061da546Spatrick 
GetAArch64TrapHanlderUnwindPlan(ConstString name)208*f6aab3d8Srobert static lldb::UnwindPlanSP GetAArch64TrapHanlderUnwindPlan(ConstString name) {
209*f6aab3d8Srobert   UnwindPlanSP unwind_plan_sp;
210*f6aab3d8Srobert   if (name != "__kernel_rt_sigreturn")
211*f6aab3d8Srobert     return unwind_plan_sp;
212*f6aab3d8Srobert 
213*f6aab3d8Srobert   UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>();
214*f6aab3d8Srobert   row->SetOffset(0);
215*f6aab3d8Srobert 
216*f6aab3d8Srobert   // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
217*f6aab3d8Srobert   //  - 128-byte siginfo struct
218*f6aab3d8Srobert   //  - ucontext struct:
219*f6aab3d8Srobert   //     - 8-byte long (uc_flags)
220*f6aab3d8Srobert   //     - 8-byte pointer (uc_link)
221*f6aab3d8Srobert   //     - 24-byte stack_t
222*f6aab3d8Srobert   //     - 128-byte signal set
223*f6aab3d8Srobert   //     - 8 bytes of padding because sigcontext has 16-byte alignment
224*f6aab3d8Srobert   //     - sigcontext/mcontext_t
225*f6aab3d8Srobert   // [1]
226*f6aab3d8Srobert   // https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c
227*f6aab3d8Srobert   int32_t offset = 128 + 8 + 8 + 24 + 128 + 8;
228*f6aab3d8Srobert   // Then sigcontext[2] is:
229*f6aab3d8Srobert   // - 8 byte fault address
230*f6aab3d8Srobert   // - 31 8 byte registers
231*f6aab3d8Srobert   // - 8 byte sp
232*f6aab3d8Srobert   // - 8 byte pc
233*f6aab3d8Srobert   // [2]
234*f6aab3d8Srobert   // https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/sigcontext.h
235*f6aab3d8Srobert 
236*f6aab3d8Srobert   // Skip fault address
237*f6aab3d8Srobert   offset += 8;
238*f6aab3d8Srobert   row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, offset);
239*f6aab3d8Srobert 
240*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x0, 0 * 8, false);
241*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x1, 1 * 8, false);
242*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x2, 2 * 8, false);
243*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x3, 3 * 8, false);
244*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x4, 4 * 8, false);
245*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x5, 5 * 8, false);
246*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x6, 6 * 8, false);
247*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x7, 7 * 8, false);
248*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x8, 8 * 8, false);
249*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x9, 9 * 8, false);
250*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x10, 10 * 8, false);
251*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x11, 11 * 8, false);
252*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x12, 12 * 8, false);
253*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x13, 13 * 8, false);
254*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x14, 14 * 8, false);
255*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x15, 15 * 8, false);
256*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x16, 16 * 8, false);
257*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x17, 17 * 8, false);
258*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x18, 18 * 8, false);
259*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x19, 19 * 8, false);
260*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x20, 20 * 8, false);
261*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x21, 21 * 8, false);
262*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x22, 22 * 8, false);
263*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x23, 23 * 8, false);
264*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x24, 24 * 8, false);
265*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x25, 25 * 8, false);
266*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x26, 26 * 8, false);
267*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x27, 27 * 8, false);
268*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x28, 28 * 8, false);
269*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::fp, 29 * 8, false);
270*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::x30, 30 * 8, false);
271*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::sp, 31 * 8, false);
272*f6aab3d8Srobert   row->SetRegisterLocationToAtCFAPlusOffset(arm64_dwarf::pc, 32 * 8, false);
273*f6aab3d8Srobert 
274*f6aab3d8Srobert   // The sigcontext may also contain floating point and SVE registers.
275*f6aab3d8Srobert   // However this would require a dynamic unwind plan so they are not included
276*f6aab3d8Srobert   // here.
277*f6aab3d8Srobert 
278*f6aab3d8Srobert   unwind_plan_sp = std::make_shared<UnwindPlan>(eRegisterKindDWARF);
279*f6aab3d8Srobert   unwind_plan_sp->AppendRow(row);
280*f6aab3d8Srobert   unwind_plan_sp->SetSourceName("AArch64 Linux sigcontext");
281*f6aab3d8Srobert   unwind_plan_sp->SetSourcedFromCompiler(eLazyBoolYes);
282*f6aab3d8Srobert   // Because sp is the same throughout the function
283*f6aab3d8Srobert   unwind_plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
284*f6aab3d8Srobert   unwind_plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolYes);
285*f6aab3d8Srobert 
286*f6aab3d8Srobert   return unwind_plan_sp;
287*f6aab3d8Srobert }
288*f6aab3d8Srobert 
289*f6aab3d8Srobert lldb::UnwindPlanSP
GetTrapHandlerUnwindPlan(const llvm::Triple & triple,ConstString name)290*f6aab3d8Srobert PlatformLinux::GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
291*f6aab3d8Srobert                                         ConstString name) {
292*f6aab3d8Srobert   if (triple.isAArch64())
293*f6aab3d8Srobert     return GetAArch64TrapHanlderUnwindPlan(name);
294*f6aab3d8Srobert 
295*f6aab3d8Srobert   return {};
296*f6aab3d8Srobert }
297*f6aab3d8Srobert 
GetMmapArgumentList(const ArchSpec & arch,addr_t addr,addr_t length,unsigned prot,unsigned flags,addr_t fd,addr_t offset)298061da546Spatrick MmapArgList PlatformLinux::GetMmapArgumentList(const ArchSpec &arch,
299061da546Spatrick                                                addr_t addr, addr_t length,
300061da546Spatrick                                                unsigned prot, unsigned flags,
301061da546Spatrick                                                addr_t fd, addr_t offset) {
302061da546Spatrick   uint64_t flags_platform = 0;
303061da546Spatrick   uint64_t map_anon = arch.IsMIPS() ? 0x800 : MAP_ANON;
304061da546Spatrick 
305061da546Spatrick   if (flags & eMmapFlagsPrivate)
306061da546Spatrick     flags_platform |= MAP_PRIVATE;
307061da546Spatrick   if (flags & eMmapFlagsAnon)
308061da546Spatrick     flags_platform |= map_anon;
309061da546Spatrick 
310061da546Spatrick   MmapArgList args({addr, length, prot, flags_platform, fd, offset});
311061da546Spatrick   return args;
312061da546Spatrick }
313061da546Spatrick 
GetSiginfoType(const llvm::Triple & triple)314*f6aab3d8Srobert CompilerType PlatformLinux::GetSiginfoType(const llvm::Triple &triple) {
315*f6aab3d8Srobert   {
316*f6aab3d8Srobert     std::lock_guard<std::mutex> guard(m_mutex);
317*f6aab3d8Srobert     if (!m_type_system)
318*f6aab3d8Srobert       m_type_system = std::make_shared<TypeSystemClang>("siginfo", triple);
319*f6aab3d8Srobert   }
320*f6aab3d8Srobert   TypeSystemClang *ast = m_type_system.get();
321*f6aab3d8Srobert 
322*f6aab3d8Srobert   bool si_errno_then_code = true;
323*f6aab3d8Srobert 
324*f6aab3d8Srobert   switch (triple.getArch()) {
325*f6aab3d8Srobert   case llvm::Triple::mips:
326*f6aab3d8Srobert   case llvm::Triple::mipsel:
327*f6aab3d8Srobert   case llvm::Triple::mips64:
328*f6aab3d8Srobert   case llvm::Triple::mips64el:
329*f6aab3d8Srobert     // mips has si_code and si_errno swapped
330*f6aab3d8Srobert     si_errno_then_code = false;
331*f6aab3d8Srobert     break;
332*f6aab3d8Srobert   default:
333*f6aab3d8Srobert     break;
334*f6aab3d8Srobert   }
335*f6aab3d8Srobert 
336*f6aab3d8Srobert   // generic types
337*f6aab3d8Srobert   CompilerType int_type = ast->GetBasicType(eBasicTypeInt);
338*f6aab3d8Srobert   CompilerType uint_type = ast->GetBasicType(eBasicTypeUnsignedInt);
339*f6aab3d8Srobert   CompilerType short_type = ast->GetBasicType(eBasicTypeShort);
340*f6aab3d8Srobert   CompilerType long_type = ast->GetBasicType(eBasicTypeLong);
341*f6aab3d8Srobert   CompilerType voidp_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
342*f6aab3d8Srobert 
343*f6aab3d8Srobert   // platform-specific types
344*f6aab3d8Srobert   CompilerType &pid_type = int_type;
345*f6aab3d8Srobert   CompilerType &uid_type = uint_type;
346*f6aab3d8Srobert   CompilerType &clock_type = long_type;
347*f6aab3d8Srobert   CompilerType &band_type = long_type;
348*f6aab3d8Srobert 
349*f6aab3d8Srobert   CompilerType sigval_type = ast->CreateRecordType(
350*f6aab3d8Srobert       nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_sigval_t",
351*f6aab3d8Srobert       clang::TTK_Union, lldb::eLanguageTypeC);
352*f6aab3d8Srobert   ast->StartTagDeclarationDefinition(sigval_type);
353*f6aab3d8Srobert   ast->AddFieldToRecordType(sigval_type, "sival_int", int_type,
354*f6aab3d8Srobert                             lldb::eAccessPublic, 0);
355*f6aab3d8Srobert   ast->AddFieldToRecordType(sigval_type, "sival_ptr", voidp_type,
356*f6aab3d8Srobert                             lldb::eAccessPublic, 0);
357*f6aab3d8Srobert   ast->CompleteTagDeclarationDefinition(sigval_type);
358*f6aab3d8Srobert 
359*f6aab3d8Srobert   CompilerType sigfault_bounds_type = ast->CreateRecordType(
360*f6aab3d8Srobert       nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "",
361*f6aab3d8Srobert       clang::TTK_Union, lldb::eLanguageTypeC);
362*f6aab3d8Srobert   ast->StartTagDeclarationDefinition(sigfault_bounds_type);
363*f6aab3d8Srobert   ast->AddFieldToRecordType(sigfault_bounds_type, "_addr_bnd",
364*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
365*f6aab3d8Srobert                                      {
366*f6aab3d8Srobert                                          {"_lower", voidp_type},
367*f6aab3d8Srobert                                          {"_upper", voidp_type},
368*f6aab3d8Srobert                                      }),
369*f6aab3d8Srobert                             lldb::eAccessPublic, 0);
370*f6aab3d8Srobert   ast->AddFieldToRecordType(sigfault_bounds_type, "_pkey", uint_type,
371*f6aab3d8Srobert                             lldb::eAccessPublic, 0);
372*f6aab3d8Srobert   ast->CompleteTagDeclarationDefinition(sigfault_bounds_type);
373*f6aab3d8Srobert 
374*f6aab3d8Srobert   // siginfo_t
375*f6aab3d8Srobert   CompilerType siginfo_type = ast->CreateRecordType(
376*f6aab3d8Srobert       nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "__lldb_siginfo_t",
377*f6aab3d8Srobert       clang::TTK_Struct, lldb::eLanguageTypeC);
378*f6aab3d8Srobert   ast->StartTagDeclarationDefinition(siginfo_type);
379*f6aab3d8Srobert   ast->AddFieldToRecordType(siginfo_type, "si_signo", int_type,
380*f6aab3d8Srobert                             lldb::eAccessPublic, 0);
381*f6aab3d8Srobert 
382*f6aab3d8Srobert   if (si_errno_then_code) {
383*f6aab3d8Srobert     ast->AddFieldToRecordType(siginfo_type, "si_errno", int_type,
384*f6aab3d8Srobert                               lldb::eAccessPublic, 0);
385*f6aab3d8Srobert     ast->AddFieldToRecordType(siginfo_type, "si_code", int_type,
386*f6aab3d8Srobert                               lldb::eAccessPublic, 0);
387*f6aab3d8Srobert   } else {
388*f6aab3d8Srobert     ast->AddFieldToRecordType(siginfo_type, "si_code", int_type,
389*f6aab3d8Srobert                               lldb::eAccessPublic, 0);
390*f6aab3d8Srobert     ast->AddFieldToRecordType(siginfo_type, "si_errno", int_type,
391*f6aab3d8Srobert                               lldb::eAccessPublic, 0);
392*f6aab3d8Srobert   }
393*f6aab3d8Srobert 
394*f6aab3d8Srobert   // the structure is padded on 64-bit arches to fix alignment
395*f6aab3d8Srobert   if (triple.isArch64Bit())
396*f6aab3d8Srobert     ast->AddFieldToRecordType(siginfo_type, "__pad0", int_type,
397*f6aab3d8Srobert                               lldb::eAccessPublic, 0);
398*f6aab3d8Srobert 
399*f6aab3d8Srobert   // union used to hold the signal data
400*f6aab3d8Srobert   CompilerType union_type = ast->CreateRecordType(
401*f6aab3d8Srobert       nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "",
402*f6aab3d8Srobert       clang::TTK_Union, lldb::eLanguageTypeC);
403*f6aab3d8Srobert   ast->StartTagDeclarationDefinition(union_type);
404*f6aab3d8Srobert 
405*f6aab3d8Srobert   ast->AddFieldToRecordType(
406*f6aab3d8Srobert       union_type, "_kill",
407*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
408*f6aab3d8Srobert                                      {
409*f6aab3d8Srobert                                          {"si_pid", pid_type},
410*f6aab3d8Srobert                                          {"si_uid", uid_type},
411*f6aab3d8Srobert                                      }),
412*f6aab3d8Srobert       lldb::eAccessPublic, 0);
413*f6aab3d8Srobert 
414*f6aab3d8Srobert   ast->AddFieldToRecordType(
415*f6aab3d8Srobert       union_type, "_timer",
416*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
417*f6aab3d8Srobert                                      {
418*f6aab3d8Srobert                                          {"si_tid", int_type},
419*f6aab3d8Srobert                                          {"si_overrun", int_type},
420*f6aab3d8Srobert                                          {"si_sigval", sigval_type},
421*f6aab3d8Srobert                                      }),
422*f6aab3d8Srobert       lldb::eAccessPublic, 0);
423*f6aab3d8Srobert 
424*f6aab3d8Srobert   ast->AddFieldToRecordType(
425*f6aab3d8Srobert       union_type, "_rt",
426*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
427*f6aab3d8Srobert                                      {
428*f6aab3d8Srobert                                          {"si_pid", pid_type},
429*f6aab3d8Srobert                                          {"si_uid", uid_type},
430*f6aab3d8Srobert                                          {"si_sigval", sigval_type},
431*f6aab3d8Srobert                                      }),
432*f6aab3d8Srobert       lldb::eAccessPublic, 0);
433*f6aab3d8Srobert 
434*f6aab3d8Srobert   ast->AddFieldToRecordType(
435*f6aab3d8Srobert       union_type, "_sigchld",
436*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
437*f6aab3d8Srobert                                      {
438*f6aab3d8Srobert                                          {"si_pid", pid_type},
439*f6aab3d8Srobert                                          {"si_uid", uid_type},
440*f6aab3d8Srobert                                          {"si_status", int_type},
441*f6aab3d8Srobert                                          {"si_utime", clock_type},
442*f6aab3d8Srobert                                          {"si_stime", clock_type},
443*f6aab3d8Srobert                                      }),
444*f6aab3d8Srobert       lldb::eAccessPublic, 0);
445*f6aab3d8Srobert 
446*f6aab3d8Srobert   ast->AddFieldToRecordType(
447*f6aab3d8Srobert       union_type, "_sigfault",
448*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
449*f6aab3d8Srobert                                      {
450*f6aab3d8Srobert                                          {"si_addr", voidp_type},
451*f6aab3d8Srobert                                          {"si_addr_lsb", short_type},
452*f6aab3d8Srobert                                          {"_bounds", sigfault_bounds_type},
453*f6aab3d8Srobert                                      }),
454*f6aab3d8Srobert       lldb::eAccessPublic, 0);
455*f6aab3d8Srobert 
456*f6aab3d8Srobert   ast->AddFieldToRecordType(
457*f6aab3d8Srobert       union_type, "_sigpoll",
458*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
459*f6aab3d8Srobert                                      {
460*f6aab3d8Srobert                                          {"si_band", band_type},
461*f6aab3d8Srobert                                          {"si_fd", int_type},
462*f6aab3d8Srobert                                      }),
463*f6aab3d8Srobert       lldb::eAccessPublic, 0);
464*f6aab3d8Srobert 
465*f6aab3d8Srobert   // NB: SIGSYS is not present on ia64 but we don't seem to support that
466*f6aab3d8Srobert   ast->AddFieldToRecordType(
467*f6aab3d8Srobert       union_type, "_sigsys",
468*f6aab3d8Srobert       ast->CreateStructForIdentifier(ConstString(),
469*f6aab3d8Srobert                                      {
470*f6aab3d8Srobert                                          {"_call_addr", voidp_type},
471*f6aab3d8Srobert                                          {"_syscall", int_type},
472*f6aab3d8Srobert                                          {"_arch", uint_type},
473*f6aab3d8Srobert                                      }),
474*f6aab3d8Srobert       lldb::eAccessPublic, 0);
475*f6aab3d8Srobert 
476*f6aab3d8Srobert   ast->CompleteTagDeclarationDefinition(union_type);
477*f6aab3d8Srobert   ast->AddFieldToRecordType(siginfo_type, "_sifields", union_type,
478*f6aab3d8Srobert                             lldb::eAccessPublic, 0);
479*f6aab3d8Srobert 
480*f6aab3d8Srobert   ast->CompleteTagDeclarationDefinition(siginfo_type);
481*f6aab3d8Srobert   return siginfo_type;
482*f6aab3d8Srobert }
483