forked from OSchip/llvm-project
[lldb-server/android] Show more processes and package name when necessary
Summary: By default `platform process list` only shows the processes of the current user that lldb-server can parse. There are several problems: - apk programs don't have an executable file. They instead use a package name as identifier. - each apk also runs under a different user. That's how android works - because of the user permission, some files like /proc/<pid>/{environ,exe} can't be read. This results in a very small process list. This is a local run on my machine ``` (lldb) platform process list 2 matching processes were found on "remote-android" PID PARENT USER TRIPLE NAME ====== ====== ========== ======================== ============================ 23291 3177 aarch64-unknown-linux-android sh 23301 23291 aarch64-unknown-linux-android lldb-server ``` However, I have 700 processes running at this time. By implementing a few fallbacks for android, I've expanded this list to 202, filtering out kernel processes, which would presumably appear in this list if the device was rooted. ``` (lldb) platform process list 202 matching processes were found on "remote-android" PID PARENT USER TRIPLE NAME ====== ====== ========== ======================== ============================ ... 12647 3208 aarch64-unknown-linux-android sh 12649 12647 aarch64-unknown-linux-android lldb-server 12653 982 com.samsung.faceservice 13185 982 com.samsung.vvm 15899 982 com.samsung.android.spay 16220 982 com.sec.spp.push 17126 982 com.sec.spp.push:RemoteDlcProcess 19772 983 com.android.chrome 20209 982 com.samsung.cmh:CMH 20380 982 com.google.android.inputmethod.latin 20879 982 com.samsung.android.oneconnect:Receiver 21212 983 com.tencent.mm 24459 1 aarch64-unknown-linux-android wpa_supplicant 25974 982 com.samsung.android.contacts 26293 982 com.samsung.android.messaging 28714 982 com.samsung.android.dialer 31605 982 com.samsung.android.MtpApplication 32256 982 com.bezobidny ``` Something to notice is that the architecture is unkonwn for all apks. And that's fine, because run-as would be required to gather this information and that would make this entire functionality massively slow. There are still several improvements to make here, like displaying actual user names, which I'll try to do in a following diff. Note: Regarding overall apk debugging support from lldb. I'm planning on having lldb spawn lldb-server by itself with the correct user, so that everything works well. The initial lldb-server used for connecting to the remote platform can be reused for such purpose. Furthermore, eventually lldb could also launch that initial lldb-server on its own. Reviewers: clayborg, aadsm, labath, xiaobai Subscribers: srhines, krytarowski, kristof.beyls, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D68289 llvm-svn: 373758
This commit is contained in:
parent
1c9e1731b0
commit
856383555b
|
@ -144,61 +144,13 @@ static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool GetProcessAndStatInfo(::pid_t pid,
|
||||
ProcessInstanceInfo &process_info,
|
||||
ProcessState &State, ::pid_t &tracerpid) {
|
||||
tracerpid = 0;
|
||||
process_info.Clear();
|
||||
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
|
||||
|
||||
// We can't use getProcFile here because proc/[pid]/exe is a symbolic link.
|
||||
llvm::SmallString<64> ProcExe;
|
||||
(llvm::Twine("/proc/") + llvm::Twine(pid) + "/exe").toVector(ProcExe);
|
||||
std::string ExePath(PATH_MAX, '\0');
|
||||
|
||||
ssize_t len = readlink(ProcExe.c_str(), &ExePath[0], PATH_MAX);
|
||||
if (len <= 0) {
|
||||
LLDB_LOG(log, "failed to read link exe link for {0}: {1}", pid,
|
||||
Status(errno, eErrorTypePOSIX));
|
||||
return false;
|
||||
}
|
||||
ExePath.resize(len);
|
||||
|
||||
// If the binary has been deleted, the link name has " (deleted)" appended.
|
||||
// Remove if there.
|
||||
llvm::StringRef PathRef = ExePath;
|
||||
PathRef.consume_back(" (deleted)");
|
||||
|
||||
process_info.SetArchitecture(GetELFProcessCPUType(PathRef));
|
||||
|
||||
// Get the process environment.
|
||||
auto BufferOrError = getProcFile(pid, "environ");
|
||||
static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info) {
|
||||
auto BufferOrError = getProcFile(pid, "cmdline");
|
||||
if (!BufferOrError)
|
||||
return false;
|
||||
std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError);
|
||||
|
||||
// Get the command line used to start the process.
|
||||
BufferOrError = getProcFile(pid, "cmdline");
|
||||
if (!BufferOrError)
|
||||
return false;
|
||||
return;
|
||||
std::unique_ptr<llvm::MemoryBuffer> Cmdline = std::move(*BufferOrError);
|
||||
|
||||
// Get User and Group IDs and get tracer pid.
|
||||
if (!GetStatusInfo(pid, process_info, State, tracerpid))
|
||||
return false;
|
||||
|
||||
process_info.SetProcessID(pid);
|
||||
process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
|
||||
|
||||
llvm::StringRef Rest = Environ->getBuffer();
|
||||
while (!Rest.empty()) {
|
||||
llvm::StringRef Var;
|
||||
std::tie(Var, Rest) = Rest.split('\0');
|
||||
process_info.GetEnvironment().insert(Var);
|
||||
}
|
||||
|
||||
llvm::StringRef Arg0;
|
||||
llvm::StringRef Arg0, Rest;
|
||||
std::tie(Arg0, Rest) = Cmdline->getBuffer().split('\0');
|
||||
process_info.SetArg0(Arg0);
|
||||
while (!Rest.empty()) {
|
||||
|
@ -206,6 +158,65 @@ static bool GetProcessAndStatInfo(::pid_t pid,
|
|||
std::tie(Arg, Rest) = Rest.split('\0');
|
||||
process_info.GetArguments().AppendArgument(Arg);
|
||||
}
|
||||
}
|
||||
|
||||
static void GetExePathAndArch(::pid_t pid, ProcessInstanceInfo &process_info) {
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
|
||||
std::string ExePath(PATH_MAX, '\0');
|
||||
|
||||
// We can't use getProcFile here because proc/[pid]/exe is a symbolic link.
|
||||
llvm::SmallString<64> ProcExe;
|
||||
(llvm::Twine("/proc/") + llvm::Twine(pid) + "/exe").toVector(ProcExe);
|
||||
|
||||
ssize_t len = readlink(ProcExe.c_str(), &ExePath[0], PATH_MAX);
|
||||
if (len > 0) {
|
||||
ExePath.resize(len);
|
||||
} else {
|
||||
LLDB_LOG(log, "failed to read link exe link for {0}: {1}", pid,
|
||||
Status(errno, eErrorTypePOSIX));
|
||||
ExePath.resize(0);
|
||||
}
|
||||
// If the binary has been deleted, the link name has " (deleted)" appended.
|
||||
// Remove if there.
|
||||
llvm::StringRef PathRef = ExePath;
|
||||
PathRef.consume_back(" (deleted)");
|
||||
|
||||
if (!PathRef.empty()) {
|
||||
process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
|
||||
process_info.SetArchitecture(GetELFProcessCPUType(PathRef));
|
||||
}
|
||||
}
|
||||
|
||||
static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info) {
|
||||
// Get the process environment.
|
||||
auto BufferOrError = getProcFile(pid, "environ");
|
||||
if (!BufferOrError)
|
||||
return;
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> Environ = std::move(*BufferOrError);
|
||||
llvm::StringRef Rest = Environ->getBuffer();
|
||||
while (!Rest.empty()) {
|
||||
llvm::StringRef Var;
|
||||
std::tie(Var, Rest) = Rest.split('\0');
|
||||
process_info.GetEnvironment().insert(Var);
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetProcessAndStatInfo(::pid_t pid,
|
||||
ProcessInstanceInfo &process_info,
|
||||
ProcessState &State, ::pid_t &tracerpid) {
|
||||
tracerpid = 0;
|
||||
process_info.Clear();
|
||||
|
||||
process_info.SetProcessID(pid);
|
||||
|
||||
GetExePathAndArch(pid, process_info);
|
||||
GetProcessArgs(pid, process_info);
|
||||
GetProcessEnviron(pid, process_info);
|
||||
|
||||
// Get User and Group IDs and get tracer pid.
|
||||
if (!GetStatusInfo(pid, process_info, State, tracerpid))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue