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 | |
18 | struct 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 | |
34 | struct 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 (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 | |
67 | static_assert(sizeof(ELFLinuxPrStatus) == 112, |
68 | "sizeof ELFLinuxPrStatus is not correct!" ); |
69 | |
70 | struct ELFLinuxSigInfo { |
71 | int32_t si_signo; |
72 | int32_t si_code; |
73 | int32_t si_errno; |
74 | |
75 | ELFLinuxSigInfo(); |
76 | |
77 | lldb_private::Status (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 | |
88 | static_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 |
95 | struct 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 (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 | |
123 | static_assert(sizeof(ELFLinuxPrPsInfo) == 136, |
124 | "sizeof ELFLinuxPrPsInfo is not correct!" ); |
125 | |
126 | struct ThreadData { |
127 | lldb_private::DataExtractor gpregset; |
128 | std::vector<lldb_private::CoreNote> notes; |
129 | lldb::tid_t tid; |
130 | int signo = 0; |
131 | int code = 0; |
132 | int prstatus_sig = 0; |
133 | std::string name; |
134 | }; |
135 | |
136 | class ThreadElfCore : public lldb_private::Thread { |
137 | public: |
138 | ThreadElfCore(lldb_private::Process &process, const ThreadData &td); |
139 | |
140 | ~ThreadElfCore() override; |
141 | |
142 | void RefreshStateAfterStop() override; |
143 | |
144 | lldb::RegisterContextSP GetRegisterContext() override; |
145 | |
146 | lldb::RegisterContextSP |
147 | CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; |
148 | |
149 | static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } |
150 | |
151 | const char *GetName() override { |
152 | if (m_thread_name.empty()) |
153 | return nullptr; |
154 | return m_thread_name.c_str(); |
155 | } |
156 | |
157 | void SetName(const char *name) override { |
158 | if (name && name[0]) |
159 | m_thread_name.assign(s: name); |
160 | else |
161 | m_thread_name.clear(); |
162 | } |
163 | |
164 | protected: |
165 | // Member variables. |
166 | std::string m_thread_name; |
167 | lldb::RegisterContextSP m_thread_reg_ctx_sp; |
168 | |
169 | int m_signo; |
170 | int m_code; |
171 | |
172 | lldb_private::DataExtractor m_gpregset_data; |
173 | std::vector<lldb_private::CoreNote> m_notes; |
174 | |
175 | bool CalculateStopInfo() override; |
176 | }; |
177 | |
178 | #endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_THREADELFCORE_H |
179 | |