#include <base/strings.h>
#include <base/stringprintf.h>
+#include "read_elf.h"
#include "utils.h"
std::vector<int> GetOnlineCpus() {
if (android::base::EndsWith(name, ".ko")) {
std::string module_name = name.substr(0, name.size() - 3);
std::replace(module_name.begin(), module_name.end(), '-', '_');
- module_file_map->insert(std::make_pair(module_name, path + name));
+ module_file_map->insert(std::make_pair(module_name, path + "/" + name));
}
}
for (auto& name : subdirs) {
return false;
}
-static bool GetThreadComm(pid_t pid, std::vector<ThreadComm>* thread_comms) {
+static std::vector<pid_t> GetThreadsInProcess(pid_t pid) {
+ std::vector<pid_t> result;
std::string task_dirname = android::base::StringPrintf("/proc/%d/task", pid);
std::vector<std::string> subdirs;
GetEntriesInDir(task_dirname, nullptr, &subdirs);
if (!StringToPid(name, &tid)) {
continue;
}
- std::string status_file = task_dirname + "/" + name + "/status";
+ result.push_back(tid);
+ }
+ return result;
+}
+
+static bool GetThreadComm(pid_t pid, std::vector<ThreadComm>* thread_comms) {
+ std::vector<pid_t> tids = GetThreadsInProcess(pid);
+ for (auto& tid : tids) {
+ std::string status_file = android::base::StringPrintf("/proc/%d/task/%d/status", pid, tid);
std::string comm;
pid_t tgid;
+ // It is possible that the process or thread exited before we can read its status.
if (!ReadThreadNameAndTgid(status_file, &comm, &tgid)) {
- return false;
+ continue;
}
+ CHECK_EQ(pid, tgid);
ThreadComm thread;
thread.tid = tid;
- thread.tgid = tgid;
+ thread.pid = pid;
thread.comm = comm;
- thread.is_process = (tid == pid);
thread_comms->push_back(thread);
}
return true;
}
return true;
}
+
+bool GetKernelBuildId(BuildId* build_id) {
+ return GetBuildIdFromNoteFile("/sys/kernel/notes", build_id);
+}
+
+bool GetModuleBuildId(const std::string& module_name, BuildId* build_id) {
+ std::string notefile = "/sys/module/" + module_name + "/notes/.note.gnu.build-id";
+ return GetBuildIdFromNoteFile(notefile, build_id);
+}
+
+bool GetValidThreadsFromProcessString(const std::string& pid_str, std::set<pid_t>* tid_set) {
+ std::vector<std::string> strs = android::base::Split(pid_str, ",");
+ for (auto& s : strs) {
+ pid_t pid;
+ if (!StringToPid(s, &pid)) {
+ LOG(ERROR) << "Invalid pid '" << s << "'";
+ return false;
+ }
+ std::vector<pid_t> tids = GetThreadsInProcess(pid);
+ if (tids.empty()) {
+ LOG(ERROR) << "Non existing process '" << pid << "'";
+ return false;
+ }
+ tid_set->insert(tids.begin(), tids.end());
+ }
+ return true;
+}
+
+bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) {
+ std::vector<std::string> strs = android::base::Split(tid_str, ",");
+ for (auto& s : strs) {
+ pid_t tid;
+ if (!StringToPid(s, &tid)) {
+ LOG(ERROR) << "Invalid tid '" << s << "'";
+ return false;
+ }
+ if (!IsDir(android::base::StringPrintf("/proc/%d", tid))) {
+ LOG(ERROR) << "Non existing thread '" << tid << "'";
+ return false;
+ }
+ tid_set->insert(tid);
+ }
+ return true;
+}
+
+bool GetExecPath(std::string* exec_path) {
+ char path[PATH_MAX];
+ ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+ if (path_len <= 0 || path_len >= static_cast<ssize_t>(sizeof(path))) {
+ PLOG(ERROR) << "readlink failed";
+ return false;
+ }
+ path[path_len] = '\0';
+ *exec_path = path;
+ return true;
+}