17#include <sys/utsname.h>
20#include "llvm/ADT/StringSwitch.h"
21#include "llvm/Object/ELF.h"
22#include "llvm/Support/ScopedPrinter.h"
40enum class ProcessState {
67 llvm::StringRef Rest = BufferOrError.get()->getBuffer();
68 while (!Rest.empty()) {
70 std::tie(Line, Rest) = Rest.split(
'\n');
72 if (Line.consume_front(
"Gid:")) {
76 Line.consumeInteger(10, RGid);
78 Line.consumeInteger(10, EGid);
82 }
else if (Line.consume_front(
"Uid:")) {
86 Line.consumeInteger(10, RUid);
88 Line.consumeInteger(10, EUid);
92 }
else if (Line.consume_front(
"PPid:")) {
94 Line.ltrim().consumeInteger(10, PPid);
96 }
else if (Line.consume_front(
"State:")) {
97 State = llvm::StringSwitch<ProcessState>(Line.ltrim().take_front(1))
98 .Case(
"D", ProcessState::DiskSleep)
99 .Case(
"I", ProcessState::Idle)
100 .Case(
"R", ProcessState::Running)
101 .Case(
"S", ProcessState::Sleeping)
102 .CaseLower(
"T", ProcessState::TracedOrStopped)
103 .Case(
"W", ProcessState::Paging)
104 .Case(
"P", ProcessState::Parked)
105 .Case(
"X", ProcessState::Dead)
106 .Case(
"Z", ProcessState::Zombie)
107 .Default(ProcessState::Unknown);
108 if (
State == ProcessState::Unknown) {
109 LLDB_LOG(log,
"Unknown process state {0}", Line);
111 }
else if (Line.consume_front(
"TracerPid:")) {
113 Line.consumeInteger(10, TracerPid);
114 }
else if (Line.consume_front(
"Tgid:")) {
116 Line.consumeInteger(10, Tgid);
123 for (; *dname; dname++) {
124 if (!isdigit(*dname))
138 llvm::object::getElfArchType(
139 {
reinterpret_cast<const char *
>(buffer_sp->GetBytes()),
140 size_t(buffer_sp->GetByteSize())})
144 case llvm::ELF::ELFCLASS32:
145 return HostInfo::GetArchitecture(HostInfo::eArchKind32);
146 case llvm::ELF::ELFCLASS64:
147 return HostInfo::GetArchitecture(HostInfo::eArchKind64);
149 LLDB_LOG(log,
"Unknown elf class ({0}) in file {1}", exe_class, exe_path);
158 std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move(*BufferOrError);
160 llvm::StringRef Arg0, Rest;
161 std::tie(Arg0, Rest) = Cmdline->getBuffer().split(
'\0');
163 while (!Rest.empty()) {
165 std::tie(Arg, Rest) = Rest.split(
'\0');
172 std::string ExePath(
PATH_MAX,
'\0');
175 llvm::SmallString<64> ProcExe;
176 (llvm::Twine(
"/proc/") + llvm::Twine(pid) +
"/exe").toVector(ProcExe);
178 ssize_t len = readlink(ProcExe.c_str(), &ExePath[0],
PATH_MAX);
182 LLDB_LOG(log,
"failed to read link exe link for {0}: {1}", pid,
188 llvm::StringRef PathRef = ExePath;
189 PathRef.consume_back(
" (deleted)");
191 if (!PathRef.empty()) {
203 std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError);
204 llvm::StringRef Rest = Environ->getBuffer();
205 while (!Rest.empty()) {
207 std::tie(Var, Rest) = Rest.split(
'\0');
217 process_info.
Clear();
234 static const char procdir[] =
"/proc/";
236 DIR *dirproc = opendir(procdir);
238 struct dirent *direntry =
nullptr;
239 const uid_t our_uid = getuid();
243 while ((direntry = readdir(dirproc)) !=
nullptr) {
244 if (direntry->d_type != DT_DIR || !
IsDirNumeric(direntry->d_name))
264 if (
State == ProcessState::Zombie)
269 if (!all_users && (our_uid != 0) && (process_info.
GetUserID() != our_uid))
272 if (match_info.
Matches(process_info)) {
273 process_infos.push_back(process_info);
280 return process_infos.size();
284 bool tids_changed =
false;
285 static const char procdir[] =
"/proc/";
286 static const char taskdir[] =
"/task/";
287 std::string process_task_dir = procdir + llvm::to_string(pid) + taskdir;
288 DIR *dirproc = opendir(process_task_dir.c_str());
291 struct dirent *direntry =
nullptr;
292 while ((direntry = readdir(dirproc)) !=
nullptr) {
293 if (direntry->d_type != DT_DIR || !
IsDirNumeric(direntry->d_name))
297 TidMap::iterator it = tids_to_attach.find(tid);
298 if (it == tids_to_attach.end()) {
299 tids_to_attach.insert(
TidPair(tid,
false));
318 return Status(
"unimplemented");
326 if (!
GetStatusInfo(tid, process_info, state, tracerpid, tgid) ||
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
An architecture specification class.
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
std::pair< iterator, bool > insert(llvm::StringRef KeyEqValue)
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
static FileSystem & Instance()
std::shared_ptr< DataBuffer > CreateDataBuffer(const llvm::Twine &path, uint64_t size=0, uint64_t offset=0)
Create memory buffer from path.
static bool FindProcessThreads(const lldb::pid_t pid, TidMap &tids_to_attach)
static Status ShellExpandArguments(ProcessLaunchInfo &launch_info)
Perform expansion of the command-line for this launch info This can potentially involve wildcard expa...
static Environment GetEnvironment()
static uint32_t FindProcessesImpl(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &proc_infos)
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
std::pair< lldb::pid_t, bool > TidPair
void SetGroupID(uint32_t gid)
void SetArchitecture(const ArchSpec &arch)
void SetArg0(llvm::StringRef arg)
void SetProcessID(lldb::pid_t pid)
FileSpec & GetExecutableFile()
uint32_t GetUserID() const
Environment & GetEnvironment()
void SetUserID(uint32_t uid)
bool Matches(const ProcessInstanceInfo &proc_info) const
bool GetMatchAllUsers() const
static void GetExePathAndArch(::pid_t pid, ProcessInstanceInfo &process_info)
static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path)
static bool GetProcessAndStatInfo(::pid_t pid, ProcessInstanceInfo &process_info, ProcessState &State, ::pid_t &tracerpid)
static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info)
static bool IsDirNumeric(const char *dname)
static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info)
static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, ProcessState &State, ::pid_t &TracerPid, ::pid_t &Tgid)
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::optional< lldb::pid_t > getPIDForTID(lldb::pid_t tid)
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file)
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
@ eErrorTypePOSIX
POSIX error codes.