LLDB  mainline
linux/Host.cpp
Go to the documentation of this file.
1 //===-- source/Host/linux/Host.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 <cerrno>
10 #include <cstdio>
11 #include <cstring>
12 #include <dirent.h>
13 #include <fcntl.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <sys/utsname.h>
17 #include <unistd.h>
18 
19 #include "llvm/ADT/StringSwitch.h"
20 #include "llvm/Object/ELF.h"
21 #include "llvm/Support/ScopedPrinter.h"
22 
23 #include "lldb/Utility/LLDBLog.h"
24 #include "lldb/Utility/Log.h"
26 #include "lldb/Utility/Status.h"
27 
28 #include "lldb/Host/FileSystem.h"
29 #include "lldb/Host/Host.h"
30 #include "lldb/Host/HostInfo.h"
31 #include "lldb/Host/linux/Host.h"
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 
38 namespace {
39 enum class ProcessState {
40  Unknown,
41  Dead,
42  DiskSleep,
43  Idle,
44  Paging,
45  Parked,
46  Running,
47  Sleeping,
48  TracedOrStopped,
49  Zombie,
50 };
51 }
52 
53 namespace lldb_private {
54 class ProcessLaunchInfo;
55 }
56 
58  ProcessState &State, ::pid_t &TracerPid,
59  ::pid_t &Tgid) {
60  Log *log = GetLog(LLDBLog::Host);
61 
62  auto BufferOrError = getProcFile(Pid, "status");
63  if (!BufferOrError)
64  return false;
65 
66  llvm::StringRef Rest = BufferOrError.get()->getBuffer();
67  while (!Rest.empty()) {
68  llvm::StringRef Line;
69  std::tie(Line, Rest) = Rest.split('\n');
70 
71  if (Line.consume_front("Gid:")) {
72  // Real, effective, saved set, and file system GIDs. Read the first two.
73  Line = Line.ltrim();
74  uint32_t RGid, EGid;
75  Line.consumeInteger(10, RGid);
76  Line = Line.ltrim();
77  Line.consumeInteger(10, EGid);
78 
79  ProcessInfo.SetGroupID(RGid);
80  ProcessInfo.SetEffectiveGroupID(EGid);
81  } else if (Line.consume_front("Uid:")) {
82  // Real, effective, saved set, and file system UIDs. Read the first two.
83  Line = Line.ltrim();
84  uint32_t RUid, EUid;
85  Line.consumeInteger(10, RUid);
86  Line = Line.ltrim();
87  Line.consumeInteger(10, EUid);
88 
89  ProcessInfo.SetUserID(RUid);
90  ProcessInfo.SetEffectiveUserID(EUid);
91  } else if (Line.consume_front("PPid:")) {
92  ::pid_t PPid;
93  Line.ltrim().consumeInteger(10, PPid);
94  ProcessInfo.SetParentProcessID(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);
109  }
110  } else if (Line.consume_front("TracerPid:")) {
111  Line = Line.ltrim();
112  Line.consumeInteger(10, TracerPid);
113  } else if (Line.consume_front("Tgid:")) {
114  Line = Line.ltrim();
115  Line.consumeInteger(10, Tgid);
116  }
117  }
118  return true;
119 }
120 
121 static bool IsDirNumeric(const char *dname) {
122  for (; *dname; dname++) {
123  if (!isdigit(*dname))
124  return false;
125  }
126  return true;
127 }
128 
129 static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) {
130  Log *log = GetLog(LLDBLog::Host);
131 
132  auto buffer_sp = FileSystem::Instance().CreateDataBuffer(exe_path, 0x20, 0);
133  if (!buffer_sp)
134  return ArchSpec();
135 
136  uint8_t exe_class =
137  llvm::object::getElfArchType(
138  {reinterpret_cast<const char *>(buffer_sp->GetBytes()),
139  size_t(buffer_sp->GetByteSize())})
140  .first;
141 
142  switch (exe_class) {
143  case llvm::ELF::ELFCLASS32:
144  return HostInfo::GetArchitecture(HostInfo::eArchKind32);
145  case llvm::ELF::ELFCLASS64:
146  return HostInfo::GetArchitecture(HostInfo::eArchKind64);
147  default:
148  LLDB_LOG(log, "Unknown elf class ({0}) in file {1}", exe_class, exe_path);
149  return ArchSpec();
150  }
151 }
152 
153 static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info) {
154  auto BufferOrError = getProcFile(pid, "cmdline");
155  if (!BufferOrError)
156  return;
157  std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move(*BufferOrError);
158 
159  llvm::StringRef Arg0, Rest;
160  std::tie(Arg0, Rest) = Cmdline->getBuffer().split('\0');
161  process_info.SetArg0(Arg0);
162  while (!Rest.empty()) {
163  llvm::StringRef Arg;
164  std::tie(Arg, Rest) = Rest.split('\0');
165  process_info.GetArguments().AppendArgument(Arg);
166  }
167 }
168 
169 static void GetExePathAndArch(::pid_t pid, ProcessInstanceInfo &process_info) {
170  Log *log = GetLog(LLDBLog::Process);
171  std::string ExePath(PATH_MAX, '\0');
172 
173  // We can't use getProcFile here because proc/[pid]/exe is a symbolic link.
174  llvm::SmallString<64> ProcExe;
175  (llvm::Twine("/proc/") + llvm::Twine(pid) + "/exe").toVector(ProcExe);
176 
177  ssize_t len = readlink(ProcExe.c_str(), &ExePath[0], PATH_MAX);
178  if (len > 0) {
179  ExePath.resize(len);
180  } else {
181  LLDB_LOG(log, "failed to read link exe link for {0}: {1}", pid,
182  Status(errno, eErrorTypePOSIX));
183  ExePath.resize(0);
184  }
185  // If the binary has been deleted, the link name has " (deleted)" appended.
186  // Remove if there.
187  llvm::StringRef PathRef = ExePath;
188  PathRef.consume_back(" (deleted)");
189 
190  if (!PathRef.empty()) {
191  process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
192  process_info.SetArchitecture(GetELFProcessCPUType(PathRef));
193  }
194 }
195 
196 static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info) {
197  // Get the process environment.
198  auto BufferOrError = getProcFile(pid, "environ");
199  if (!BufferOrError)
200  return;
201 
202  std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError);
203  llvm::StringRef Rest = Environ->getBuffer();
204  while (!Rest.empty()) {
205  llvm::StringRef Var;
206  std::tie(Var, Rest) = Rest.split('\0');
207  process_info.GetEnvironment().insert(Var);
208  }
209 }
210 
211 static bool GetProcessAndStatInfo(::pid_t pid,
212  ProcessInstanceInfo &process_info,
213  ProcessState &State, ::pid_t &tracerpid) {
214  ::pid_t tgid;
215  tracerpid = 0;
216  process_info.Clear();
217 
218  process_info.SetProcessID(pid);
219 
220  GetExePathAndArch(pid, process_info);
221  GetProcessArgs(pid, process_info);
222  GetProcessEnviron(pid, process_info);
223 
224  // Get User and Group IDs and get tracer pid.
225  if (!GetStatusInfo(pid, process_info, State, tracerpid, tgid))
226  return false;
227 
228  return true;
229 }
230 
231 uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
232  ProcessInstanceInfoList &process_infos) {
233  static const char procdir[] = "/proc/";
234 
235  DIR *dirproc = opendir(procdir);
236  if (dirproc) {
237  struct dirent *direntry = nullptr;
238  const uid_t our_uid = getuid();
239  const lldb::pid_t our_pid = getpid();
240  bool all_users = match_info.GetMatchAllUsers();
241 
242  while ((direntry = readdir(dirproc)) != nullptr) {
243  if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name))
244  continue;
245 
246  lldb::pid_t pid = atoi(direntry->d_name);
247 
248  // Skip this process.
249  if (pid == our_pid)
250  continue;
251 
252  ::pid_t tracerpid;
253  ProcessState State;
254  ProcessInstanceInfo process_info;
255 
256  if (!GetProcessAndStatInfo(pid, process_info, State, tracerpid))
257  continue;
258 
259  // Skip if process is being debugged.
260  if (tracerpid != 0)
261  continue;
262 
263  if (State == ProcessState::Zombie)
264  continue;
265 
266  // Check for user match if we're not matching all users and not running
267  // as root.
268  if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
269  continue;
270 
271  if (match_info.Matches(process_info)) {
272  process_infos.push_back(process_info);
273  }
274  }
275 
276  closedir(dirproc);
277  }
278 
279  return process_infos.size();
280 }
281 
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());
288 
289  if (dirproc) {
290  struct dirent *direntry = nullptr;
291  while ((direntry = readdir(dirproc)) != nullptr) {
292  if (direntry->d_type != DT_DIR || !IsDirNumeric(direntry->d_name))
293  continue;
294 
295  lldb::tid_t tid = atoi(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));
299  tids_changed = true;
300  }
301  }
302  closedir(dirproc);
303  }
304 
305  return tids_changed;
306 }
307 
308 bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
309  ::pid_t tracerpid;
310  ProcessState State;
311  return GetProcessAndStatInfo(pid, process_info, State, tracerpid);
312 }
313 
314 Environment Host::GetEnvironment() { return Environment(environ); }
315 
316 Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
317  return Status("unimplemented");
318 }
319 
320 llvm::Optional<lldb::pid_t> lldb_private::getPIDForTID(lldb::pid_t tid) {
321  ::pid_t tracerpid, tgid = LLDB_INVALID_PROCESS_ID;
322  ProcessInstanceInfo process_info;
323  ProcessState state;
324 
325  if (!GetStatusInfo(tid, process_info, state, tracerpid, tgid) ||
326  tgid == LLDB_INVALID_PROCESS_ID)
327  return llvm::None;
328  return tgid;
329 }
lldb_private::ProcessInfo::GetArguments
Args & GetArguments()
Definition: ProcessInfo.h:75
lldb_private::ProcessInstanceInfo
Definition: ProcessInfo.h:108
GetExePathAndArch
static void GetExePathAndArch(::pid_t pid, ProcessInstanceInfo &process_info)
Definition: linux/Host.cpp:169
lldb_private::ArchSpec
Definition: ArchSpec.h:33
FileSystem.h
x20
@ x20
Definition: CompactUnwindInfo.cpp:1238
lldb_private::ProcessInstanceInfoMatch::GetMatchAllUsers
bool GetMatchAllUsers() const
Definition: ProcessInfo.h:178
lldb_private::ProcessInfo::SetArchitecture
void SetArchitecture(const ArchSpec &arch)
Definition: ProcessInfo.h:65
LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:81
lldb_private::ProcessInstanceInfo::Clear
void Clear()
Definition: ProcessInfo.h:116
Host.h
lldb_private::ProcessInfo::GetUserID
uint32_t GetUserID() const
Definition: ProcessInfo.h:49
lldb_private::Args::AppendArgument
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition: Args.cpp:318
lldb_private::ProcessInfo::SetUserID
void SetUserID(uint32_t uid)
Definition: ProcessInfo.h:57
GetELFProcessCPUType
static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path)
Definition: linux/Host.cpp:129
lldb_private::ProcessInstanceInfoMatch
Definition: ProcessInfo.h:163
lldb_private::ProcessInfo::SetProcessID
void SetProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:69
GetProcessAndStatInfo
static bool GetProcessAndStatInfo(::pid_t pid, ProcessInstanceInfo &process_info, ProcessState &State, ::pid_t &tracerpid)
Definition: linux/Host.cpp:211
lldb_private::ProcessInstanceInfoMatch::Matches
bool Matches(const ProcessInstanceInfo &proc_info) const
Definition: ProcessInfo.cpp:292
lldb::eErrorTypePOSIX
@ eErrorTypePOSIX
POSIX error codes.
Definition: lldb-enumerations.h:310
lldb_private::Environment::insert
std::pair< iterator, bool > insert(llvm::StringRef KeyEqValue)
Definition: Environment.h:71
ProcessInfo.h
lldb_private::ProcessLaunchInfo
Definition: ProcessLaunchInfo.h:31
Log.h
lldb_private::ProcessInfo
Definition: ProcessInfo.h:30
lldb_private::ProcessInfo::SetArg0
void SetArg0(llvm::StringRef arg)
Definition: ProcessInfo.cpp:79
lldb_private::LLDBLog::State
@ State
GetProcessArgs
static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info)
Definition: linux/Host.cpp:153
HostInfo.h
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::getProcFile
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file)
Definition: Support.cpp:15
IsDirNumeric
static bool IsDirNumeric(const char *dname)
Definition: linux/Host.cpp:121
lldb_private::Status
Definition: Status.h:44
uint32_t
lldb_private::ProcessInfo::GetEnvironment
Environment & GetEnvironment()
Definition: ProcessInfo.h:87
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
Support.h
Host.h
lldb_private::Environment
Definition: Environment.h:18
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:336
DataExtractor.h
GetStatusInfo
static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo, ProcessState &State, ::pid_t &TracerPid, ::pid_t &Tgid)
Definition: linux/Host.cpp:57
Status.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::ProcessInfo::GetExecutableFile
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:42
environ
char ** environ
lldb_private::Log
Definition: Log.h:115
lldb_private::getPIDForTID
llvm::Optional< lldb::pid_t > getPIDForTID(lldb::pid_t tid)
Definition: linux/Host.cpp:320
lldb_private::FileSpec::SetFile
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:172
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
lldb_private::ProcessInstanceInfoList
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition: Host.h:31
lldb
Definition: SBAddress.h:15
GetProcessEnviron
static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info)
Definition: linux/Host.cpp:196
LLDBLog.h
lldb_private::ProcessInfo::SetGroupID
void SetGroupID(uint32_t gid)
Definition: ProcessInfo.h:59
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86