aboutsummaryrefslogtreecommitdiff
path: root/tools/gator/daemon/Proc.cpp
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2014-10-31 16:29:17 +0000
committerMark Brown <broonie@kernel.org>2014-10-31 16:29:17 +0000
commita3d64deb4ee72f27441dd5363d74c294b7dd34a7 (patch)
treee8cd428e662cdeec5e8376d1aac3ab07eb5edbce /tools/gator/daemon/Proc.cpp
parent335ab1659bbf3ecf8dc1ba31e66111d35d54e8c9 (diff)
parent715db954c8f2d97a6742ff13be91c99db22135e9 (diff)
Merge branch 'lsk-3.10-gator' of git://git.linaro.org/landing-teams/working/arm/kernel into lsk-v3.10-gator
Diffstat (limited to 'tools/gator/daemon/Proc.cpp')
-rw-r--r--tools/gator/daemon/Proc.cpp137
1 files changed, 117 insertions, 20 deletions
diff --git a/tools/gator/daemon/Proc.cpp b/tools/gator/daemon/Proc.cpp
index 9f01770d6609..e6b26b1199fa 100644
--- a/tools/gator/daemon/Proc.cpp
+++ b/tools/gator/daemon/Proc.cpp
@@ -10,13 +10,16 @@
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "Buffer.h"
#include "DynBuf.h"
#include "Logging.h"
+#include "SessionData.h"
struct ProcStat {
// From linux-dev/include/linux/sched.h
@@ -57,6 +60,8 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf
return true;
}
+static const char APP_PROCESS[] = "app_process";
+
static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) {
if (tid == -1 ? !printb->printf("/proc/%i/exe", pid)
: !printb->printf("/proc/%i/task/%i/exe", pid, tid)) {
@@ -82,7 +87,8 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
}
// Android apps are run by app_process but the cmdline is changed to reference the actual app name
- if (strcmp(image, "app_process") != 0) {
+ // On 64-bit android app_process can be app_process32 or app_process64
+ if (strncmp(image, APP_PROCESS, sizeof(APP_PROCESS) - 1) != 0) {
return image;
}
@@ -100,7 +106,7 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
return b->getBuf();
}
-static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
+static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
if (!b1->printf("/proc/%i/task", pid)) {
@@ -110,7 +116,8 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
DIR *task = opendir(b1->getBuf());
if (task == NULL) {
logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
- return result;
+ // This is not a fatal error - the thread just doesn't exist any more
+ return true;
}
struct dirent *dirent;
@@ -138,7 +145,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
goto fail;
}
- buffer->comm(pid, tid, image, ps.comm);
+ buffer->comm(currTime, pid, tid, image, ps.comm);
}
result = true;
@@ -149,7 +156,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
return result;
}
-bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
+bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
DIR *proc = opendir("/proc");
@@ -177,19 +184,6 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
goto fail;
}
- if (sendMaps) {
- if (!printb->printf("/proc/%i/maps", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- if (!b2->read(printb->getBuf())) {
- logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
- // This is not a fatal error - the process just doesn't exist any more
- continue;
- }
-
- buffer->maps(pid, pid, b2->getBuf());
- }
if (ps.numThreads <= 1) {
const char *const image = readProcExe(printb, pid, -1, b1);
if (image == NULL) {
@@ -197,9 +191,9 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
goto fail;
}
- buffer->comm(pid, pid, image, ps.comm);
+ buffer->comm(currTime, pid, pid, image, ps.comm);
} else {
- if (!readProcTask(buffer, pid, printb, b1, b3)) {
+ if (!readProcTask(currTime, buffer, pid, printb, b1, b2)) {
logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
@@ -213,3 +207,106 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
return result;
}
+
+bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b) {
+ bool result = false;
+
+ DIR *proc = opendir("/proc");
+ if (proc == NULL) {
+ logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
+ return result;
+ }
+
+ struct dirent *dirent;
+ while ((dirent = readdir(proc)) != NULL) {
+ char *endptr;
+ const int pid = strtol(dirent->d_name, &endptr, 10);
+ if (*endptr != '\0') {
+ // Ignore proc items that are not integers like ., cpuinfo, etc...
+ continue;
+ }
+
+ if (!printb->printf("/proc/%i/maps", pid)) {
+ logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+ goto fail;
+ }
+ if (!b->read(printb->getBuf())) {
+ logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
+ // This is not a fatal error - the process just doesn't exist any more
+ continue;
+ }
+
+ buffer->maps(currTime, pid, pid, b->getBuf());
+ }
+
+ result = true;
+
+ fail:
+ closedir(proc);
+
+ return result;
+}
+
+bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *const isDone) {
+ int fd = ::open("/proc/kallsyms", O_RDONLY | O_CLOEXEC);
+
+ if (fd < 0) {
+ logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
+ return true;
+ };
+
+ char buf[1<<12];
+ ssize_t pos = 0;
+ while (gSessionData->mSessionIsActive && !ACCESS_ONCE(*isDone)) {
+ // Assert there is still space in the buffer
+ if (sizeof(buf) - pos - 1 == 0) {
+ logg->logError(__FILE__, __LINE__, "no space left in buffer");
+ handleException();
+ }
+
+ {
+ // -1 to reserve space for \0
+ const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
+ if (bytes < 0) {
+ logg->logError(__FILE__, __LINE__, "read failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ if (bytes == 0) {
+ // Assert the buffer is empty
+ if (pos != 0) {
+ logg->logError(__FILE__, __LINE__, "buffer not empty on eof");
+ handleException();
+ }
+ break;
+ }
+ pos += bytes;
+ }
+
+ ssize_t newline;
+ // Find the last '\n'
+ for (newline = pos - 1; newline >= 0; --newline) {
+ if (buf[newline] == '\n') {
+ const char was = buf[newline + 1];
+ buf[newline + 1] = '\0';
+ buffer->kallsyms(currTime, buf);
+ // Sleep 3 ms to avoid sending out too much data too quickly
+ usleep(3000);
+ buf[0] = was;
+ // Assert the memory regions do not overlap
+ if (pos - newline >= newline + 1) {
+ logg->logError(__FILE__, __LINE__, "memcpy src and dst overlap");
+ handleException();
+ }
+ if (pos - newline - 2 > 0) {
+ memcpy(buf + 1, buf + newline + 2, pos - newline - 2);
+ }
+ pos -= newline + 1;
+ break;
+ }
+ }
+ }
+
+ close(fd);
+
+ return true;
+}