citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

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:
Mlib/lib.c | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mlib/libP.h | 4++--
Mlib/lib_unix.c | 29+++++++++++++++++++++--------
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)