commit e724aca2a3416b17b9a9a6966c633cd6de951d18
parent 814c6c55a38a388287bc79ef4e2d120ceb13a394
Author: Kyle Milz <kyle@0x30.net>
Date: Sat, 7 Oct 2017 01:54:38 -0600
lib: move `fd` from global visibility to function
Diffstat:
3 files changed, 81 insertions(+), 24 deletions(-)
diff --git a/lib/lib.c b/lib/lib.c
@@ -21,34 +21,77 @@
/*
- * Extends the memory mapping and puts a struct citrun_header on top of it.
+ * The purpose of the instrumentation runtime is to create a file in a well
+ * known location and constantly write counter information to it.
+ *
+ * Once the file is initially created it does not change in size. There is one
+ * `struct citrun_node` per instrumented translation unit. The file is
+ * structured like the following:
+ *
+ * /tmp/citrun/a.out_XXXXXXX:
+ *
+ * +-----------------------+
+ * | struct citrun_header |
+ * | - citrun version |
+ * | - process ids |
+ * | - program name |
+ * | - working directory |
+ * | padding |
+ * +-----------------------+
+ * | struct citrun_node 1 |
+ * | - source file paths |
+ * | - counter buffer | <-- size ~ lines in source file
+ * | padding |
+ * +-----------------------+
+ * | struct citrun_node .. |
+ * | - source file paths |
+ * | - counter buffer |
+ * | padding |
+ * + ----------------------+------
+ * | struct citrun_node N | ^
+ * | - source file paths | |-- sized for efficient memory access
+ * | - counter buffer | |
+ * | padding | v
+ * +-----------------------+------
+ */
+
+/*
+ * Internal function that extends the file descriptor given as the first
+ * argument and fills the extended space with version and runtime information.
+ *
+ * Returns a pointer to the beginning of the extended region on success.
+ * The instrumented program will exit nonzero on failure.
*/
static struct citrun_header *
-citrun_add_header()
+citrun_add_header(int fd)
{
struct citrun_header *new_header;
- new_header = citrun_extend(sizeof(struct citrun_header));
+ new_header = citrun_extend(fd, sizeof(struct citrun_header));
strncpy(new_header->magic, "ctrn", sizeof(new_header->magic));
new_header->major = citrun_major;
new_header->minor = citrun_minor;
- /* Fill in os specific information in header. */
+ /* Fill in various runtime information fields. */
citrun_os_info(new_header);
return new_header;
}
/*
- * Public Interface citrun_node_add.
+ * Public function called by code inserted into each translation unit. Takes a
+ * version major and minor as the first two arguments and a pointer to an
+ * existing `struct citrun_node` as the third argument.
+ *
+ * If the passed version numbers don't exactly match the version numbers this
+ * library was compiled with a runtime error occurs. This means all instrumented
+ * object files must be generated by the same citrun tools.
+ *
+ * The passed in `struct citrun_node` gets its fields copied to the runtime
+ * file, and extra counter buffer space is allocated.
*
- * Create or enlarge memory block backed by file. The first call to this
- * function creates a new memory block with a header.
- * Any call after the first enlarges the memory block with enough storage for:
- * - copying incoming struct citrun_node verbatim
- * - live execution buffers (8 bytes per line of instrumented translation unit)
- * Exits on failure.
+ * Instrumented program will exit nonzero on failure.
*/
void
citrun_node_add(unsigned int major, unsigned int minor, struct citrun_node *n)
@@ -56,6 +99,7 @@ citrun_node_add(unsigned int major, unsigned int minor, struct citrun_node *n)
size_t sz;
struct citrun_node *new;
static struct citrun_header *header = NULL;
+ static int fd = 0;
/* Binary compatibility between versions not guaranteed. */
if (major != citrun_major || minor != citrun_minor) {
@@ -66,14 +110,14 @@ citrun_node_add(unsigned int major, unsigned int minor, struct citrun_node *n)
}
if (header == NULL) {
- citrun_open_fd();
- header = citrun_add_header();
+ fd = citrun_open_fd();
+ header = citrun_add_header(fd);
}
/* Allocate enough room for node and live execution buffers. */
sz = sizeof(struct citrun_node);
sz += n->size * sizeof(unsigned long long);
- new = citrun_extend(sz);
+ new = citrun_extend(fd, sz);
/* Increment accumulation fields in header. */
header->units++;
diff --git a/lib/libP.h b/lib/libP.h
@@ -2,6 +2,6 @@
/*
* Operating system specific functions.
*/
-void *citrun_extend(size_t);
+void *citrun_extend(int, size_t);
void citrun_os_info(struct citrun_header *);
-void citrun_open_fd();
+int citrun_open_fd();
diff --git a/lib/lib_unix.c b/lib/lib_unix.c
@@ -27,15 +27,17 @@
#include "libP.h"
-static int fd;
/*
- * Extends the file and memory mapping length of fd by a requested amount of
- * bytes (rounded up to the next page size).
- * Returns a pointer to the extended region on success, exits on failure.
+ * Extend the length of the file descriptor passed as the first argument, by a
+ * number of bytes (rounded up to a convenient size) given by the second
+ * argument.
+ *
+ * Returns a pointer to the beginning of the extended region on success.
+ * Instrumented program exits nonzero on failure.
*/
void *
-citrun_extend(size_t req_bytes)
+citrun_extend(int fd, size_t req_bytes)
{
size_t aligned_bytes;
off_t len;
@@ -63,13 +65,19 @@ citrun_extend(size_t req_bytes)
}
/*
- * Opens a file with a random suffix. Exits on error.
+ * Opens a new file semi randomly named like "my_program_name_3IcD7HyvoZ".
+ * If the CITRUN_PROCDIR environment variable is set its value is prefixed to
+ * the file name else "/tmp/citrun/" is prefixed.
+ *
+ * Returns a new file descriptor with a unique file system path on success.
+ * Instrumented program exits nonzero on failure.
*/
-void
+int
citrun_open_fd()
{
const char *procdir;
char procfile[PATH_MAX];
+ int fd;
if ((procdir = getenv("CITRUN_PROCDIR")) == NULL)
procdir = "/tmp/citrun";
@@ -84,10 +92,15 @@ citrun_open_fd()
if ((fd = mkstemp(procfile)) < 0)
err(1, "mkstemp");
+
+ return fd;
}
/*
- * Fills in a few operating system specific fields in struct citrun_header.
+ * Takes a pointer to a struct citrun_header and fills in fields related to
+ * process id, program name, and working directory.
+ *
+ * Returns nothing and never fails.
*/
void
citrun_os_info(struct citrun_header *h)