15 #include <sys/types.h>
16 #include <sys/utsname.h>
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/Object/ELF.h"
21 #include "llvm/Support/ScopedPrinter.h"
39 enum class ProcessState {
58 ProcessState &State, ::
pid_t &TracerPid,
66 llvm::StringRef Rest = BufferOrError.get()->getBuffer();
67 while (!Rest.empty()) {
69 std::tie(Line, Rest) = Rest.split(
'\n');
71 if (Line.consume_front(
"Gid:")) {
75 Line.consumeInteger(10, RGid);
77 Line.consumeInteger(10, EGid);
81 }
else if (Line.consume_front(
"Uid:")) {
85 Line.consumeInteger(10, RUid);
87 Line.consumeInteger(10, EUid);
91 }
else if (Line.consume_front(
"PPid:")) {
93 Line.ltrim().consumeInteger(10, PPid);
95 }
else if (Line.consume_front(
"State:")) {
96 State = llvm::StringSwitch<ProcessState>(Line.ltrim().take_front(1))
97 .Case(
"D", ProcessState::DiskSleep)
98 .Case(
"I", ProcessState::Idle)
99 .Case(
"R", ProcessState::Running)
100 .Case(
"S", ProcessState::Sleeping)
101 .CaseLower(
"T", ProcessState::TracedOrStopped)
102 .Case(
"W", ProcessState::Paging)
103 .Case(
"P", ProcessState::Parked)
104 .Case(
"X", ProcessState::Dead)
105 .Case(
"Z", ProcessState::Zombie)
106 .Default(ProcessState::Unknown);
107 if (
State == ProcessState::Unknown) {
108 LLDB_LOG(log,
"Unknown process state {0}", Line);
110 }
else if (Line.consume_front(
"TracerPid:")) {
112 Line.consumeInteger(10, TracerPid);
113 }
else if (Line.consume_front(
"Tgid:")) {
115 Line.consumeInteger(10, Tgid);
122 for (; *dname; dname++) {
123 if (!isdigit(*dname))
132 auto buffer_sp = FileSystem::Instance().CreateDataBuffer(exe_path, 0
x20, 0);
137 llvm::object::getElfArchType(
138 {
reinterpret_cast<const char *
>(buffer_sp->GetBytes()),
139 size_t(buffer_sp->GetByteSize())})
143 case llvm::ELF::ELFCLASS32:
144 return HostInfo::GetArchitecture(HostInfo::eArchKind32);
145 case llvm::ELF::ELFCLASS64:
146 return HostInfo::GetArchitecture(HostInfo::eArchKind64);
148 LLDB_LOG(log,
"Unknown elf class ({0}) in file {1}", exe_class, exe_path);
157 std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move(*BufferOrError);
159 llvm::StringRef Arg0, Rest;
160 std::tie(Arg0, Rest) = Cmdline->getBuffer().split(
'\0');
162 while (!Rest.empty()) {
164 std::tie(Arg, Rest) = Rest.split(
'\0');
174 llvm::SmallString<64> ProcExe;
175 (llvm::Twine(
"/proc/") + llvm::Twine(pid) +
"/exe").toVector(ProcExe);
177 ssize_t len = readlink(ProcExe.c_str(), &ExePath[0],
PATH_MAX);
181 LLDB_LOG(log,
"failed to read link exe link for {0}: {1}", pid,
187 llvm::StringRef PathRef = ExePath;
188 PathRef.consume_back(
" (deleted)");
190 if (!PathRef.empty()) {
202 std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError);
203 llvm::StringRef Rest = Environ->getBuffer();
204 while (!Rest.empty()) {
206 std::tie(Var, Rest) = Rest.split(
'\0');
213 ProcessState &State, ::
pid_t &tracerpid) {
216 process_info.
Clear();
233 static const char procdir[] =
"/proc/";
235 DIR *dirproc = opendir(procdir);
237 struct dirent *direntry =
nullptr;
238 const uid_t our_uid = getuid();
242 while ((direntry = readdir(dirproc)) !=
nullptr) {
243 if (direntry->d_type != DT_DIR || !
IsDirNumeric(direntry->d_name))
263 if (State == ProcessState::Zombie)
268 if (!all_users && (our_uid != 0) && (process_info.
GetUserID() != our_uid))
271 if (match_info.
Matches(process_info)) {
272 process_infos.push_back(process_info);
279 return process_infos.size();
282 bool Host::FindProcessThreads(
const lldb::pid_t pid, TidMap &tids_to_attach) {
283 bool tids_changed =
false;
284 static const char procdir[] =
"/proc/";
285 static const char taskdir[] =
"/task/";
286 std::string process_task_dir = procdir + llvm::to_string(pid) + taskdir;
287 DIR *dirproc = opendir(process_task_dir.c_str());
290 struct dirent *direntry =
nullptr;
291 while ((direntry = readdir(dirproc)) !=
nullptr) {
292 if (direntry->d_type != DT_DIR || !
IsDirNumeric(direntry->d_name))
296 TidMap::iterator it = tids_to_attach.find(tid);
297 if (it == tids_to_attach.end()) {
298 tids_to_attach.insert(TidPair(tid,
false));
317 return Status(
"unimplemented");
325 if (!
GetStatusInfo(tid, process_info, state, tracerpid, tgid) ||