Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
213845 views
1
//===-- NativeProcessAIX.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 "NativeProcessAIX.h"
10
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
11
#include "lldb/Host/Host.h"
12
#include "lldb/Host/HostInfo.h"
13
#include "lldb/Host/HostProcess.h"
14
#include "lldb/Host/ProcessLaunchInfo.h"
15
#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
16
#include "lldb/Symbol/ObjectFile.h"
17
#include "lldb/Utility/Log.h"
18
#include "lldb/Utility/State.h"
19
#include "lldb/Utility/Status.h"
20
#include "llvm/Support/Errno.h"
21
#include "llvm/Support/Error.h"
22
#include <cerrno>
23
#include <cstdint>
24
#include <cstring>
25
#include <sstream>
26
#include <string>
27
#include <sys/ptrace.h>
28
#include <unistd.h>
29
30
using namespace lldb;
31
using namespace lldb_private;
32
using namespace lldb_private::process_aix;
33
using namespace llvm;
34
35
static constexpr unsigned k_ptrace_word_size = sizeof(void *);
36
static_assert(sizeof(long) >= k_ptrace_word_size,
37
"Size of long must be larger than ptrace word size");
38
39
// Simple helper function to ensure flags are enabled on the given file
40
// descriptor.
41
static llvm::Error SetFDFlags(int fd, int flags) {
42
int status = fcntl(fd, F_GETFL);
43
if (status == -1)
44
return errorCodeToError(errnoAsErrorCode());
45
if (fcntl(fd, F_SETFL, status | flags) == -1)
46
return errorCodeToError(errnoAsErrorCode());
47
return Error::success();
48
}
49
50
NativeProcessAIX::Manager::Manager(MainLoop &mainloop)
51
: NativeProcessProtocol::Manager(mainloop) {
52
Status status;
53
m_sigchld_handle = mainloop.RegisterSignal(
54
SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
55
assert(m_sigchld_handle && status.Success());
56
}
57
58
// Public Static Methods
59
60
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
61
NativeProcessAIX::Manager::Launch(ProcessLaunchInfo &launch_info,
62
NativeDelegate &native_delegate) {
63
Log *log = GetLog(POSIXLog::Process);
64
65
Status status;
66
::pid_t pid = ProcessLauncherPosixFork()
67
.LaunchProcess(launch_info, status)
68
.GetProcessId();
69
LLDB_LOG(log, "pid = {0:x}", pid);
70
if (status.Fail()) {
71
LLDB_LOG(log, "failed to launch process: {0}", status);
72
return status.ToError();
73
}
74
75
// Wait for the child process to trap on its call to execve.
76
int wstatus = 0;
77
::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
78
assert(wpid == pid);
79
UNUSED_IF_ASSERT_DISABLED(wpid);
80
if (!WIFSTOPPED(wstatus)) {
81
LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
82
WaitStatus::Decode(wstatus));
83
return llvm::make_error<StringError>("Could not sync with inferior process",
84
llvm::inconvertibleErrorCode());
85
}
86
LLDB_LOG(log, "inferior started, now in stopped state");
87
88
return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(
89
pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
90
HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, {pid}));
91
}
92
93
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
94
NativeProcessAIX::Manager::Attach(
95
lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {
96
Log *log = GetLog(POSIXLog::Process);
97
LLDB_LOG(log, "pid = {0:x}", pid);
98
99
auto tids_or = NativeProcessAIX::Attach(pid);
100
if (!tids_or)
101
return tids_or.takeError();
102
103
return std::unique_ptr<NativeProcessAIX>(new NativeProcessAIX(
104
pid, -1, native_delegate,
105
HostInfo::GetArchitecture(HostInfo::eArchKind64), *this, *tids_or));
106
}
107
108
lldb::addr_t NativeProcessAIX::GetSharedLibraryInfoAddress() {
109
return LLDB_INVALID_ADDRESS;
110
}
111
112
static std::optional<std::pair<lldb::pid_t, WaitStatus>> WaitPid() {
113
Log *log = GetLog(POSIXLog::Process);
114
115
int status;
116
::pid_t wait_pid =
117
llvm::sys::RetryAfterSignal(-1, ::waitpid, -1, &status, WNOHANG);
118
119
if (wait_pid == 0)
120
return std::nullopt;
121
122
if (wait_pid == -1) {
123
Status error(errno, eErrorTypePOSIX);
124
LLDB_LOG(log, "waitpid(-1, &status, _) failed: {0}", error);
125
return std::nullopt;
126
}
127
128
WaitStatus wait_status = WaitStatus::Decode(status);
129
130
LLDB_LOG(log, "waitpid(-1, &status, _) = {0}, status = {1}", wait_pid,
131
wait_status);
132
return std::make_pair(wait_pid, wait_status);
133
}
134
135
void NativeProcessAIX::Manager::SigchldHandler() {
136
while (true) {
137
auto wait_result = WaitPid();
138
if (!wait_result)
139
return;
140
}
141
}
142
143
void NativeProcessAIX::Manager::CollectThread(::pid_t tid) {}
144
145
// Public Instance Methods
146
147
NativeProcessAIX::NativeProcessAIX(::pid_t pid, int terminal_fd,
148
NativeDelegate &delegate,
149
const ArchSpec &arch, Manager &manager,
150
llvm::ArrayRef<::pid_t> tids)
151
: NativeProcessProtocol(pid, terminal_fd, delegate), m_manager(manager),
152
m_arch(arch) {
153
manager.AddProcess(*this);
154
if (m_terminal_fd != -1)
155
cantFail(SetFDFlags(m_terminal_fd, O_NONBLOCK));
156
157
// Let our process instance know the thread has stopped.
158
SetCurrentThreadID(tids[0]);
159
SetState(StateType::eStateStopped, false);
160
}
161
162
llvm::Expected<std::vector<::pid_t>> NativeProcessAIX::Attach(::pid_t pid) {
163
Log *log = GetLog(POSIXLog::Process);
164
Status status;
165
if (llvm::Error err = PtraceWrapper(PT_ATTACH, pid).takeError())
166
return err;
167
168
int wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, nullptr, WNOHANG);
169
if (wpid <= 0)
170
return llvm::errorCodeToError(errnoAsErrorCode());
171
LLDB_LOG(log, "adding pid = {0}", pid);
172
173
return std::vector<::pid_t>{pid};
174
}
175
176
bool NativeProcessAIX::SupportHardwareSingleStepping() const { return false; }
177
178
Status NativeProcessAIX::Resume(const ResumeActionList &resume_actions) {
179
return Status("unsupported");
180
}
181
182
Status NativeProcessAIX::Halt() { return Status("unsupported"); }
183
184
Status NativeProcessAIX::Detach() { return Status("unsupported"); }
185
186
Status NativeProcessAIX::Signal(int signo) { return Status("unsupported"); }
187
188
Status NativeProcessAIX::Interrupt() { return Status("unsupported"); }
189
190
Status NativeProcessAIX::Kill() { return Status("unsupported"); }
191
192
Status NativeProcessAIX::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
193
size_t &bytes_read) {
194
return Status("unsupported");
195
}
196
197
Status NativeProcessAIX::WriteMemory(lldb::addr_t addr, const void *buf,
198
size_t size, size_t &bytes_written) {
199
return Status("unsupported");
200
}
201
202
size_t NativeProcessAIX::UpdateThreads() {
203
// The NativeProcessAIX monitoring threads are always up to date with
204
// respect to thread state and they keep the thread list populated properly.
205
// All this method needs to do is return the thread count.
206
return m_threads.size();
207
}
208
209
Status NativeProcessAIX::GetLoadedModuleFileSpec(const char *module_path,
210
FileSpec &file_spec) {
211
return Status("unsupported");
212
}
213
214
Status NativeProcessAIX::SetBreakpoint(lldb::addr_t addr, uint32_t size,
215
bool hardware) {
216
if (hardware)
217
return SetHardwareBreakpoint(addr, size);
218
return SetSoftwareBreakpoint(addr, size);
219
}
220
221
Status NativeProcessAIX::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {
222
if (hardware)
223
return RemoveHardwareBreakpoint(addr);
224
return NativeProcessProtocol::RemoveBreakpoint(addr);
225
}
226
227
llvm::Error NativeProcessAIX::Detach(lldb::tid_t tid) {
228
return PtraceWrapper(PT_DETACH, tid).takeError();
229
}
230
231
llvm::Expected<int> NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid,
232
void *addr, void *data,
233
size_t data_size) {
234
int ret;
235
236
Log *log = GetLog(POSIXLog::Ptrace);
237
switch (req) {
238
case PT_ATTACH:
239
case PT_DETACH:
240
ret = ptrace64(req, pid, 0, 0, nullptr);
241
break;
242
default:
243
llvm_unreachable("PT_ request not supported yet.");
244
}
245
246
LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3}, {4})={5:x}", req, pid, addr, data,
247
data_size, ret);
248
249
if (ret == -1) {
250
LLDB_LOG(log, "ptrace() failed");
251
return llvm::errorCodeToError(errnoAsErrorCode());
252
}
253
return ret;
254
}
255
256