1//===-- ThreadElfCore.h -----------------------------------------*- 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#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H
10#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H
11
12#include "Plugins/Process/elf-core/RegisterUtilities.h"
13#include "lldb/Target/Thread.h"
14#include "lldb/Utility/DataExtractor.h"
15#include "llvm/ADT/DenseMap.h"
16#include <string>
17
18struct compat_timeval {
19  alignas(8) uint64_t tv_sec;
20  alignas(8) uint64_t tv_usec;
21};
22
23// PRSTATUS structure's size differs based on architecture.
24// This is the layout in the x86-64 arch.
25// In the i386 case we parse it manually and fill it again
26// in the same structure
27// The gp registers are also a part of this struct, but they are handled
28// separately
29
30#undef si_signo
31#undef si_code
32#undef si_errno
33
34struct ELFLinuxPrStatus {
35  int32_t si_signo;
36  int32_t si_code;
37  int32_t si_errno;
38
39  int16_t pr_cursig;
40
41  alignas(8) uint64_t pr_sigpend;
42  alignas(8) uint64_t pr_sighold;
43
44  uint32_t pr_pid;
45  uint32_t pr_ppid;
46  uint32_t pr_pgrp;
47  uint32_t pr_sid;
48
49  compat_timeval pr_utime;
50  compat_timeval pr_stime;
51  compat_timeval pr_cutime;
52  compat_timeval pr_cstime;
53
54  ELFLinuxPrStatus();
55
56  lldb_private::Status Parse(const lldb_private::DataExtractor &data,
57                             const lldb_private::ArchSpec &arch);
58
59  // Return the bytesize of the structure
60  // 64 bit - just sizeof
61  // 32 bit - hardcoded because we are reusing the struct, but some of the
62  // members are smaller -
63  // so the layout is not the same
64  static size_t GetSize(const lldb_private::ArchSpec &arch);
65};
66
67static_assert(sizeof(ELFLinuxPrStatus) == 112,
68              "sizeof ELFLinuxPrStatus is not correct!");
69
70struct ELFLinuxSigInfo {
71  int32_t si_signo;
72  int32_t si_code;
73  int32_t si_errno;
74
75  ELFLinuxSigInfo();
76
77  lldb_private::Status Parse(const lldb_private::DataExtractor &data,
78                             const lldb_private::ArchSpec &arch);
79
80  // Return the bytesize of the structure
81  // 64 bit - just sizeof
82  // 32 bit - hardcoded because we are reusing the struct, but some of the
83  // members are smaller -
84  // so the layout is not the same
85  static size_t GetSize(const lldb_private::ArchSpec &arch);
86};
87
88static_assert(sizeof(ELFLinuxSigInfo) == 12,
89              "sizeof ELFLinuxSigInfo is not correct!");
90
91// PRPSINFO structure's size differs based on architecture.
92// This is the layout in the x86-64 arch case.
93// In the i386 case we parse it manually and fill it again
94// in the same structure
95struct ELFLinuxPrPsInfo {
96  char pr_state;
97  char pr_sname;
98  char pr_zomb;
99  char pr_nice;
100  alignas(8) uint64_t pr_flag;
101  uint32_t pr_uid;
102  uint32_t pr_gid;
103  int32_t pr_pid;
104  int32_t pr_ppid;
105  int32_t pr_pgrp;
106  int32_t pr_sid;
107  char pr_fname[16];
108  char pr_psargs[80];
109
110  ELFLinuxPrPsInfo();
111
112  lldb_private::Status Parse(const lldb_private::DataExtractor &data,
113                             const lldb_private::ArchSpec &arch);
114
115  // Return the bytesize of the structure
116  // 64 bit - just sizeof
117  // 32 bit - hardcoded because we are reusing the struct, but some of the
118  // members are smaller -
119  // so the layout is not the same
120  static size_t GetSize(const lldb_private::ArchSpec &arch);
121};
122
123static_assert(sizeof(ELFLinuxPrPsInfo) == 136,
124              "sizeof ELFLinuxPrPsInfo is not correct!");
125
126struct ThreadData {
127  lldb_private::DataExtractor gpregset;
128  std::vector<lldb_private::CoreNote> notes;
129  lldb::tid_t tid;
130  int signo = 0;
131  int prstatus_sig = 0;
132  std::string name;
133};
134
135class ThreadElfCore : public lldb_private::Thread {
136public:
137  ThreadElfCore(lldb_private::Process &process, const ThreadData &td);
138
139  ~ThreadElfCore() override;
140
141  void RefreshStateAfterStop() override;
142
143  lldb::RegisterContextSP GetRegisterContext() override;
144
145  lldb::RegisterContextSP
146  CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
147
148  static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
149
150  const char *GetName() override {
151    if (m_thread_name.empty())
152      return nullptr;
153    return m_thread_name.c_str();
154  }
155
156  void SetName(const char *name) override {
157    if (name && name[0])
158      m_thread_name.assign(name);
159    else
160      m_thread_name.clear();
161  }
162
163protected:
164  // Member variables.
165  std::string m_thread_name;
166  lldb::RegisterContextSP m_thread_reg_ctx_sp;
167
168  int m_signo;
169
170  lldb_private::DataExtractor m_gpregset_data;
171  std::vector<lldb_private::CoreNote> m_notes;
172
173  bool CalculateStopInfo() override;
174};
175
176#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H
177