commit adae8b96bef786868c54f441f82e9f77320cce93
parent 7c72a249aa0ae8e452852e223e0cab463974945c
Author: Kyle Milz <kyle@0x30.net>
Date: Fri, 9 Dec 2016 00:19:05 -0700
src: sync process file with runtime
Diffstat:
3 files changed, 165 insertions(+), 150 deletions(-)
diff --git a/src/gl_main.cc b/src/gl_main.cc
@@ -83,11 +83,11 @@ add_new_process(std::string const &file_name)
demo_buffer_clear(buffer);
std::stringstream ss;
- ss << "program name:\t" << pfile->m_progname << std::endl;
+ ss << "program name:\t" << pfile->progname() << std::endl;
ss << "trnsltn units:\t" << pfile->m_tus.size() << std::endl;
- ss << "process id:\t" << pfile->m_pid << std::endl;
- ss << "parent pid:\t" << pfile->m_ppid << std::endl;
- ss << "process group:\t" << pfile->m_pgrp << std::endl;
+ ss << "process id:\t" << pfile->getpid() << std::endl;
+ ss << "parent pid:\t" << pfile->getppid() << std::endl;
+ ss << "process group:\t" << pfile->getpgrp() << std::endl;
glyphy_point_t cur_pos = { 0, 0 };
demo_buffer_move_to(buffer, &cur_pos);
@@ -98,7 +98,7 @@ add_new_process(std::string const &file_name)
cur_pos.x = 0;
for (auto &t : pfile->m_tus) {
- demo_buffer_add_text(buffer, t.comp_file_path.c_str(), font, 1);
+ demo_buffer_add_text(buffer, t.comp_file_path().c_str(), font, 1);
}
}
@@ -112,15 +112,15 @@ next_frame(View *vu)
delete new_files;
for (auto &rp : drawables) {
- rp.read_executions();
+ // rp.read_executions();
//glyphy_point_t tmp;
for (auto &t : rp.m_tus) {
//size_t bytes_total = t.num_lines * sizeof(uint64_t);
- for (unsigned int i = 0; i < t.num_lines; i++) {
- if (t.exec_counts[i] == 0)
- continue;
+ for (unsigned int i = 0; i < t.num_lines(); i++) {
+ //if (t.exec_counts[i] == 0)
+ // continue;
// demo_buffer_add_text(buffer, ">>", font, 1);
}
diff --git a/src/process_file.cc b/src/process_file.cc
@@ -18,138 +18,144 @@
#include <cassert>
#include <csignal> // kill
+#include <cstring> // strncmp
#include <err.h>
#include <fcntl.h> // O_RDONLY
#include <fstream>
+#include <iostream>
#include <stdlib.h> // getenv
+#include <string.h> // memcpy
#include <unistd.h> // getpagesize
#include "process_file.h"
+#include "rt.h" // struct citrun_{node,header}
#include "version.h" // citrun_major
-ProcessFile::ProcessFile(std::string const &path) :
- m_path(path),
- m_fd(0),
- m_mem(NULL),
- m_pos(0),
- m_tus_with_execs(0),
- m_program_loc(0)
+//
+// Take a pointer to a shared memory region and map data structures on top.
+// Automatically increments the pointer once we know how big this region is.
+//
+TranslationUnit::TranslationUnit(void* &mem) :
+ m_node(static_cast<struct citrun_node *>(mem)),
+ m_data((unsigned long long *)(m_node + 1)),
+ m_data_buffer(new uint64_t[m_node->size]())
{
- if ((m_fd = open(m_path.c_str(), O_RDONLY, S_IRUSR | S_IWUSR)) < 0)
- err(1, "open");
-
- struct stat sb;
- fstat(m_fd, &sb);
-
- if (sb.st_size > 1024 * 1024 * 1024)
- errx(1, "shared memory too large: %lli", sb.st_size);
-
- m_mem = (uint8_t *)mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, m_fd, 0);
- if (m_mem == MAP_FAILED)
- err(1, "mmap");
-
- m_size = sb.st_size;
-
- std::string magic;
- assert(sizeof(pid_t) == 4);
-
- shm_read_magic(magic);
- assert(magic == "citrun");
- shm_read_all(&m_major);
- assert(m_major == citrun_major);
- shm_read_all(&m_minor);
- shm_read_all(&m_pid);
- shm_read_all(&m_ppid);
- shm_read_all(&m_pgrp);
- shm_read_string(m_progname);
- shm_read_string(m_cwd);
- shm_next_page();
-
- while (shm_at_end() == false) {
- TranslationUnit t;
+ unsigned int size, page_mask;
- shm_read_all(&t.num_lines);
+ // Total size is node size plus live execution data size.
+ size = sizeof(struct citrun_node);
+ size += m_node->size * sizeof(unsigned long long);
- shm_read_string(t.comp_file_path);
- shm_read_string(t.abs_file_path);
+ // Increment passed in pointer to next page.
+ page_mask = getpagesize() - 1;
+ mem = (char *)mem + ((size + page_mask) & ~page_mask);
- t.exec_counts = (uint64_t *)shm_get_block(t.num_lines * 8);
- t.exec_counts_last = new uint64_t[t.num_lines]();
-
- t.source.resize(t.num_lines);
- m_program_loc += t.num_lines;
- read_source(t);
+ read_source();
+}
- m_tus.push_back(t);
+//
+// Returns number of lines that citrun-inst processed (whole source file
+// ideally)
+//
+unsigned int
+TranslationUnit::num_lines() const
+{
+ return m_node->size;
+}
- shm_next_page();
- }
+//
+// Returns the source file path as it was passed to the compiler.
+//
+std::string
+TranslationUnit::comp_file_path() const
+{
+ return std::string(m_node->comp_file_path);
}
+//
+// Try and read the contents of the on disk source file using the absolute path
+// provided by clang/llvm.
+//
void
-ProcessFile::read_source(struct TranslationUnit &t)
+TranslationUnit::read_source()
{
- std::ifstream file_stream(t.abs_file_path);
+ std::ifstream file_stream(m_node->abs_file_path);
if (file_stream.is_open() == 0) {
- warnx("ifstream.open(%s)", t.abs_file_path.c_str());
+ warnx("ifstream.open(%s)", m_node->abs_file_path);
return;
}
- for (auto &l : t.source)
- std::getline(file_stream, l);
+ std::string line;
+ while (std::getline(file_stream, line))
+ m_source.push_back(line);
}
+//
+// Copy live executions to secondary buffer. Used for computing deltas later.
+//
void
-ProcessFile::shm_next_page()
+TranslationUnit::save_executions()
{
- int page_size = getpagesize();
- m_pos += page_size - (m_pos % page_size);
+ memcpy(m_data_buffer, m_data, m_node->size * sizeof(unsigned long long));
}
-void
-ProcessFile::shm_read_magic(std::string &magic)
+
+//
+// Take a filesystem path and memory map its contents. Map at least a header
+// structure on top of it.
+//
+ProcessFile::ProcessFile(std::string const &path) :
+ m_path(path),
+ m_fd(0),
+ m_tus_with_execs(0),
+ m_program_loc(0)
{
- magic.resize(6);
+ struct stat sb;
+ void *mem, *end;
- memcpy(&magic[0], m_mem + m_pos, 6);
- m_pos += 6;
-}
+ if ((m_fd = open(m_path.c_str(), O_RDONLY, S_IRUSR | S_IWUSR)) < 0)
+ err(1, "open");
-void
-ProcessFile::shm_read_string(std::string &str)
-{
- uint16_t len;
+ if (fstat(m_fd, &sb) < 0)
+ err(1, "fstat");
- memcpy(&len, m_mem + m_pos, sizeof(len));
- m_pos += sizeof(len);
+ if (sb.st_size > 1024 * 1024 * 1024)
+ errx(1, "shared memory too large: %lli", sb.st_size);
- str.resize(len);
- memcpy(&str[0], m_mem + m_pos, len);
- m_pos += len;
-}
+ m_size = sb.st_size;
-void *
-ProcessFile::shm_get_block(size_t inc)
-{
- void *block = m_mem + m_pos;
- m_pos += inc;
+ mem = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, m_fd, 0);
+ if (mem == MAP_FAILED)
+ err(1, "mmap");
- return block;
-}
-bool
-ProcessFile::shm_at_end()
-{
- assert(m_pos <= m_size);
- return (m_pos == m_size ? true : false);
+ // Header is always at offset 0 and always one page long.
+ m_header = static_cast<struct citrun_header *>(mem);
+
+ end = (char *)mem + m_size;
+ mem = (char *)mem + getpagesize();
+
+ assert(std::strncmp(m_header->magic, "ctrn", 4) == 0);
+ assert(m_header->major == citrun_major);
+
+ while (mem < end)
+ m_tus.push_back(TranslationUnit(mem));
+ // Make sure internal increment in TranslationUnit works as intended.
+ assert(mem == end);
+
+ for (auto &t : m_tus)
+ m_program_loc += t.num_lines();
}
+//
+// Checks if the pid given by the runtime is alive. Prone to race conditions.
+//
bool
ProcessFile::is_alive() const
{
- if (kill(m_pid, 0) == 0)
+ if (kill(m_header->pids[0], 0) == 0)
return 1;
return 0;
}
@@ -158,19 +164,37 @@ const TranslationUnit *
ProcessFile::find_tu(std::string const &srcname) const
{
for (auto &i : m_tus)
- if (srcname == i.comp_file_path)
+ if (srcname == i.comp_file_path())
return &i;
return NULL;
}
-void
-ProcessFile::save_executions()
+//
+// Return program the runtime is/was running within.
+//
+std::string
+ProcessFile::progname() const
{
- for (auto &t : m_tus)
- memcpy(t.exec_counts_last, t.exec_counts, t.num_lines * 8);
+ return std::string(m_header->progname);
}
-void
-ProcessFile::read_executions()
+//
+// Return the pid, ppid, pgrp the runtime is/was running within.
+//
+int
+ProcessFile::getpid() const
+{
+ return m_header->pids[0];
+}
+
+int
+ProcessFile::getppid() const
+{
+ return m_header->pids[1];
+}
+
+int
+ProcessFile::getpgrp() const
{
+ return m_header->pids[2];
}
diff --git a/src/process_file.h b/src/process_file.h
@@ -1,58 +1,49 @@
#include <string>
-#include <string.h> // memcpy
#include <vector>
-struct TranslationUnit {
- std::vector<std::string> source;
- std::string comp_file_path;
- std::string abs_file_path;
- uint64_t *exec_counts;
- uint64_t *exec_counts_last;
- uint32_t num_lines;
- uint8_t has_execs;
+//
+// Owns a few pages of shared memory that are created by a running instrumented
+// translation unit.
+//
+class TranslationUnit
+{
+ struct citrun_node *m_node;
+ uint64_t *m_data;
+ uint64_t *m_data_buffer;
+
+ std::vector<std::string> m_source;
+
+public:
+ TranslationUnit(void* &);
+
+ std::string comp_file_path() const;
+ unsigned int num_lines() const;
+ void read_source();
+ void save_executions();
};
-class ProcessFile {
-private:
- void read_source(struct TranslationUnit &);
-
- template<typename T>
- void shm_read_all(T *buf)
- {
- memcpy(buf, m_mem + m_pos, sizeof(T));
- m_pos += sizeof(T);
- };
-
- void shm_next_page();
- void shm_read_string(std::string &);
- void shm_read_magic(std::string &);
- void *shm_get_block(size_t);
- bool shm_at_end();
-
- std::string m_path;
- int m_fd;
- uint8_t *m_mem;
- size_t m_pos;
- size_t m_size;
+//
+// Owns an executing/executed instrumented processes shared memory file.
+//
+class ProcessFile
+{
+ struct citrun_header *m_header;
+ std::string m_path;
+ int m_fd;
+ size_t m_size;
+ int m_tus_with_execs;
+ unsigned int m_program_loc;
public:
ProcessFile(std::string const &);
- const TranslationUnit *find_tu(std::string const &) const;
- bool is_alive() const;
- void read_executions();
- void save_executions();
-
- uint8_t m_major;
- uint8_t m_minor;
- std::string m_progname;
- std::string m_cwd;
- uint32_t m_pid;
- uint32_t m_ppid;
- uint32_t m_pgrp;
- std::vector<TranslationUnit> m_tus;
- int m_tus_with_execs;
+ const TranslationUnit *find_tu(std::string const &) const;
+ bool is_alive() const;
+ std::string progname() const;
+ int getpid() const;
+ int getppid() const;
+ int getpgrp() const;
- uint32_t m_program_loc;
+ std::vector<TranslationUnit> m_tus;
};